Skip to content

Commit

Permalink
feat: Allow customizing the name for the widget library
Browse files Browse the repository at this point in the history
Added a property for customizing the name of a Widget, when adding a widget to the library, refactored, moved and removed `add_widgets` and `remove_widgets` functions, fixed "Property Deferred is not subscriptable"-Error

fix #1, fix #6
  • Loading branch information
BlenderDefender committed Feb 17, 2024
1 parent 36a15d5 commit d670932
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 134 deletions.
105 changes: 1 addition & 104 deletions functions/json_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,11 @@

import json

import typing

import numpy


from .. import (
__package__,
custom_types
__package__
)


Expand Down Expand Up @@ -114,103 +111,3 @@ def write_widgets(wgts: dict) -> None:

with open(json_file, "w+", encoding="utf-8") as f:
json.dump(wgts, f)


def add_widgets(context: 'Context', items: typing.List[typing.Tuple[str]], widgets: typing.Union[str, typing.List['Object']]) -> str:
"""Add a widget to the widgets file.
Args:
context (Context): The current Blender context
items (typing.List[typing.Tuple[str]]): The List of Enum Items (for the UI EnumProperty)
widgets (typing.Union[str, typing.List['Object']]): The list of widget objects if add, else the name of the widget that should be removed.
Returns:
str: Message of the return status.
"""

wgts: dict = read_widgets()
prefs: 'custom_types.AddonPreferences' = context.preferences.addons[__package__].preferences

widget_items: list = []
for widget_item in items:
widget_items.append(widget_item[1])

active_shape: str = None
ob_name: str = None

# ------ Add block ----------
bw_widget_prefix = prefs.widget_prefix
for ob in widgets:
ob_name = ob.name.removeprefix(bw_widget_prefix)

if ob_name in widget_items:
continue

widget_items.append(ob_name)
wgts[ob_name] = object_data_to_dico(context, ob)
active_shape = ob_name
# -----------------------------

if active_shape is not None:
del bpy.types.Scene.widget_list

widget_items_sorted: list = []
for w in sorted(widget_items):
widget_items_sorted.append((w, w, ""))

bpy.types.Scene.widget_list = bpy.props.EnumProperty(
items=widget_items_sorted, name="Shape", description="Shape")
context.scene.widget_list = active_shape
write_widgets(wgts)
return ""

if ob_name is not None:
return "Widget - " + ob_name + " already exists!"

return ""


def remove_widgets(context: 'Context', items: typing.List[typing.Tuple[str]], widgets: typing.Union[str, typing.List['Object']]) -> str:
"""Remove a widget to the widgets file.
Args:
context (Context): The current Blender context
items (typing.List[typing.Tuple[str]]): The List of Enum Items (for the UI EnumProperty)
widgets (typing.Union[str, typing.List['Object']]): The list of widget objects if add, else the name of the widget that should be removed.
Returns:
str: Message of the return status.
"""

wgts: dict = read_widgets()

widget_items: list = []
for widget_item in items:
widget_items.append(widget_item[1])

active_shape: str = None
ob_name: str = None

# ------ Remove block ---------------
del wgts[widgets]
widget_items.remove(widgets)
active_shape = widget_items[0] # ? Is there a bug hidden here?
# -----------------------------------

if active_shape is not None:
del bpy.types.Scene.widget_list

widget_items_sorted: list = []
for w in sorted(widget_items):
widget_items_sorted.append((w, w, ""))

bpy.types.Scene.widget_list = bpy.props.EnumProperty(
items=widget_items_sorted, name="Shape", description="Shape")
context.scene.widget_list = active_shape
write_widgets(wgts) # ? Is there a bug hidden here?
return ""

if ob_name is not None:
return "Widget - " + ob_name + " already exists!"

return ""
86 changes: 65 additions & 21 deletions operators.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from bpy.types import (
Context,
Collection,
Event,
LayerCollection,
Object,
Operator,
Expand All @@ -31,7 +32,8 @@
from bpy.props import (
FloatProperty,
BoolProperty,
FloatVectorProperty
FloatVectorProperty,
StringProperty
)

import numpy
Expand All @@ -40,8 +42,6 @@
import typing

from .functions import (
remove_widgets,
add_widgets,
bone_matrix,
find_match_bones,
from_widget_find_bone,
Expand All @@ -50,6 +50,8 @@
read_widgets,
recursively_find_layer_collection,
symmetrize_widget_helper,
object_data_to_dico,
write_widgets
)

from .custom_types import (
Expand Down Expand Up @@ -352,43 +354,85 @@ def execute(self, context: 'Context'):


class BONEWIDGET_OT_add_widgets(Operator):
"""Add selected mesh object to Bone Widget Library"""
"""Add the active object to the Bone Widget Library"""
bl_idname = "bonewidget.add_widgets"
bl_label = "Add Widgets"
bl_label = "Add to Widget library"

widget_name: StringProperty(
name="Widget Name",
options={"TEXTEDIT_UPDATE"},
)

@classmethod
def description(cls, context: 'Context', properties):
if context.mode == "POSE":
return "Add the custom shape of the active bone to the Bone Widget Library"

return "Add the active object to the Bone Widget Library"

@classmethod
def poll(cls, context: 'Context'):
if context.mode == "POSE":
return context.active_pose_bone is not None and context.active_pose_bone.custom_shape is not None

return (context.object and context.object.type == 'MESH' and context.object.mode == 'OBJECT'
and context.active_object is not None)

def execute(self, context: 'Context'):
objects = []
def invoke(self, context: 'Context', event: 'Event'):
prefs: 'AddonPreferences' = context.preferences.addons[__package__].preferences

self.widget_object: 'Object' = context.active_object

if context.mode == "POSE":
for bone in context.selected_pose_bones:
objects.append(bone.custom_shape)
else:
for ob in context.selected_objects:
if ob.type == 'MESH':
objects.append(ob)
self.widget_object = context.active_pose_bone.custom_shape

if not self.widget_object:
self.report({'WARNING'}, 'No object or pose bone selected.')
return {'FINISHED'}

self.widget_name = self.widget_object.name.removeprefix(
prefs.widget_prefix)

return context.window_manager.invoke_props_dialog(self)

def draw(self, context: 'Context'):
layout: 'UILayout' = self.layout
layout.label(text="Widget Name:")
layout.prop(self, "widget_name", text="")

if not objects:
self.report({'INFO'}, 'Select Meshes or Pose_bones')
def execute(self, context: 'Context'):
wgts: dict = read_widgets()

add_widgets(
context, bpy.types.Scene.widget_list[1]["items"], objects)
widget_names: typing.List[str] = [k for k in wgts.keys()]

if self.widget_name in widget_names:
self.report(
{'WARNING'}, f"A widget called '{self.widget_name}' already exists!")
return {'FINISHED'}

widget_names.append(self.widget_name)
wgts[self.widget_name] = object_data_to_dico(
context, self.widget_object)

write_widgets(wgts)

context.scene.widget_list = self.widget_name
return {'FINISHED'}


class BONEWIDGET_OT_remove_widgets(Operator):
"""Remove selected widget object from the Bone Widget Library"""
"""Remove selected widget from the Bone Widget Library"""
bl_idname = "bonewidget.remove_widgets"
bl_label = "Remove Widgets"

def execute(self, context: 'Context'):
objects = context.scene.widget_list
unwanted_list = remove_widgets(
context, "remove", bpy.types.Scene.widget_list[1]["items"], objects)
wgts: dict = read_widgets()

target_widget = context.scene.widget_list

wgts.pop(target_widget, "")
write_widgets(wgts)

return {'FINISHED'}


Expand Down
19 changes: 10 additions & 9 deletions panels.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,15 @@
)


def get_widget_list_items(self, context: 'Context'):
items = []

for key in sorted(read_widgets().keys()):
items.append((key, key, ""))

return items


@BlClassRegistry()
class BONEWIDGET_PT_posemode_panel(Panel):
bl_label = "Bone Widget"
Expand All @@ -47,16 +56,8 @@ class BONEWIDGET_PT_posemode_panel(Panel):
bl_region_type = 'UI'
bl_idname = 'VIEW3D_PT_bw_posemode_panel'

items: list = []
for key, value in read_widgets().items():
items.append(key)

items_sort: list = []
for key in sorted(items):
items_sort.append((key, key, ""))

bpy.types.Scene.widget_list = EnumProperty(
items=items_sort, name="Shape", description="Shape")
items=get_widget_list_items, name="Shape", description="Shape")

def draw(self, context: 'Context'):
layout: 'UILayout' = self.layout
Expand Down

0 comments on commit d670932

Please sign in to comment.