From 6160b99c93c2ce390785c978ea6b2075b1f9154d Mon Sep 17 00:00:00 2001 From: themancalledjakob Date: Sat, 31 May 2025 19:53:37 +0200 Subject: [PATCH] [fix] recursive selections --- __init__.py | 146 ++++++++++++++-------------------------------------- butils.py | 8 +++ 2 files changed, 46 insertions(+), 108 deletions(-) diff --git a/__init__.py b/__init__.py index 3dbc369..c27a677 100644 --- a/__init__.py +++ b/__init__.py @@ -269,8 +269,9 @@ class ABC3D_data(bpy.types.PropertyGroup): ) def active_text_index_update(self, context): + lock_depsgraph_updates() if self.active_text_index != -1: - text_properties = butils.get_text_properties( + text_properties = butils.get_text_properties_by_index( self.active_text_index, context.scene ) if text_properties is not None: @@ -278,16 +279,20 @@ class ABC3D_data(bpy.types.PropertyGroup): # active_text_index changed. so let's update the selection # check if it is already selected # or perhaps one of the glyphs - if ( - o is not None - and not o.select_get() - and not len([c for c in o.children if c.select_get()]) > 0 + if os is not None and not butils.is_or_has_parent( + context.active_object, o ): + # if ( + # o is not None + # and not o.select_get() + # and not len([c for c in o.children if c.select_get()]) > 0 + # ): bpy.ops.object.select_all(action="DESELECT") o.select_set(True) context.view_layer.objects.active = o - # else: - # print("already selected") + unlock_depsgraph_updates() + # else: + # print("already selected") active_text_index: bpy.props.IntProperty(update=active_text_index_update) @@ -487,99 +492,6 @@ class ABC3D_PT_TextManagement(bpy.types.Panel): bl_region_type = "UI" bl_options = {"DEFAULT_CLOSED"} - # TODO: perhaps this should be done in a periodic timer - @classmethod - def poll(self, context): - scene = context.scene - abc3d_data = scene.abc3d_data - # TODO: update available_texts - - def update(): - if bpy.context.screen.is_animation_playing: - return - active_text_index = -1 - remove_list = [] - for i, t in enumerate(abc3d_data.available_texts): - if type(t.text_object) == type(None): - remove_list.append(i) - continue - remove_me = True - for c in t.text_object.children: - if ( - len(c.users_collection) > 0 - and not isinstance(c.get(f"{utils.prefix()}_text_id"), None) - and c.get(f"{utils.prefix()}_text_id") == t.text_id - ): - remove_me = False - # not sure how to solve this reliably atm, - # we need to reassign the glyph, but also get the proper properties from glyph_properties - # these might be there in t.glyphs, but linked to removed objects - # or they might be lost - if type( - next( - ( - g - for g in t.glyphs - if type(g.glyph_object) == type(None) - ), - None, - ) - ) == type(None): - g = next( - ( - g - for g in t.glyphs - if type(g.glyph_object) == type(None) - ), - None, - ) - # for g in t.glyphs: - # if type(g) == type(None): - # print("IS NONE") - # if type(g.glyph_object) == type(None): - # print("go IS NONE") - # else: - # if g.glyph_object == c: - # # print(g.glyph_object.name) - # pass - - if remove_me: - remove_list.append(i) - - for i in remove_list: - if abc3d_data.available_texts[i].text_object is not None: - mom = abc3d_data.available_texts[i].text_object - - def delif(o, p): - if p in o: - del o[p] - - delif(mom, f"{utils.prefix()}_text_id") - delif(mom, f"{utils.prefix()}_font_name") - delif(mom, f"{utils.prefix()}_face_name") - delif(mom, f"{utils.prefix()}_font_size") - delif(mom, f"{utils.prefix()}_letter_spacing") - delif(mom, f"{utils.prefix()}_orientation") - delif(mom, f"{utils.prefix()}_translation") - delif(mom, f"{utils.prefix()}_offset") - abc3d_data.available_texts.remove(i) - - for i, t in enumerate(abc3d_data.available_texts): - if context.active_object == t.text_object: - active_text_index = i - if ( - hasattr(context.active_object, "parent") - and context.active_object.parent == t.text_object - ): - active_text_index = i - - if active_text_index != abc3d_data.active_text_index: - abc3d_data.active_text_index = active_text_index - - # butils.run_in_main_thread(update) - - return True - def draw(self, context): layout = self.layout wm = context.window_manager @@ -1234,7 +1146,7 @@ class ABC3D_OT_RemoveText(bpy.types.Operator): def execute(self, context): abc3d_data = context.scene.abc3d_data - lock_depsgraph_updates(auto_unlock_s=-1) + lock_depsgraph_updates() if abc3d_data.active_text_index < 0: butils.ShowMessageBox( title="No text selected", @@ -1354,10 +1266,7 @@ class ABC3D_OT_PlaceText(bpy.types.Operator): distribution_type = "DEFAULT" - text_id = 0 - for i, tt in enumerate(abc3d_data.available_texts): - while text_id == tt.text_id: - text_id = text_id + 1 + text_id = butils.find_free_text_id() t = abc3d_data.available_texts.add() # If you wish to set a value and not fire an update, set the id property. # A property defined via bpy.props for example ob.prop is stored as ob["prop"] once set to non default. @@ -1907,13 +1816,33 @@ def compare_text_object_with_object(t, o, strict=False): def link_text_object_with_new_text_properties(text_object, scene=None): - lock_depsgraph_updates(auto_unlock_s=-1) + lock_depsgraph_updates() butils.link_text_object_with_new_text_properties(text_object, scene) unlock_depsgraph_updates() +def determine_active_text_index_from_selection(): + if bpy.context.active_object is None: + return -1 + for text_index, text_properties in enumerate( + bpy.context.scene.abc3d_data.available_texts + ): + if butils.is_text_object_legit(text_properties.text_object): + if butils.is_or_has_parent( + bpy.context.active_object, text_properties.text_object + ): + return text_index + return -1 + + +def update_active_text_index(): + text_index = determine_active_text_index_from_selection() + if text_index != bpy.context.scene.abc3d_data.active_text_index: + bpy.context.scene.abc3d_data.active_text_index = text_index + + def detect_text(): - lock_depsgraph_updates(auto_unlock_s=-1) + lock_depsgraph_updates() scene = bpy.context.scene abc3d_data = scene.abc3d_data required_keys = [ @@ -2015,7 +1944,7 @@ def unlock_depsgraph_updates(): depsgraph_updates_locked -= 1 -def lock_depsgraph_updates(auto_unlock_s=1): +def lock_depsgraph_updates(auto_unlock_s=-1): global depsgraph_updates_locked depsgraph_updates_locked += 1 if auto_unlock_s >= 0: @@ -2059,6 +1988,7 @@ def on_depsgraph_update(scene, depsgraph): # must be a new thing, maybe manually created or so link_text_object_with_new_text_properties(u.id.original, scene) butils.clean_text_properties() + update_active_text_index() unlock_depsgraph_updates() diff --git a/butils.py b/butils.py index c24c891..28dbd0f 100644 --- a/butils.py +++ b/butils.py @@ -1184,6 +1184,14 @@ def get_text_properties(text_id, scene=None): return t return None +def get_text_properties_by_index(text_index, scene=None): + if scene is None: + scene = bpy.context.scene + abc3d_data = scene.abc3d_data + if text_index >= len(abc3d_data.available_texts): + return None + return abc3d_data.available_texts[text_index] + def duplicate( obj,