From a5f23cd329228d149bc031761427b43cc1cde5a5 Mon Sep 17 00:00:00 2001 From: luboslenco Date: Sun, 18 Nov 2018 21:52:50 +0100 Subject: [PATCH] Allow to set object properties through UI --- blender/arm/exporter.py | 8 + ...ume_trigger.py => value_volume_trigger.py} | 0 blender/arm/props_properties.py | 171 ++++++++++++++++++ blender/arm/props_traits_props.py | 5 +- blender/arm/props_ui.py | 4 + blender/data/haxelogic.py | 2 +- blender/data/noise_gen.py | 6 + blender/start.py | 3 + 8 files changed, 194 insertions(+), 5 deletions(-) rename blender/arm/logicnode/{action_volume_trigger.py => value_volume_trigger.py} (100%) create mode 100644 blender/arm/props_properties.py create mode 100644 blender/data/noise_gen.py diff --git a/blender/arm/exporter.py b/blender/arm/exporter.py index 4a09ea10..4d561b40 100755 --- a/blender/arm/exporter.py +++ b/blender/arm/exporter.py @@ -903,6 +903,14 @@ class ArmoryExporter: o['tilesheet_ref'] = bobject.arm_tilesheet o['tilesheet_action_ref'] = bobject.arm_tilesheet_action + if len(bobject.arm_propertylist) > 0: + o['properties'] = [] + for p in bobject.arm_propertylist: + po = {} + po['name'] = p.name_prop + po['value'] = getattr(p, p.type_prop + '_prop') + o['properties'].append(po) + layer_found = False if bpy.app.version >= (2, 80, 1): layer_found = True diff --git a/blender/arm/logicnode/action_volume_trigger.py b/blender/arm/logicnode/value_volume_trigger.py similarity index 100% rename from blender/arm/logicnode/action_volume_trigger.py rename to blender/arm/logicnode/value_volume_trigger.py diff --git a/blender/arm/props_properties.py b/blender/arm/props_properties.py new file mode 100644 index 00000000..93c1d18d --- /dev/null +++ b/blender/arm/props_properties.py @@ -0,0 +1,171 @@ +import bpy +from bpy.types import Menu, Panel, UIList +from bpy.props import * + +class ArmPropertyListItem(bpy.types.PropertyGroup): + type_prop = bpy.props.EnumProperty( + items = [('string', 'String', 'String'), + ('integer', 'Integer', 'Integer'), + ('float', 'Float', 'Float'), + ('boolean', 'Boolean', 'Boolean'), + ], + name = "Type") + name_prop = bpy.props.StringProperty(name="Name", description="A name for this item", default="my_prop") + string_prop = bpy.props.StringProperty(name="String", description="A name for this item", default="text") + integer_prop = bpy.props.IntProperty(name="Integer", description="A name for this item", default=0) + float_prop = bpy.props.FloatProperty(name="Float", description="A name for this item", default=0.0) + boolean_prop = bpy.props.BoolProperty(name="Boolean", description="A name for this item", default=False) + +class ArmPropertyList(bpy.types.UIList): + def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index): + # Make sure your code supports all 3 layout types + if self.layout_type in {'DEFAULT', 'COMPACT'}: + split = layout.row() + split.prop(item, "name_prop", text="", emboss=False, icon="OBJECT_DATAMODE") + split.prop(item, item.type_prop + "_prop", text="", emboss=(item.type_prop == 'boolean')) + elif self.layout_type in {'GRID'}: + layout.alignment = 'CENTER' + layout.label(text="", icon="OBJECT_DATAMODE") + +class ArmPropertyListNewItem(bpy.types.Operator): + # Add a new item to the list + bl_idname = "arm_propertylist.new_item" + bl_label = "New" + + type_prop = bpy.props.EnumProperty( + items = [('String', 'String', 'String'), + ('Integer', 'Integer', 'Integer'), + ('Float', 'Float', 'Float'), + ('Boolean', 'Boolean', 'Boolean'), + ], + name = "Type") + + def invoke(self, context, event): + wm = context.window_manager + return wm.invoke_props_dialog(self) + + def draw(self,context): + layout = self.layout + layout.prop(self, "type_prop", expand=True) + + def execute(self, context): + obj = bpy.context.object + prop = obj.arm_propertylist.add() + prop.type_prop = self.type_prop + obj.arm_propertylist_index = len(obj.arm_propertylist) - 1 + return{'FINISHED'} + +class ArmPropertyListDeleteItem(bpy.types.Operator): + # Delete the selected item from the list + bl_idname = "arm_propertylist.delete_item" + bl_label = "Deletes an item" + + @classmethod + def poll(self, context): + """ Enable if there's something in the list """ + obj = bpy.context.object + if obj == None: + return False + return len(obj.arm_propertylist) > 0 + + def execute(self, context): + obj = bpy.context.object + lst = obj.arm_propertylist + index = obj.arm_propertylist_index + + if len(lst) <= index: + return{'FINISHED'} + + lst.remove(index) + + if index > 0: + index = index - 1 + + obj.arm_propertylist_index = index + return{'FINISHED'} + +class ArmPropertyListMoveItem(bpy.types.Operator): + # Move an item in the list + bl_idname = "arm_propertylist.move_item" + bl_label = "Move an item in the list" + direction = bpy.props.EnumProperty( + items=( + ('UP', 'Up', ""), + ('DOWN', 'Down', ""),)) + + # @classmethod + # def poll(self, context): + # if self.is_object: + # obj = bpy.context.object + # else: + # obj = bpy.context.scene + # if obj == None: + # return False + # """ Enable if there's something in the list. """ + # return len(obj.arm_propertylist) > 0 + + def move_index(self): + # Move index of an item render queue while clamping it + obj = bpy.context.object + index = obj.arm_propertylist_index + list_length = len(obj.arm_propertylist) - 1 + new_index = 0 + + if self.direction == 'UP': + new_index = index - 1 + elif self.direction == 'DOWN': + new_index = index + 1 + + new_index = max(0, min(new_index, list_length)) + index = new_index + + def execute(self, context): + obj = bpy.context.object + list = obj.arm_propertylist + index = obj.arm_propertylist_index + + if self.direction == 'DOWN': + neighbor = index + 1 + #queue.move(index,neighbor) + self.move_index() + + elif self.direction == 'UP': + neighbor = index - 1 + #queue.move(neighbor, index) + self.move_index() + else: + return{'CANCELLED'} + return{'FINISHED'} + +def draw_properties(layout, obj): + layout.label("Properties") + rows = 2 + if len(obj.arm_traitlist) > 1: + rows = 4 + row = layout.row() + row.template_list("ArmPropertyList", "The_List", obj, "arm_propertylist", obj, "arm_propertylist_index", rows=rows) + col = row.column(align=True) + op = col.operator("arm_propertylist.new_item", icon='ZOOMIN', text="") + op = col.operator("arm_propertylist.delete_item", icon='ZOOMOUT', text="") + if len(obj.arm_propertylist) > 1: + col.separator() + op = col.operator("arm_propertylist.move_item", icon='TRIA_UP', text="") + op.direction = 'UP' + op = col.operator("arm_propertylist.move_item", icon='TRIA_DOWN', text="") + op.direction = 'DOWN' + +def register(): + bpy.utils.register_class(ArmPropertyListItem) + bpy.utils.register_class(ArmPropertyList) + bpy.utils.register_class(ArmPropertyListNewItem) + bpy.utils.register_class(ArmPropertyListDeleteItem) + bpy.utils.register_class(ArmPropertyListMoveItem) + bpy.types.Object.arm_propertylist = bpy.props.CollectionProperty(type=ArmPropertyListItem) + bpy.types.Object.arm_propertylist_index = bpy.props.IntProperty(name="Index for arm_propertylist", default=0) + +def unregister(): + bpy.utils.unregister_class(ArmPropertyListItem) + bpy.utils.unregister_class(ArmPropertyList) + bpy.utils.unregister_class(ArmPropertyListNewItem) + bpy.utils.unregister_class(ArmPropertyListDeleteItem) + bpy.utils.unregister_class(ArmPropertyListMoveItem) \ No newline at end of file diff --git a/blender/arm/props_traits_props.py b/blender/arm/props_traits_props.py index 470f5cde..873b9ddf 100644 --- a/blender/arm/props_traits_props.py +++ b/blender/arm/props_traits_props.py @@ -25,14 +25,11 @@ class ArmTraitPropList(bpy.types.UIList): # Make sure your code supports all 3 layout types if self.layout_type in {'DEFAULT', 'COMPACT'}: - #layout.prop(item, "enabled_prop") - #layout.label(text=item.name, icon = custom_icon) - # layout.label(text=item.name) layout.prop(item, "value", text=item.name, emboss=False, icon=custom_icon) elif self.layout_type in {'GRID'}: layout.alignment = 'CENTER' - layout.label(text="", icon = custom_icon) + layout.label(text="", icon=custom_icon) def register(): bpy.utils.register_class(ArmTraitPropListItem) diff --git a/blender/arm/props_ui.py b/blender/arm/props_ui.py index 62b22579..4853a845 100644 --- a/blender/arm/props_ui.py +++ b/blender/arm/props_ui.py @@ -10,6 +10,7 @@ import arm.assets as assets import arm.log as log import arm.proxy import arm.api +import arm.props_properties # Menu in object region class ObjectPropsPanel(bpy.types.Panel): @@ -49,6 +50,9 @@ class ObjectPropsPanel(bpy.types.Panel): break layout.prop_search(obj, "arm_tilesheet_action", selected_ts, "arm_tilesheetactionlist", text="Action") + # Properties list + arm.props_properties.draw_properties(layout, obj) + class ModifiersPropsPanel(bpy.types.Panel): bl_label = "Armory Props" bl_space_type = "PROPERTIES" diff --git a/blender/data/haxelogic.py b/blender/data/haxelogic.py index 8e3eccae..c2bcc745 100644 --- a/blender/data/haxelogic.py +++ b/blender/data/haxelogic.py @@ -56,7 +56,7 @@ for m in modules: # if l.startswith('property'): if 'EnumProperty' in l: # TODO: enum only for now but = {} - but['name'] = 'property' + l[-1] + but['name'] = 'property' + l.split(' = ', 1)[0][-1] but['type'] = 'ENUM' but['default_value'] = 0 but['data'] = [] diff --git a/blender/data/noise_gen.py b/blender/data/noise_gen.py new file mode 100644 index 00000000..22dc4bbb --- /dev/null +++ b/blender/data/noise_gen.py @@ -0,0 +1,6 @@ +for x in range(256): + for y in range(256): + x2 = (x - 37) & 255 + y2 = (y - 17) & 255 + img.pixels[(y * 255 + x) * 4 + 1] = img.pixels[(y2 * 255 + x2) * 4] + img.pixels[(y * 255 + x) * 4 + 3] = img.pixels[(y2 * 255 + x2) * 4 + 2] diff --git a/blender/start.py b/blender/start.py index b6bc1c38..14ad85ec 100755 --- a/blender/start.py +++ b/blender/start.py @@ -6,6 +6,7 @@ import arm.props_tilesheet import arm.props_exporter import arm.props_bake import arm.props_renderpath +import arm.props_properties import arm.props import arm.props_ui import arm.handlers @@ -25,6 +26,7 @@ def register(local_sdk=False): arm.props_exporter.register() arm.props_bake.register() arm.props_renderpath.register() + arm.props_properties.register() arm.props.register() arm.props_ui.register() arm.nodes_logic.register() @@ -47,3 +49,4 @@ def unregister(): arm.props_exporter.unregister() arm.props_bake.unregister() arm.props_renderpath.unregister() + arm.props_properties.unregister()