diff --git a/korman/exporter/etlight.py b/korman/exporter/etlight.py index 0f1c428..730248c 100644 --- a/korman/exporter/etlight.py +++ b/korman/exporter/etlight.py @@ -146,12 +146,9 @@ class LightBaker: def _generate_lightgroup(self, bo, user_lg=None): """Makes a new light group for the baking process that excludes all Plasma RT lamps""" - - if user_lg is not None: - user_lg = bpy.data.groups.get(user_lg) shouldibake = (user_lg is not None and bool(user_lg.objects)) - mesh = bo.data + for material in mesh.materials: if material is None: # material is not assigned to this material... (why is this even a thing?) @@ -245,7 +242,7 @@ class LightBaker: uv_textures = mesh.uv_textures # Create a special light group for baking - if not self._generate_lightgroup(bo, modifier.light_group): + if not self._generate_lightgroup(bo, modifier.lights): return False # We need to ensure that we bake onto the "BlahObject_LIGHTMAPGEN" image diff --git a/korman/idprops.py b/korman/idprops.py index 903c54a..f7ea5b2 100644 --- a/korman/idprops.py +++ b/korman/idprops.py @@ -133,5 +133,8 @@ def poll_mesh_objects(self, value): def poll_softvolume_objects(self, value): return value.plasma_modifiers.softvolume.enabled +def poll_visregion_objects(self, value): + return value.plasma_modifiers.visregion.enabled + def poll_envmap_textures(self, value): return isinstance(value, bpy.types.EnvironmentMapTexture) diff --git a/korman/operators/op_lightmap.py b/korman/operators/op_lightmap.py index 5581718..e67e241 100644 --- a/korman/operators/op_lightmap.py +++ b/korman/operators/op_lightmap.py @@ -32,8 +32,6 @@ class LightmapAutobakePreviewOperator(_LightingOperator, bpy.types.Operator): bl_label = "Preview Lightmap" bl_options = {"INTERNAL"} - light_group = StringProperty(name="Light Group") - def __init__(self): super().__init__() diff --git a/korman/properties/modifiers/render.py b/korman/properties/modifiers/render.py index dcad670..cf9247f 100644 --- a/korman/properties/modifiers/render.py +++ b/korman/properties/modifiers/render.py @@ -22,6 +22,7 @@ from .base import PlasmaModifierProperties from ...exporter.etlight import _NUM_RENDER_LAYERS from ...exporter import utils from ...exporter.explosions import ExportError +from ... import idprops class PlasmaFadeMod(PlasmaModifierProperties): @@ -81,7 +82,7 @@ class PlasmaFadeMod(PlasmaModifierProperties): mod.farTrans = self.far_trans -class PlasmaFollowMod(PlasmaModifierProperties): +class PlasmaFollowMod(idprops.IDPropObjectMixin, PlasmaModifierProperties): pl_id = "followmod" bl_category = "Render" @@ -108,8 +109,9 @@ class PlasmaFollowMod(PlasmaModifierProperties): ("kFollowObject", "Object", "Follow an object"), ]) - leader_object = StringProperty(name="Leader Object", - description="Object to follow") + leader = PointerProperty(name="Leader Object", + description="Object to follow", + type=bpy.types.Object) def export(self, exporter, bo, so): fm = exporter.mgr.find_create_object(plFollowMod, so=so, name=self.key_name) @@ -122,21 +124,21 @@ class PlasmaFollowMod(PlasmaModifierProperties): if self.leader_type == "kFollowObject": # If this object is following another object, make sure that the # leader has been selected and is a valid SO. - if self.leader_object: - leader_obj = bpy.data.objects.get(self.leader_object, None) - if leader_obj is None: - raise ExportError("'{}': Follow's leader object is invalid".format(self.key_name)) - else: - fm.leader = exporter.mgr.find_create_key(plSceneObject, bl=leader_obj) + if self.leader: + fm.leader = exporter.mgr.find_create_key(plSceneObject, bl=self.leader) else: raise ExportError("'{}': Follow's leader object must be selected".format(self.key_name)) + @classmethod + def _idprop_mapping(cls): + return {"leader": "leader_object"} + @property def requires_actor(self): return True -class PlasmaLightMapGen(PlasmaModifierProperties): +class PlasmaLightMapGen(idprops.IDPropMixin, PlasmaModifierProperties): pl_id = "lightmap" bl_category = "Render" @@ -159,8 +161,9 @@ class PlasmaLightMapGen(PlasmaModifierProperties): size=_NUM_RENDER_LAYERS, default=((True,) * _NUM_RENDER_LAYERS)) - light_group = StringProperty(name="Light Group", - description="Group that defines the collection of lights to bake") + lights = PointerProperty(name="Light Group", + description="Group that defines the collection of lights to bake", + type=bpy.types.Group) uv_map = StringProperty(name="UV Texture", description="UV Texture used as the basis for the lightmap") @@ -208,6 +211,13 @@ class PlasmaLightMapGen(PlasmaModifierProperties): # Mmm... cheating mat_mgr.export_prepared_layer(layer, lightmap_im) + @classmethod + def _idprop_mapping(cls): + return {"lights": "light_group"} + + def _idprop_sources(self): + return {"light_group": bpy.data.groups} + @property def key_name(self): return "{}_LIGHTMAPGEN".format(self.id_data.name) @@ -317,7 +327,7 @@ class PlasmaShadowCasterMod(PlasmaModifierProperties): caster.castFlags |= plShadowCaster.kSelfShadow -class PlasmaViewFaceMod(PlasmaModifierProperties): +class PlasmaViewFaceMod(idprops.IDPropObjectMixin, PlasmaModifierProperties): pl_id = "viewfacemod" bl_category = "Render" @@ -340,8 +350,9 @@ class PlasmaViewFaceMod(PlasmaModifierProperties): ("kFacePlay", "Player", "Face the local player"), ("kFaceObj", "Object", "Face an object"), ]) - target_object = StringProperty(name="Target Object", - description="Object to face") + target = PointerProperty(name="Target Object", + description="Object to face", + type=bpy.types.Object) pivot_on_y = BoolProperty(name="Pivot on local Y", description="Swivel only around the local Y axis", @@ -376,12 +387,8 @@ class PlasmaViewFaceMod(PlasmaModifierProperties): if self.follow_mode == "kFaceObj": # If this swivel is following an object, make sure that the # target has been selected and is a valid SO. - if self.target_object: - target_obj = bpy.data.objects.get(self.target_object, None) - if target_obj is None: - raise ExportError("'{}': Swivel's target object is invalid".format(self.key_name)) - else: - vfm.faceObj = exporter.mgr.find_create_key(plSceneObject, bl=target_obj) + if self.target: + vfm.faceObj = exporter.mgr.find_create_key(plSceneObject, bl=self.target) else: raise ExportError("'{}': Swivel's target object must be selected".format(self.key_name)) @@ -395,12 +402,16 @@ class PlasmaViewFaceMod(PlasmaModifierProperties): if self.offset_local: vfm.setFlag(plViewFaceModifier.kOffsetLocal, True) + @classmethod + def _idprop_mapping(cls): + return {"target": "target_object"} + @property def requires_actor(self): return True -class PlasmaVisControl(PlasmaModifierProperties): +class PlasmaVisControl(idprops.IDPropObjectMixin, PlasmaModifierProperties): pl_id = "visregion" bl_category = "Render" @@ -412,8 +423,10 @@ class PlasmaVisControl(PlasmaModifierProperties): items=[("normal", "Normal", "Objects are only visible when the camera is inside this region"), ("exclude", "Exclude", "Objects are only visible when the camera is outside this region"), ("fx", "Special FX", "This is a list of objects used for special effects only")]) - softvolume = StringProperty(name="Region", - description="Object defining the SoftVolume for this VisRegion") + soft_region = PointerProperty(name="Region", + description="Object defining the SoftVolume for this VisRegion", + type=bpy.types.Object, + poll=idprops.poll_softvolume_objects) replace_normal = BoolProperty(name="Hide Drawables", description="Hides drawables attached to this region", default=True) @@ -430,21 +443,31 @@ class PlasmaVisControl(PlasmaModifierProperties): exporter.report.msg("[VisRegion] I'm a SoftVolume myself :)", indent=1) rgn.region = this_sv.get_key(exporter, so) else: - exporter.report.msg("[VisRegion] SoftVolume '{}'", self.softvolume, indent=1) - sv_bo = bpy.data.objects.get(self.softvolume, None) - if sv_bo is None: - raise ExportError("'{}': Invalid object '{}' for VisControl soft volume".format(bo.name, self.softvolume)) + if not self.soft_region: + raise ExportError("'{}': Visibility Control must have a Soft Volume selected".format(self.key_name)) + sv_bo = self.soft_region sv = sv_bo.plasma_modifiers.softvolume + exporter.report.msg("[VisRegion] SoftVolume '{}'", sv_bo.name, indent=1) if not sv.enabled: - raise ExportError("'{}': '{}' is not a SoftVolume".format(bo.name, self.softvolume)) + raise ExportError("'{}': '{}' is not a SoftVolume".format(self.key_name, sv_bo.name)) rgn.region = sv.get_key(exporter) rgn.setProperty(plVisRegion.kIsNot, self.mode == "exclude") + @classmethod + def _idprop_mapping(cls): + return {"soft_region": "softvolume"} + -class VisRegion(bpy.types.PropertyGroup): +class VisRegion(idprops.IDPropObjectMixin, bpy.types.PropertyGroup): enabled = BoolProperty(default=True) - region_name = StringProperty(name="Control", - description="Object defining a Plasma Visibility Control") + control_region = PointerProperty(name="Control", + description="Object defining a Plasma Visibility Control", + type=bpy.types.Object, + poll=idprops.poll_visregion_objects) + + @classmethod + def _idprop_mapping(cls): + return {"control_region": "region_name"} class PlasmaVisibilitySet(PlasmaModifierProperties): @@ -474,7 +497,6 @@ class PlasmaVisibilitySet(PlasmaModifierProperties): for region in self.regions: if not region.enabled: continue - rgn_bo = bpy.data.objects.get(region.region_name, None) - if rgn_bo is None: - raise ExportError("{}: Invalid VisControl '{}' in VisSet modifier".format(bo.name, region.region_name)) - addRegion(exporter.mgr.find_create_key(plVisRegion, bl=rgn_bo)) + if not region.control_region: + raise ExportError("{}: Not all Visibility Controls are set up properly in Visibility Set".format(bo.name)) + addRegion(exporter.mgr.find_create_key(plVisRegion, bl=region.control_region)) diff --git a/korman/ui/modifiers/render.py b/korman/ui/modifiers/render.py index 5020a54..f097f66 100644 --- a/korman/ui/modifiers/render.py +++ b/korman/ui/modifiers/render.py @@ -43,7 +43,7 @@ def followmod(modifier, layout, context): layout.row().prop(modifier, "follow_mode", expand=True) layout.prop(modifier, "leader_type") if modifier.leader_type == "kFollowObject": - layout.prop_search(modifier, "leader_object", bpy.data, "objects", icon="OUTLINER_OB_MESH") + layout.prop(modifier, "leader", icon="OUTLINER_OB_MESH") def lighting(modifier, layout, context): split = layout.split() @@ -84,11 +84,10 @@ def lighting(modifier, layout, context): def lightmap(modifier, layout, context): layout.row(align=True).prop(modifier, "quality", expand=True) layout.prop(modifier, "render_layers", text="Active Render Layers") - layout.prop_search(modifier, "light_group", bpy.data, "groups", icon="GROUP") + layout.prop(modifier, "lights") layout.prop_search(modifier, "uv_map", context.active_object.data, "uv_textures") operator = layout.operator("object.plasma_lightmap_preview", "Preview Lightmap", icon="RENDER_STILL") - operator.light_group = modifier.light_group # Kind of clever stuff to show the user a preview... # We can't show images, so we make a hidden ImageTexture called LIGHTMAPGEN_PREVIEW. We check @@ -117,7 +116,7 @@ def viewfacemod(modifier, layout, context): if modifier.preset_options == "Custom": layout.row().prop(modifier, "follow_mode") if modifier.follow_mode == "kFaceObj": - layout.prop_search(modifier, "target_object", bpy.data, "objects", icon="OUTLINER_OB_MESH") + layout.prop(modifier, "target", icon="OUTLINER_OB_MESH") layout.separator() layout.prop(modifier, "pivot_on_y") @@ -136,9 +135,10 @@ def viewfacemod(modifier, layout, context): class VisRegionListUI(bpy.types.UIList): def draw_item(self, context, layout, data, item, icon, active_data, active_property, index=0, flt_flag=0): - myIcon = "ERROR" if bpy.data.objects.get(item.region_name, None) is None else "OBJECT_DATA" - label = item.region_name if item.region_name else "[No Object Specified]" - layout.label(label, icon=myIcon) + if item.control_region is None: + layout.label("[No Object Specified]", icon="ERROR") + else: + layout.label(item.control_region.name, icon="OBJECT_DATA") layout.prop(item, "enabled", text="") @@ -156,7 +156,7 @@ def visibility(modifier, layout, context): op.index = modifier.active_region_index if modifier.regions: - layout.prop_search(modifier.regions[modifier.active_region_index], "region_name", bpy.data, "objects") + layout.prop(modifier.regions[modifier.active_region_index], "control_region") def visregion(modifier, layout, context): layout.prop(modifier, "mode") @@ -164,7 +164,7 @@ def visregion(modifier, layout, context): # Only allow SoftVolume spec if this is not an FX and this object is not an SV itself sv = modifier.id_data.plasma_modifiers.softvolume if modifier.mode != "fx" and not sv.enabled: - layout.prop_search(modifier, "softvolume", bpy.data, "objects") + layout.prop(modifier, "soft_region") # Other settings layout.prop(modifier, "replace_normal")