diff --git a/korman/operators/__init__.py b/korman/operators/__init__.py
index 94b352f..006053c 100644
--- a/korman/operators/__init__.py
+++ b/korman/operators/__init__.py
@@ -19,8 +19,8 @@ from . import op_mesh as mesh
from . import op_modifier as modifier
from . import op_nodes as nodes
from . import op_sound as sound
-from . import op_texture as texture
from . import op_toolbox as toolbox
+from . import op_ui as ui
from . import op_world as world
def register():
diff --git a/korman/operators/op_modifier.py b/korman/operators/op_modifier.py
index f640bfc..82292c2 100644
--- a/korman/operators/op_modifier.py
+++ b/korman/operators/op_modifier.py
@@ -233,44 +233,3 @@ class ModifierLogicWizOperator(ModifierOperator, bpy.types.Operator):
end = time.process_time()
print("\nLogicWiz finished in {:.2f} seconds".format(end-start))
return {"FINISHED"}
-
-
-class ModifierCollectionAddOperator(ModifierOperator, bpy.types.Operator):
- bl_idname = "object.plasma_modifier_collection_add"
- bl_label = "Add Item"
- bl_description = "Adds an item to the collection"
-
- modifier = StringProperty(name="Modifier", description="Attribute name of the Plasma Modifier")
- collection = StringProperty(name="Collection", description="Attribute name of the collection property")
- name_prefix = StringProperty(name="Name Prefix", description="Prefix for autogenerated item names", default="Item")
- name_prop = StringProperty(name="Name Property", description="Attribute name of the item name property")
-
- def execute(self, context):
- obj = context.active_object
- mod = getattr(obj.plasma_modifiers, self.modifier)
- collection = getattr(mod, self.collection)
- idx = len(collection)
- collection.add()
- if self.name_prop:
- setattr(collection[idx], self.name_prop, "{} {}".format(self.name_prefix, idx+1))
- return {"FINISHED"}
-
-
-class ModifierCollectionRemoveOperator(ModifierOperator, bpy.types.Operator):
- bl_idname = "object.plasma_modifier_collection_remove"
- bl_label = "Remove Item"
- bl_description = "Removes an item from the collection"
-
- modifier = StringProperty(name="Modifier", description="Attribute name of the Plasma Modifier")
- collection = StringProperty(name="Collection", description="Attribute name of the collection property")
- index = IntProperty(name="Index", description="Item index to remove")
-
- def execute(self, context):
- obj = context.active_object
- mod = getattr(obj.plasma_modifiers, self.modifier)
- collection = getattr(mod, self.collection)
- if len(collection) > self.index:
- collection.remove(self.index)
- return {"FINISHED"}
- else:
- return {"CANCELLED"}
diff --git a/korman/operators/op_texture.py b/korman/operators/op_texture.py
deleted file mode 100644
index 86d5391..0000000
--- a/korman/operators/op_texture.py
+++ /dev/null
@@ -1,61 +0,0 @@
-# This file is part of Korman.
-#
-# Korman is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Korman is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Korman. If not, see .
-
-import bpy
-from bpy.props import *
-
-class TextureOperator:
- @classmethod
- def poll(cls, context):
- return context.scene.render.engine == "PLASMA_GAME" and context.texture
-
-
-class TextureCollectionAddOperator(TextureOperator, bpy.types.Operator):
- bl_idname = "texture.plasma_collection_add"
- bl_label = "Add Item"
- bl_description = "Adds an item to the collection"
-
- group = StringProperty(name="Modifier", description="Attribute name of the PropertyGroup")
- collection = StringProperty(name="Collection", description="Attribute name of the collection property")
- name_prefix = StringProperty(name="Name Prefix", description="Prefix for autogenerated item names", default="Item")
- name_prop = StringProperty(name="Name Property", description="Attribute name of the item name property")
-
- def execute(self, context):
- mod = getattr(context.texture, self.group)
- collection = getattr(mod, self.collection)
- idx = len(collection)
- collection.add()
- if self.name_prop:
- setattr(collection[idx], self.name_prop, "{} {}".format(self.name_prefix, idx+1))
- return {"FINISHED"}
-
-
-class TextureCollectionRemoveOperator(TextureOperator, bpy.types.Operator):
- bl_idname = "texture.plasma_collection_remove"
- bl_label = "Remove Item"
- bl_description = "Removes an item from the collection"
-
- group = StringProperty(name="Modifier", description="Attribute name of the PropertyGroup")
- collection = StringProperty(name="Collection", description="Attribute name of the collection property")
- index = IntProperty(name="Index", description="Item index to remove")
-
- def execute(self, context):
- mod = getattr(context.texture, self.group)
- collection = getattr(mod, self.collection)
- if len(collection) > self.index:
- collection.remove(self.index)
- return {"FINISHED"}
- else:
- return {"CANCELLED"}
diff --git a/korman/operators/op_ui.py b/korman/operators/op_ui.py
new file mode 100644
index 0000000..0f23da4
--- /dev/null
+++ b/korman/operators/op_ui.py
@@ -0,0 +1,89 @@
+# This file is part of Korman.
+#
+# Korman is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Korman is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Korman. If not, see .
+
+import bpy
+from bpy.props import *
+
+class UIOperator:
+ @classmethod
+ def poll(cls, context):
+ return context.scene.render.engine == "PLASMA_GAME"
+
+
+class CollectionAddOperator(UIOperator, bpy.types.Operator):
+ bl_idname = "ui.plasma_collection_add"
+ bl_label = "Add Item"
+ bl_description = "Adds an item to the collection"
+
+ context = StringProperty(name="ID Path",
+ description="Path to the relevant datablock from the current context",
+ options=set())
+ group_path = StringProperty(name="Property Group Path",
+ description="Path to the property group from the ID",
+ options=set())
+ collection_prop = StringProperty(name="Collection Property",
+ description="Name of the collection property",
+ options=set())
+ index_prop = StringProperty(name="Index Property",
+ description="Name of the active element index property",
+ options=set())
+ name_prefix = StringProperty(name="Name Prefix",
+ description="Prefix for autogenerated item names",
+ default="Item",
+ options=set())
+ name_prop = StringProperty(name="Name Property",
+ description="Attribute name of the item name property",
+ options=set())
+
+ def execute(self, context):
+ props = getattr(context, self.context).path_resolve(self.group_path)
+ collection = getattr(props, self.collection_prop)
+ idx = len(collection)
+ collection.add()
+ if self.name_prop:
+ setattr(collection[idx], self.name_prop, "{} {}".format(self.name_prefix, idx+1))
+ if self.index_prop:
+ setattr(props, self.index_prop, idx)
+ return {"FINISHED"}
+
+
+class CollectionRemoveOperator(UIOperator, bpy.types.Operator):
+ bl_idname = "ui.plasma_collection_remove"
+ bl_label = "Remove Item"
+ bl_description = "Removes an item from the collection"
+
+ context = StringProperty(name="ID Path",
+ description="Path to the relevant datablock from the current context",
+ options=set())
+ group_path = StringProperty(name="Property Group Path",
+ description="Path to the property group from the ID",
+ options=set())
+ collection_prop = StringProperty(name="Collection Property",
+ description="Name of the collection property",
+ options=set())
+ index_prop = StringProperty(name="Index Property",
+ description="Name of the active element index property",
+ options=set())
+
+ def execute(self, context):
+ props = getattr(context, self.context).path_resolve(self.group_path)
+ collection = getattr(props, self.collection_prop)
+ index = getattr(props, self.index_prop)
+ if len(collection) > index:
+ collection.remove(index)
+ setattr(props, self.index_prop, index - 1)
+ return {"FINISHED"}
+ else:
+ return {"CANCELLED"}
diff --git a/korman/ui/__init__.py b/korman/ui/__init__.py
index c334f8a..c1f3e3f 100644
--- a/korman/ui/__init__.py
+++ b/korman/ui/__init__.py
@@ -14,6 +14,7 @@
# along with Korman. If not, see .
from .ui_lamp import *
+from .ui_list import *
from .ui_menus import *
from .ui_modifiers import *
from .ui_object import *
diff --git a/korman/ui/modifiers/anim.py b/korman/ui/modifiers/anim.py
index 681e43a..5216dda 100644
--- a/korman/ui/modifiers/anim.py
+++ b/korman/ui/modifiers/anim.py
@@ -15,6 +15,8 @@
import bpy
+from .. import ui_list
+
def _check_for_anim(layout, modifier):
try:
action = modifier.blender_action
@@ -67,18 +69,8 @@ def animation_group(modifier, layout, context):
if action is None:
return
- row = layout.row()
- row.template_list("GroupListUI", "children", modifier, "children", modifier, "active_child_index",
- rows=3, maxrows=4)
- col = row.column(align=True)
- op = col.operator("object.plasma_modifier_collection_add", icon="ZOOMIN", text="")
- op.modifier = modifier.pl_id
- op.collection = "children"
- op = col.operator("object.plasma_modifier_collection_remove", icon="ZOOMOUT", text="")
- op.modifier = modifier.pl_id
- op.collection = "children"
- op.index = modifier.active_child_index
-
+ ui_list.draw_modifier_list(layout, "GroupListUI", modifier, "children",
+ "active_child_index", rows=3, maxrows=4)
if modifier.children:
layout.prop(modifier.children[modifier.active_child_index], "child_anim", icon="ACTION")
@@ -96,20 +88,9 @@ def animation_loop(modifier, layout, context):
elif action is None:
return
- row = layout.row()
- row.template_list("LoopListUI", "loops", modifier, "loops", modifier, "active_loop_index",
- rows=2, maxrows=3)
- col = row.column(align=True)
- op = col.operator("object.plasma_modifier_collection_add", icon="ZOOMIN", text="")
- op.modifier = modifier.pl_id
- op.collection = "loops"
- op.name_prefix = "Loop"
- op.name_prop = "loop_name"
- op = col.operator("object.plasma_modifier_collection_remove", icon="ZOOMOUT", text="")
- op.modifier = modifier.pl_id
- op.collection = "loops"
- op.index = modifier.active_loop_index
-
+ ui_list.draw_modifier_list(layout, "LoopListUI", modifier, "loops",
+ "active_loop_index", name_prefix="Loop",
+ name_prop="loop_name", rows=2, maxrows=3)
# Modify the loop points
if modifier.loops:
loop = modifier.loops[modifier.active_loop_index]
diff --git a/korman/ui/modifiers/logic.py b/korman/ui/modifiers/logic.py
index c96f675..2a789a1 100644
--- a/korman/ui/modifiers/logic.py
+++ b/korman/ui/modifiers/logic.py
@@ -15,27 +15,19 @@
import bpy
+from .. import ui_list
+
class LogicListUI(bpy.types.UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_property, index=0, flt_flag=0):
layout.prop(item, "name", emboss=False, text="", icon="NODETREE")
def advanced_logic(modifier, layout, context):
- row = layout.row()
- row.template_list("LogicListUI", "logic_groups", modifier, "logic_groups", modifier, "active_group_index",
- rows=2, maxrows=3)
- col = row.column(align=True)
- op = col.operator("object.plasma_modifier_collection_add", icon="ZOOMIN", text="")
- op.modifier = modifier.pl_id
- op.collection = "logic_groups"
- op.name_prefix = "Logic"
- op.name_prop = "name"
- op = col.operator("object.plasma_modifier_collection_remove", icon="ZOOMOUT", text="")
- op.modifier = modifier.pl_id
- op.collection = "logic_groups"
- op.index = modifier.active_group_index
-
- # Modify the loop points
+ ui_list.draw_modifier_list(layout, "LogicListUI", modifier, "logic_groups",
+ "active_group_index", name_prefix="Logic",
+ name_prop="name", rows=2, maxrows=3)
+
+ # Modify the logic groups
if modifier.logic_groups:
logic = modifier.logic_groups[modifier.active_group_index]
layout.row().prop_menu_enum(logic, "version")
diff --git a/korman/ui/modifiers/render.py b/korman/ui/modifiers/render.py
index be79b78..df55ee4 100644
--- a/korman/ui/modifiers/render.py
+++ b/korman/ui/modifiers/render.py
@@ -15,6 +15,8 @@
import bpy
+from .. import ui_list
+
def fademod(modifier, layout, context):
layout.prop(modifier, "fader_type")
@@ -147,17 +149,8 @@ class VisRegionListUI(bpy.types.UIList):
def visibility(modifier, layout, context):
- row = layout.row()
- row.template_list("VisRegionListUI", "regions", modifier, "regions", modifier, "active_region_index",
- rows=2, maxrows=3)
- col = row.column(align=True)
- op = col.operator("object.plasma_modifier_collection_add", icon="ZOOMIN", text="")
- op.modifier = modifier.pl_id
- op.collection = "regions"
- op = col.operator("object.plasma_modifier_collection_remove", icon="ZOOMOUT", text="")
- op.modifier = modifier.pl_id
- op.collection = "regions"
- op.index = modifier.active_region_index
+ ui_list.draw_modifier_list(layout, "VisRegionListUI", modifier, "regions",
+ "active_region_index", rows=2, maxrows=3)
if modifier.regions:
layout.prop(modifier.regions[modifier.active_region_index], "control_region")
diff --git a/korman/ui/modifiers/sound.py b/korman/ui/modifiers/sound.py
index 376a29e..e51b383 100644
--- a/korman/ui/modifiers/sound.py
+++ b/korman/ui/modifiers/sound.py
@@ -15,6 +15,8 @@
import bpy
+from .. import ui_list
+
def _draw_fade_ui(modifier, layout, label):
layout.label(label)
layout.prop(modifier, "fade_type", text="")
@@ -30,17 +32,8 @@ class SoundListUI(bpy.types.UIList):
def soundemit(modifier, layout, context):
- row = layout.row()
- row.template_list("SoundListUI", "sounds", modifier, "sounds", modifier, "active_sound_index",
- rows=2, maxrows=3)
- col = row.column(align=True)
- op = col.operator("object.plasma_modifier_collection_add", icon="ZOOMIN", text="")
- op.modifier = modifier.pl_id
- op.collection = "sounds"
- op = col.operator("object.plasma_modifier_collection_remove", icon="ZOOMOUT", text="")
- op.modifier = modifier.pl_id
- op.collection = "sounds"
- op.index = modifier.active_sound_index
+ ui_list.draw_modifier_list(layout, "SoundListUI", modifier, "sounds",
+ "active_sound_index", rows=2, maxrows=3)
try:
sound = modifier.sounds[modifier.active_sound_index]
diff --git a/korman/ui/modifiers/water.py b/korman/ui/modifiers/water.py
index f6dec6f..08313b9 100644
--- a/korman/ui/modifiers/water.py
+++ b/korman/ui/modifiers/water.py
@@ -15,6 +15,8 @@
import bpy
+from .. import ui_list
+
def swimregion(modifier, layout, context):
split = layout.split()
col = split.column()
@@ -111,19 +113,9 @@ class ShoreListUI(bpy.types.UIList):
def water_shore(modifier, layout, context):
- row = layout.row()
- row.template_list("ShoreListUI", "shores", modifier, "shores", modifier, "active_shore_index",
- rows=2, maxrows=3)
- col = row.column(align=True)
- op = col.operator("object.plasma_modifier_collection_add", icon="ZOOMIN", text="")
- op.modifier = modifier.pl_id
- op.collection = "shores"
- op.name_prefix = "Shore"
- op.name_prop = "display_name"
- op = col.operator("object.plasma_modifier_collection_remove", icon="ZOOMOUT", text="")
- op.modifier = modifier.pl_id
- op.collection = "shores"
- op.index = modifier.active_shore_index
+ ui_list.draw_modifier_list(layout, "ShoreListUI", modifier, "shores",
+ "active_shore_index", name_prefix="Shore",
+ name_prop="display_name", rows=2, maxrows=3)
# Display the active shore
if modifier.shores:
diff --git a/korman/ui/ui_list.py b/korman/ui/ui_list.py
new file mode 100644
index 0000000..7f7e032
--- /dev/null
+++ b/korman/ui/ui_list.py
@@ -0,0 +1,55 @@
+# This file is part of Korman.
+#
+# Korman is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Korman is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Korman. If not, see .
+
+import bpy
+
+def draw_list(layout, listtype, context_attr, prop_base, collection_name, index_name, **kwargs):
+ """Draws a generic UI list, including add/remove buttons. Note that in order to use this,
+ the parent datablock must be available in the context provided to operators. This should
+ always be true, but this is Blender...
+ Arguments:
+ - layout: required
+ - listtype: bpy.types.UIList subclass
+ - context_attr: attribute name to get the properties from in the current context
+ - prop_base: property group owning the collection
+ - collection_name: name of the collection property
+ - index_name: name of the active element index property
+ - name_prefix: (optional) prefix to apply to display name of new elements
+ - name_prop: (optional) property for each element's display name
+ *** any other arguments are passed as keyword arguments to the template_list call
+ """
+ prop_path = prop_base.path_from_id()
+ name_prefix = kwargs.pop("name_prefix", "")
+ name_prop = kwargs.pop("name_prop", "")
+
+ row = layout.row()
+ row.template_list(listtype, collection_name, prop_base, collection_name,
+ prop_base, index_name, **kwargs)
+ col = row.column(align=True)
+ op = col.operator("ui.plasma_collection_add", icon="ZOOMIN", text="")
+ op.context = context_attr
+ op.group_path = prop_path
+ op.collection_prop = collection_name
+ op.index_prop = index_name
+ op.name_prefix = name_prefix
+ op.name_prop = name_prop
+ op = col.operator("ui.plasma_collection_remove", icon="ZOOMOUT", text="")
+ op.context = context_attr
+ op.group_path = prop_path
+ op.collection_prop = collection_name
+ op.index_prop = index_name
+
+def draw_modifier_list(layout, listtype, prop_base, collection_name, index_name, **kwargs):
+ draw_list(layout, listtype, "object", prop_base, collection_name, index_name, **kwargs)
diff --git a/korman/ui/ui_texture.py b/korman/ui/ui_texture.py
index 2bc3d7a..80b5d20 100644
--- a/korman/ui/ui_texture.py
+++ b/korman/ui/ui_texture.py
@@ -15,6 +15,8 @@
import bpy
+from . import ui_list
+
class TextureButtonsPanel:
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
@@ -42,17 +44,8 @@ class PlasmaEnvMapPanel(TextureButtonsPanel, bpy.types.Panel):
layout.separator()
layout.label("Visibility Sets:")
- row = layout.row()
- row.template_list("VisRegionListUI", "vis_regions", layer_props, "vis_regions", layer_props, "active_region_index",
- rows=2, maxrows=3)
- col = row.column(align=True)
- op = col.operator("texture.plasma_collection_add", icon="ZOOMIN", text="")
- op.group = "plasma_layer"
- op.collection = "vis_regions"
- op = col.operator("texture.plasma_collection_remove", icon="ZOOMOUT", text="")
- op.group = "plasma_layer"
- op.collection = "vis_regions"
- op.index = layer_props.active_region_index
+ ui_list.draw_list(layout, "VisRegionListUI", "texture", layer_props,
+ "vis_regions", "active_region_index", rows=2, maxrows=3)
rgns = layer_props.vis_regions
if layer_props.vis_regions:
layout.prop(rgns[layer_props.active_region_index], "control_region")