diff --git a/CHANGELOG.md b/CHANGELOG.md index 2af1db6..e4b5045 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +2.0.3 + +- changed: `X-ray` to `In Front`, match original object property name + 2.0.2 - added: possibility to select which point attribute is copied by GP layer copy to clipboard diff --git a/__init__.py b/__init__.py index 8eaeea9..34d969e 100755 --- a/__init__.py +++ b/__init__.py @@ -4,7 +4,7 @@ bl_info = { "name": "GP toolbox", "description": "Tool set for Grease Pencil in animation production", "author": "Samuel Bernou, Christophe Seux", -"version": (2, 0, 3), +"version": (2, 0, 4), "blender": (2, 91, 0), "location": "Sidebar (N menu) > Gpencil > Toolbox / Gpencil properties", "warning": "", @@ -52,14 +52,21 @@ from .OP_pseudo_tint import GPT_OT_auto_tint_gp_layers from . import UI_tools -from .properties import GP_PG_ToolsSettings, GP_PG_FixSettings +from .properties import ( + GP_PG_ToolsSettings, + GP_PG_FixSettings, + GP_PG_namespace_props, + GP_PG_namespaces, + ) from bpy.props import (FloatProperty, BoolProperty, EnumProperty, StringProperty, - IntProperty) + IntProperty, + PointerProperty + ) import bpy import os @@ -103,6 +110,110 @@ def remap_on_save_update(self, context): # kmi.active = self.use_precise_eraser + +class GPTB_OT_add_namespace_prefix(bpy.types.Operator): + bl_idname = "gptb.add_namespace_prefix" + bl_label = "Add" + bl_description = "Add item in list" + bl_options = {'REGISTER', 'INTERNAL'} + + idx : bpy.props.IntProperty() + new : bpy.props.BoolProperty(default=True, options={'SKIP_SAVE'}) + + def invoke(self, context, event): + self.pg = get_addon_prefs().user_prefixes + # self.pg.namespaces.add() + # return {'FINISHED'}# can just add empty entry and leave... + if self.new: + self.pg.namespaces.add() + self.idx = len(self.pg.namespaces) - 1 + return context.window_manager.invoke_props_dialog(self, width=650) + + def draw(self, context): + import re + layout = self.layout + # layout.use_property_split = True + item = self.pg.namespaces[self.idx] + layout.label(text='Enter prefix:', icon='INFO') + layout.prop(item, 'prefix') + if item.prefix and not re.match(r'^[A-Z]{2}$', item.prefix): + layout.label(text='Prefix are preferably two capital letter (ex: CO)', icon='ERROR') + + layout.separator() + layout.label(text='Provide a name (Optional):', icon='INFO') + layout.prop(item, 'name') + + def execute(self, context): + item = self.pg.namespaces[self.idx] + ## Here can perform post add checks + # (check for duplicate ?) + # all_prefix = [n.prefix for i, n in enumerate(self.pg.namespaces) if i != self.pg.idx] + + if self.new: + # in case of new addition, remove just added if nothing specified + if not item.prefix and not item.name: + self.pg.dirs.remove(self.idx) + + context.area.tag_redraw() + return {'FINISHED'} +class GPTB_OT_move_item(bpy.types.Operator): + bl_idname = "gptb.move_item" + bl_label = "Move Item" + bl_description = "Move item in list up or down" + bl_options = {'REGISTER', 'INTERNAL'} + + # direction : bpy.props.IntProperty(default=1) + direction : bpy.props.EnumProperty( + items=( + ('UP', 'Move Up', 'Move up'), + ('DOWN', 'Move down', 'Move down'), + ), + default='UP', + + ) + # prop_name : bpy.props.StringProperty() + + def execute(self, context): + pg = get_addon_prefs().user_prefixes + # uilist = getattr(pg, self.prop_name) + uilist = pg.namespaces + index = pg.idx + + neighbor = index + (-1 if self.direction == 'UP' else 1) + uilist.move(neighbor, index) + list_length = len(uilist) - 1 # (index starts at 0) + new_index = index + (-1 if self.direction == 'UP' else 1) + list_index = max(0, min(new_index, list_length)) + + # index = list_index + # setattr(pg, self.prop_name + '_idx', list_index) + setattr(pg, 'idx', list_index) + return {'FINISHED'} + +class GPTB_UL_namespace_list(bpy.types.UIList): + + # show_desc : BoolProperty(name="Show Description", default=True, + # description="Display Description") + + def draw_item(self, context, layout, data, item, icon, active_data, active_propname): + # self.use_filter_show = True # force open/close the search feature + # prefs = get_addon_prefs() + # split = layout.split(align=False, factor=0.3) + row = layout.row() + ico = 'HIDE_ON' if item.hide else 'HIDE_OFF' + row.prop(item, 'hide', text='', icon=ico, invert_checkbox=True) + row.prop(item, 'prefix', text='') + row.prop(item, 'name', text='') + + # row = layout.split(align=False) + # row.label(text=item.prefix) + # row.label(text=item.name) + + # if self.show_desc: + # row.label(text=item.description) + # row.operator('sbam.open_online_repo', text='', icon='URL') + + class GPTB_prefs(bpy.types.AddonPreferences): bl_idname = __name__ @@ -213,6 +324,9 @@ class GPTB_prefs(bpy.types.AddonPreferences): name="Layers Prefixes", description="List of prefixes (two capital letters) available for layers(ex: AN,CO,CL)", default="", maxlen=0) + + # user_prefixes : PointerProperty(type=GP_PG_namespaces) + ### proj_prefixes : PointerProperty(type=GP_PG_namespaces) # Store in the same list ? suffixes : StringProperty( name="Layers Suffixes", @@ -397,6 +511,7 @@ class GPTB_prefs(bpy.types.AddonPreferences): subbox.label(text='Namespace:') subbox.prop(self, 'separator') subbox.prop(self, 'show_prefix_buttons', text='Use Prefixes Toggles') + if self.show_prefix_buttons: # subbox.prop(self, 'use_env_namespace') row = subbox.row() @@ -405,6 +520,22 @@ class GPTB_prefs(bpy.types.AddonPreferences): row = subbox.row() row.prop(self, 'suffixes') row.operator('prefs.reset_gp_toolbox_env', text='', icon='LOOP_BACK').mode = 'SUFFIXES' + + ## Collection UI list version # WIP # TODO + """ + pg = self.user_prefixes + row = subbox.row(align=True) + row.template_list("GPTB_UL_namespace_list", "", pg, "namespaces", pg, "idx", rows=6) + subcol = row.column(align=True) # Lateral right + subcol.operator("gptb.add_namespace_prefix", icon="PLUS", text="") + subcol.separator() + op_move = subcol.operator("gptb.move_item", icon="TRIA_UP", text="") + # op_move.prop_name = 'namespaces' + op_move.direction = 'UP' + op_move = subcol.operator("gptb.move_item", icon="TRIA_DOWN", text="") + # op_move.prop_name = 'namespaces' + op_move.direction = 'DOWN' + """ ### TODO add render settings @@ -677,6 +808,11 @@ class GPTB_set_env_settings(bpy.types.Operator): classes = ( + # GP_PG_namespace_props, + # GP_PG_namespaces, + # GPTB_OT_add_namespace_prefix, + # GPTB_OT_move_item, + # GPTB_UL_namespace_list, GP_PG_FixSettings, GP_PG_ToolsSettings, GPTB_set_env_settings, diff --git a/properties.py b/properties.py index 70b2080..b7a6937 100755 --- a/properties.py +++ b/properties.py @@ -1,4 +1,5 @@ import bpy +from bpy.types import PropertyGroup from bpy.props import ( IntProperty, BoolProperty, @@ -28,7 +29,7 @@ def update_layer_name(self, context): # context.object.data.layers.active.info = self.layer_name -class GP_PG_FixSettings(bpy.types.PropertyGroup): +class GP_PG_FixSettings(PropertyGroup): check_only : BoolProperty( name="Dry run mode (Check only)", @@ -147,7 +148,7 @@ class GP_PG_FixSettings(bpy.types.PropertyGroup): ('UNLOCK', 'Unlock object mode', 'Toggle lock object mode Off', 2), )) -class GP_PG_ToolsSettings(bpy.types.PropertyGroup): +class GP_PG_ToolsSettings(PropertyGroup): eraser_radius : IntProperty( name="Eraser Radius", description="Radius of eraser brush", default=20, min=0, max=500, subtype='PIXEL') @@ -202,6 +203,7 @@ class GP_PG_ToolsSettings(bpy.types.PropertyGroup): description="The layer name, should describe the content of the layer", default="", update=update_layer_name)# update=None, get=None, set=None + """ reconnect_parent = bpy.props.PointerProperty(type =bpy.types.Object,poll=poll_armature) render_settings = bpy.props.BoolProperty(default = False) @@ -221,4 +223,21 @@ class GP_PG_ToolsSettings(bpy.types.PropertyGroup): opacity_layers = bpy.props.FloatProperty(min=0,max=1,default = 1,update = update_layers_opacity) stroke_select = bpy.props.EnumProperty(items = [("POINT","Point",""),("STROKE","Stroke","")],update = update_selection_mode) - """ \ No newline at end of file + """ + +class GP_PG_namespace_props(PropertyGroup): + + prefix : StringProperty( + name="Prefix", description="Layer namespace prefix", + default="") + name : StringProperty( + name="Name", description="Name that represent this prefix (used as hint and tooltip)", + default="") + hide : BoolProperty( + name="Hide", description="Hide this prefix from layer prefex management", + default=False) + +class GP_PG_namespaces(PropertyGroup): + idx : IntProperty(default=-1) + + namespaces : bpy.props.CollectionProperty(type=GP_PG_namespace_props) \ No newline at end of file