Browse Source

Rework camera UI to not be so monolithic

pull/105/head
Adam Johnson 6 years ago
parent
commit
1ca9456870
Signed by: Hoikas
GPG Key ID: 0B6515D6FF6F271E
  1. 5
      korman/exporter/camera.py
  2. 17
      korman/properties/prop_camera.py
  3. 4
      korman/render.py
  4. 23
      korman/ui/modifiers/region.py
  5. 256
      korman/ui/ui_camera.py

5
korman/exporter/camera.py

@ -140,7 +140,8 @@ class CameraConverter:
return brain return brain
def _export_fixed_camera(self, so, bo, props): def _export_fixed_camera(self, so, bo, props):
self._exporter().animation.convert_object_animations(bo, so) if props.anim_enabled:
self._exporter().animation.convert_object_animations(bo, so)
brain = self._mgr.find_create_object(plCameraBrain1_Fixed, so=so) brain = self._mgr.find_create_object(plCameraBrain1_Fixed, so=so)
self._convert_brain(so, bo, props, brain) self._convert_brain(so, bo, props, brain)
return brain return brain
@ -185,6 +186,8 @@ class CameraConverter:
else: else:
# The animation is a loop # The animation is a loop
path.flags |= plAnimPath.kWrap path.flags |= plAnimPath.kWrap
if props.rail_pos == "farthest":
path.flags |= plAnimPath.kFarthest
path.length = end / bpy.context.scene.render.fps path.length = end / bpy.context.scene.render.fps
rail.path = path rail.path = path
brain.rail = rail.key brain.rail = rail.key

17
korman/properties/prop_camera.py

@ -159,8 +159,8 @@ class PlasmaCameraProperties(bpy.types.PropertyGroup):
options=set()) options=set())
circle_pos = EnumProperty(name="Position on Circle", circle_pos = EnumProperty(name="Position on Circle",
description="The point on the circle the camera moves to", description="The point on the circle the camera moves to",
items=[("closest", "Closest Point", "The camera moves to point on the circle closest to the Point of Attention"), items=[("closest", "Closest Point", "The camera moves to the point on the circle closest to the Point of Attention"),
("farthest", "Farthest Point", "The point farthest from the Point of Attention")], ("farthest", "Farthest Point", "The camera moves to the point on the circle farthest from the Point of Attention")],
options=set()) options=set())
circle_velocity = FloatProperty(name="Velocity", circle_velocity = FloatProperty(name="Velocity",
description="Velocity of the circle camera in degrees per second", description="Velocity of the circle camera in degrees per second",
@ -174,16 +174,29 @@ class PlasmaCameraProperties(bpy.types.PropertyGroup):
min=0.0, default=8.5, options={"HIDDEN"}) min=0.0, default=8.5, options={"HIDDEN"})
# Animation # Animation
anim_enabled = BoolProperty(name="Animation Enabled",
description="Export the camera's animation",
default=True,
options=set())
start_on_push = BoolProperty(name="Start on Push", start_on_push = BoolProperty(name="Start on Push",
description="Start playing the camera's animation when the camera is activated", description="Start playing the camera's animation when the camera is activated",
default=True,
options=set()) options=set())
stop_on_pop = BoolProperty(name="Pause on Pop", stop_on_pop = BoolProperty(name="Pause on Pop",
description="Pauses the camera's animation when the camera is no longer activated", description="Pauses the camera's animation when the camera is no longer activated",
default=True,
options=set()) options=set())
reset_on_pop = BoolProperty(name="Reset on Pop", reset_on_pop = BoolProperty(name="Reset on Pop",
description="Reset the camera's animation to the beginning when the camera is no longer activated", description="Reset the camera's animation to the beginning when the camera is no longer activated",
options=set()) options=set())
# Rail
rail_pos = EnumProperty(name="Position on Rail",
description="The point on the rail the camera moves to",
items=[("closest", "Closest Point", "The camera moves to the point on the rail closest to the Point of Attention"),
("farthest", "Farthest Point", "The camera moves to the point on the rail farthest from the Point of Attention")],
options=set())
def get_circle_radius(self, bo): def get_circle_radius(self, bo):
"""Gets the circle camera radius for this camera when it is attached to the given Object""" """Gets the circle camera radius for this camera when it is attached to the given Object"""
assert bo is not None assert bo is not None

4
korman/render.py

@ -36,10 +36,6 @@ properties_material.MATERIAL_PT_transp.COMPAT_ENGINES.add("PLASMA_GAME")
properties_material.MATERIAL_PT_shadow.COMPAT_ENGINES.add("PLASMA_GAME") properties_material.MATERIAL_PT_shadow.COMPAT_ENGINES.add("PLASMA_GAME")
del properties_material del properties_material
from bl_ui import properties_data_camera
properties_data_camera.DATA_PT_context_camera.COMPAT_ENGINES.add("PLASMA_GAME")
del properties_data_camera
from bl_ui import properties_data_mesh from bl_ui import properties_data_mesh
properties_data_mesh.DATA_PT_uv_texture.COMPAT_ENGINES.add("PLASMA_GAME") properties_data_mesh.DATA_PT_uv_texture.COMPAT_ENGINES.add("PLASMA_GAME")
properties_data_mesh.DATA_PT_vertex_colors.COMPAT_ENGINES.add("PLASMA_GAME") properties_data_mesh.DATA_PT_vertex_colors.COMPAT_ENGINES.add("PLASMA_GAME")

23
korman/ui/modifiers/region.py

@ -14,14 +14,33 @@
# along with Korman. If not, see <http://www.gnu.org/licenses/>. # along with Korman. If not, see <http://www.gnu.org/licenses/>.
import bpy import bpy
from ..ui_camera import draw_camera_properties from .. import ui_camera
def camera_rgn(modifier, layout, context): def camera_rgn(modifier, layout, context):
layout.prop(modifier, "camera_type") layout.prop(modifier, "camera_type")
if modifier.camera_type == "manual": if modifier.camera_type == "manual":
layout.prop(modifier, "camera_object", icon="CAMERA_DATA") layout.prop(modifier, "camera_object", icon="CAMERA_DATA")
else: else:
draw_camera_properties("follow", modifier.auto_camera, layout, context, True) cam_type = modifier.camera_type[5:]
cam_props = modifier.auto_camera
def _draw_props(layout, cb):
for i in cb:
layout.separator()
i(layout, cam_type, cam_props)
def _draw_circle_cam_props(layout, cam_type, props):
# needs a sublayout that we can deactivate because the ui_camera
# version assumes we are most definitely a circle camera...
col = layout.column()
col.active = cam_type == "circle"
col.label("Circle Camera:")
ui_camera.draw_circle_camera_props(col, props)
_draw_props(layout, (ui_camera.draw_camera_mode_props,
ui_camera.draw_camera_poa_props,
ui_camera.draw_camera_pos_props,
ui_camera.draw_camera_manipulation_props,
_draw_circle_cam_props))
def footstep(modifier, layout, context): def footstep(modifier, layout, context):
layout.prop(modifier, "bounds") layout.prop(modifier, "bounds")

256
korman/ui/ui_camera.py

@ -14,69 +14,45 @@
# along with Korman. If not, see <http://www.gnu.org/licenses/>. # along with Korman. If not, see <http://www.gnu.org/licenses/>.
import bpy import bpy
from .. import helpers
def _draw_alert_prop(layout, props, the_prop, cam_type, alert_cam="", min=None, max=None, **kwargs):
can_alert = not alert_cam or alert_cam == cam_type
if can_alert:
value = getattr(props, the_prop)
if min is not None and value < min:
layout.alert = True
if max is not None and value > max:
layout.alert = True
layout.prop(props, the_prop, **kwargs)
layout.alert = False
else:
layout.prop(props, the_prop, **kwargs)
def _draw_gated_prop(layout, props, gate_prop, actual_prop):
row = layout.row(align=True)
row.prop(props, gate_prop, text="")
row = row.row(align=True)
row.active = getattr(props, gate_prop)
row.prop(props, actual_prop)
def draw_camera_manipulation_props(layout, cam_type, props):
# Camera Panning
split = layout.split()
col = split.column()
col.label("Limit Panning:")
col.prop(props, "x_pan_angle")
col.prop(props, "y_pan_angle")
class CameraButtonsPanel: # Camera Zoom
bl_space_type = "PROPERTIES" col = split.column()
bl_region_type = "WINDOW" col.label("Field of View:")
bl_context = "data" col.prop(props, "fov")
_draw_gated_prop(col, props, "limit_zoom", "zoom_min")
@classmethod _draw_gated_prop(col, props, "limit_zoom", "zoom_max")
def poll(cls, context): _draw_gated_prop(col, props, "limit_zoom", "zoom_rate")
return (context.camera and context.scene.render.engine == "PLASMA_GAME")
class PlasmaCameraPanel(CameraButtonsPanel, bpy.types.Panel):
bl_label = "Plasma Camera"
def draw(self, context):
camera = context.camera.plasma_camera
layout = self.layout
layout.prop(camera, "camera_type")
layout.separator()
draw_camera_properties(camera.camera_type, camera.settings, layout, context)
class PlasmaCameraTransitionPanel(CameraButtonsPanel, bpy.types.Panel):
bl_label = "Plasma Transitions"
def draw(self, context):
pass
def draw_camera_properties(cam_type, props, layout, context, force_no_anim=False):
trans = props.transition
def _draw_alert_prop(layout, props, the_prop, cam="", min=None, max=None, **kwargs):
can_alert = not cam or cam == cam_type
if can_alert:
value = getattr(props, the_prop)
if min is not None and value < min:
layout.alert = True
if max is not None and value > max:
layout.alert = True
layout.prop(props, the_prop, **kwargs)
layout.alert = False
else:
layout.prop(props, the_prop, **kwargs)
def _draw_gated_prop(layout, props, gate_prop, actual_prop):
row = layout.row(align=True)
row.prop(props, gate_prop, text="")
row = row.row(align=True)
row.active = getattr(props, gate_prop)
row.prop(props, actual_prop)
def _is_camera_animated(cam_type, props, context, force_no_anim):
if force_no_anim or cam_type == "rail":
return False
# Check for valid animation data on either the object or the camera
# TODO: Should probably check for valid FCurve channels at some point???
for i in (props.id_data, context.object):
if i.animation_data is None:
continue
if i.animation_data.action is not None:
return True
return False
def draw_camera_mode_props(layout, cam_type, props):
# Point of Attention # Point of Attention
split = layout.split() split = layout.split()
col = split.column() col = split.column()
@ -99,8 +75,10 @@ def draw_camera_properties(cam_type, props, layout, context, force_no_anim=False
col.prop(props, "fast_run") col.prop(props, "fast_run")
col.prop(props, "ignore_subworld") col.prop(props, "ignore_subworld")
def draw_camera_poa_props(layout, cam_type, props):
trans = props.transition
# PoA Tracking # PoA Tracking
layout.separator()
split = layout.split() split = layout.split()
col = split.column() col = split.column()
col.label("Default Tracking Transition:") col.label("Default Tracking Transition:")
@ -115,17 +93,22 @@ def draw_camera_properties(cam_type, props, layout, context, force_no_anim=False
col.prop(props, "poa_offset", text="") col.prop(props, "poa_offset", text="")
col.prop(props, "poa_worldspace") col.prop(props, "poa_worldspace")
def draw_camera_pos_props(layout, cam_type, props):
trans = props.transition
# Position Tracking (only for follow cams) # Position Tracking (only for follow cams)
layout.separator()
split = layout.split() split = layout.split()
col = split.column() col = split.column()
# Position Transitions # Position Transitions
col.active = cam_type != "circle" col.active = cam_type != "circle"
col.label("Default Position Transition:") col.label("Default Position Transition:")
_draw_alert_prop(col, trans, "pos_acceleration", cam="rail", max=10.0, text="Acceleration") _draw_alert_prop(col, trans, "pos_acceleration", cam_type,
_draw_alert_prop(col, trans, "pos_deceleration", cam="rail", max=10.0, text="Deceleration") alert_cam="rail", max=10.0, text="Acceleration")
_draw_alert_prop(col, trans, "pos_velocity", cam="rail", max=10.0, text="Maximum Velocity") _draw_alert_prop(col, trans, "pos_deceleration", cam_type,
alert_cam="rail", max=10.0, text="Deceleration")
_draw_alert_prop(col, trans, "pos_velocity", cam_type,
alert_cam="rail", max=10.0, text="Maximum Velocity")
col.prop(trans, "pos_cut") col.prop(trans, "pos_cut")
# Position Offsets # Position Offsets
@ -135,39 +118,116 @@ def draw_camera_properties(cam_type, props, layout, context, force_no_anim=False
col.prop(props, "pos_offset", text="") col.prop(props, "pos_offset", text="")
col.prop(props, "pos_worldspace") col.prop(props, "pos_worldspace")
# Camera Panning def draw_circle_camera_props(layout, props):
layout.separator()
split = layout.split()
col = split.column()
col.label("Limit Panning:")
col.prop(props, "x_pan_angle")
col.prop(props, "y_pan_angle")
# Camera Zoom
col = split.column()
col.label("Field of View:")
col.prop(props, "fov")
_draw_gated_prop(col, props, "limit_zoom", "zoom_min")
_draw_gated_prop(col, props, "limit_zoom", "zoom_max")
_draw_gated_prop(col, props, "limit_zoom", "zoom_rate")
# Circle Camera Stuff # Circle Camera Stuff
layout.separator() layout.prop(props, "circle_center")
split = layout.split() layout.prop(props, "circle_pos")
col = split.column() layout.prop(props, "circle_velocity")
col.active = cam_type == "circle" row = layout.row(align=True)
col.label("Circle Camera:")
col.prop(props, "circle_center", text="")
col.prop(props, "circle_pos", text="")
col.prop(props, "circle_velocity")
row = col.row(align=True)
row.active = props.circle_center is None row.active = props.circle_center is None
row.prop(props, "circle_radius_ui") row.prop(props, "circle_radius_ui")
# Animated Camera Stuff class CameraButtonsPanel:
col = split.column() bl_space_type = "PROPERTIES"
col.active = _is_camera_animated(cam_type, props, context, force_no_anim) bl_region_type = "WINDOW"
col.label("Animation:") bl_context = "data"
col.prop(props, "start_on_push")
col.prop(props, "stop_on_pop") @classmethod
col.prop(props, "reset_on_pop") def poll(cls, context):
return (context.camera and context.scene.render.engine == "PLASMA_GAME")
class PlasmaCameraTypePanel(CameraButtonsPanel, bpy.types.Panel):
bl_label = ""
bl_options = {"HIDE_HEADER"}
def draw(self, context):
camera = context.camera.plasma_camera
self.layout.prop(camera, "camera_type")
class PlasmaCameraModePanel(CameraButtonsPanel, bpy.types.Panel):
bl_label = "Camera Tracking"
def draw(self, context):
camera = context.camera.plasma_camera
draw_camera_mode_props(self.layout, camera.camera_type, camera.settings)
class PlasmaCameraAttentionPanel(CameraButtonsPanel, bpy.types.Panel):
bl_label = "Point of Attention Tracking"
def draw(self, context):
camera = context.camera.plasma_camera
draw_camera_poa_props(self.layout, camera.camera_type, camera.settings)
class PlasmaCameraPositionPanel(CameraButtonsPanel, bpy.types.Panel):
bl_label = "Position Tracking"
def draw(self, context):
camera = context.camera.plasma_camera
draw_camera_pos_props(self.layout, camera.camera_type, camera.settings)
class PlasmaCameraCirclePanel(CameraButtonsPanel, bpy.types.Panel):
bl_label = "Circle Camera"
def draw(self, context):
camera = context.camera.plasma_camera
draw_circle_camera_props(self.layout, camera.settings)
@classmethod
def poll(cls, context):
return super().poll(context) and context.camera.plasma_camera.camera_type == "circle"
class PlasmaCameraAnimationPanel(CameraButtonsPanel, bpy.types.Panel):
bl_label = "Camera Animation"
bl_options = {"DEFAULT_CLOSED"}
def draw(self, context):
layout = self.layout
camera = context.camera.plasma_camera
props = camera.settings
split = layout.split()
col = split.column()
col.label("Animation:")
col.active = props.anim_enabled and any(helpers.fetch_fcurves(context.object))
col.prop(props, "start_on_push")
col.prop(props, "stop_on_pop")
col.prop(props, "reset_on_pop")
col = split.column()
col.active = camera.camera_type == "rail"
col.label("Rail:")
col.prop(props, "rail_pos", text="")
def draw_header(self, context):
self.layout.active = any(helpers.fetch_fcurves(context.object))
self.layout.prop(context.camera.plasma_camera.settings, "anim_enabled", text="")
class PlasmaCameraViewPanel(CameraButtonsPanel, bpy.types.Panel):
bl_label = "Camera Lens"
def draw(self, context):
camera = context.camera.plasma_camera
draw_camera_manipulation_props(self.layout, camera.camera_type, camera.settings)
class TransitionListUI(bpy.types.UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_property, index=0, flt_flag=0):
if item.camera is None:
layout.label("[Default Transition]")
else:
layout.label(item.camera.name, icon="CAMERA_DATA")
layout.prop(item, "enabled", text="")
class PlasmaCameraTransitionPanel(CameraButtonsPanel, bpy.types.Panel):
bl_label = "Transitions"
def draw(self, context):
pass

Loading…
Cancel
Save