regenerate on demand, easier orientation, various
This commit is contained in:
parent
846b84b6f4
commit
07c38fcdaf
2 changed files with 200 additions and 70 deletions
173
__init__.py
173
__init__.py
|
@ -167,12 +167,30 @@ class FONT3D_glyph_properties(bpy.types.PropertyGroup):
|
||||||
class FONT3D_text_properties(bpy.types.PropertyGroup):
|
class FONT3D_text_properties(bpy.types.PropertyGroup):
|
||||||
def update_callback(self, context):
|
def update_callback(self, context):
|
||||||
butils.set_text_on_curve(self)
|
butils.set_text_on_curve(self)
|
||||||
text_index: bpy.props.IntProperty()
|
# TODO: update when animate
|
||||||
|
# does not work like this, somehow it does not run in main thread when the text is actually being set
|
||||||
|
# def get_float(self):
|
||||||
|
# return self["letter_spacingor"]
|
||||||
|
# def set_float(self, value):
|
||||||
|
# print(f"{utils.get_timestamp()} setting float to {value}")
|
||||||
|
# self["letter_spacingor"] = value
|
||||||
|
# def fun(text_properties : FONT3D_text_properties):
|
||||||
|
# # print(text_properties)
|
||||||
|
# # print(type(text_properties))
|
||||||
|
# # print(text_properties.letter_spacing)
|
||||||
|
# print(f"is running ---------------------------------->>>>>>> {text_properties.letter_spacing} and {text_properties.get('letter_spacingor')}")
|
||||||
|
# # butils.set_text_on_curve(text_properties)
|
||||||
|
# run_in_main_thread(lambda: fun(self))
|
||||||
|
text_id: bpy.props.IntProperty()
|
||||||
font_name: bpy.props.StringProperty()
|
font_name: bpy.props.StringProperty()
|
||||||
font_face: bpy.props.StringProperty()
|
font_face: bpy.props.StringProperty()
|
||||||
text_object: bpy.props.PointerProperty(type=bpy.types.Object)
|
text_object: bpy.props.PointerProperty(type=bpy.types.Object)
|
||||||
text: bpy.props.StringProperty()
|
text: bpy.props.StringProperty(
|
||||||
|
update=update_callback
|
||||||
|
)
|
||||||
letter_spacing: bpy.props.FloatProperty(
|
letter_spacing: bpy.props.FloatProperty(
|
||||||
|
# get=get_float,
|
||||||
|
# set=set_float,
|
||||||
update=update_callback,
|
update=update_callback,
|
||||||
name="Letter Spacing",
|
name="Letter Spacing",
|
||||||
description="Letter Spacing",
|
description="Letter Spacing",
|
||||||
|
@ -202,7 +220,7 @@ class FONT3D_UL_fonts(bpy.types.UIList):
|
||||||
class FONT3D_UL_texts(bpy.types.UIList):
|
class FONT3D_UL_texts(bpy.types.UIList):
|
||||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
|
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
|
||||||
split = layout.split(factor=0.3)
|
split = layout.split(factor=0.3)
|
||||||
split.label(text="Index: %d" % (index))
|
split.label(text="Id: %d" % (item.text_id))
|
||||||
# custom_icon = "OUTLINER_OB_%s" % item.obj_type
|
# custom_icon = "OUTLINER_OB_%s" % item.obj_type
|
||||||
# split.prop(item, "name", text="", emboss=False, translate=False)
|
# split.prop(item, "name", text="", emboss=False, translate=False)
|
||||||
split.label(text=f"{item.text}") # avoids renaming the item by accident
|
split.label(text=f"{item.text}") # avoids renaming the item by accident
|
||||||
|
@ -249,15 +267,36 @@ class FONT3D_PT_panel(bpy.types.Panel):
|
||||||
continue
|
continue
|
||||||
remove_me = True
|
remove_me = True
|
||||||
for c in t.text_object.children:
|
for c in t.text_object.children:
|
||||||
if len(c.users_collection) > 0 and (c.get('linked_textobject')) != type(None) and c.get('linked_textobject') == t.text_index:
|
if len(c.users_collection) > 0 and (c.get('linked_textobject')) != type(None) and c.get('linked_textobject') == t.text_id:
|
||||||
remove_me = False
|
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:
|
if remove_me:
|
||||||
remove_list.append(i)
|
remove_list.append(i)
|
||||||
|
|
||||||
for i in remove_list:
|
for i in remove_list:
|
||||||
font3d_data.available_texts.remove(i)
|
font3d_data.available_texts.remove(i)
|
||||||
|
|
||||||
# print(f"{utils.get_timestamp()} ors something")
|
for i, t in enumerate(font3d_data.available_texts):
|
||||||
|
if context.active_object == t.text_object:
|
||||||
|
font3d_data.active_text_index = i
|
||||||
|
if (hasattr(context.active_object, "parent") and
|
||||||
|
context.active_object.parent == t.text_object):
|
||||||
|
font3d_data.active_text_index = i
|
||||||
|
|
||||||
run_in_main_thread(update)
|
run_in_main_thread(update)
|
||||||
|
|
||||||
|
@ -425,12 +464,12 @@ class FONT3D_OT_TestFont(bpy.types.Operator):
|
||||||
|
|
||||||
distribution_type = 'DEFAULT'
|
distribution_type = 'DEFAULT'
|
||||||
|
|
||||||
t = font3d_data.available_texts.add()
|
text_id = 0
|
||||||
text_index = 0
|
|
||||||
for i, tt in enumerate(font3d_data.available_texts):
|
for i, tt in enumerate(font3d_data.available_texts):
|
||||||
while text_index == tt.text_index:
|
while text_id == tt.text_id:
|
||||||
text_index = text_index + 1
|
text_id = text_id + 1
|
||||||
t.text_index = text_index
|
t = font3d_data.available_texts.add()
|
||||||
|
t.text_id = text_id
|
||||||
|
|
||||||
t.font_name = font_name
|
t.font_name = font_name
|
||||||
t.font_face = font_face
|
t.font_face = font_face
|
||||||
|
@ -631,15 +670,21 @@ class FONT3D_OT_CreateFontFromObjects(bpy.types.Operator):
|
||||||
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
class FONT3D_PT_RightPropertiesPanel(bpy.types.Panel):
|
||||||
class HelloWorldPanel(bpy.types.Panel):
|
|
||||||
"""Creates a Panel in the Object properties window"""
|
"""Creates a Panel in the Object properties window"""
|
||||||
bl_label = "Hello World Panel"
|
bl_label = f"{__name__}"
|
||||||
bl_idname = "OBJECT_PT_hello"
|
bl_idname = "FONT3D_PT_RightPropertiesPanel"
|
||||||
bl_space_type = 'PROPERTIES'
|
bl_space_type = 'PROPERTIES'
|
||||||
bl_region_type = 'WINDOW'
|
bl_region_type = 'WINDOW'
|
||||||
bl_context = "object"
|
bl_context = "object"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def poll(self,context):
|
||||||
|
# only show the panel, if it's a textobject or a glyph
|
||||||
|
is_text = type(next((t for t in context.scene.font3d_data.available_texts if t.text_object == context.active_object), None)) != type(None)
|
||||||
|
is_glyph = type(next((t for t in context.scene.font3d_data.available_texts if t.text_object == context.active_object.parent), None)) != type(None)
|
||||||
|
return is_text or is_glyph
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
scene = context.scene
|
scene = context.scene
|
||||||
|
@ -648,16 +693,27 @@ class HelloWorldPanel(bpy.types.Panel):
|
||||||
|
|
||||||
obj = context.active_object
|
obj = context.active_object
|
||||||
|
|
||||||
|
def is_text():
|
||||||
|
return type(next((t for t in context.scene.font3d_data.available_texts if t.text_object == context.active_object), None)) != type(None)
|
||||||
|
def is_glyph():
|
||||||
|
return type(next((t for t in context.scene.font3d_data.available_texts if t.text_object == context.active_object.parent), None)) != type(None)
|
||||||
|
|
||||||
|
textobject = obj if is_text() else obj.parent if is_glyph() else obj
|
||||||
|
available_text = font3d_data.available_texts[font3d_data.active_text_index]
|
||||||
|
|
||||||
row = layout.row()
|
row = layout.row()
|
||||||
row.label(text="Hello world!", icon='WORLD_DATA')
|
row.label(text="Hello world!", icon='WORLD_DATA')
|
||||||
|
|
||||||
row = layout.row()
|
row = layout.row()
|
||||||
row.label(text="Active object is: " + obj.name)
|
row.label(text="Active object is: " + obj.name)
|
||||||
row = layout.row()
|
row = layout.row()
|
||||||
row.prop(obj, "location")
|
row.label(text="text object is: " + textobject.name)
|
||||||
|
|
||||||
row = layout.row()
|
row = layout.row()
|
||||||
row.operator("mesh.primitive_cube_add")
|
row.label(text=f"active text index is: {font3d_data.active_text_index}")
|
||||||
|
row = layout.row()
|
||||||
|
row.prop(available_text, "text")
|
||||||
|
row = layout.row()
|
||||||
|
row.prop(available_text, "letter_spacing")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -679,35 +735,98 @@ classes = (
|
||||||
FONT3D_OT_ToggleFont3DCollection,
|
FONT3D_OT_ToggleFont3DCollection,
|
||||||
FONT3D_OT_SaveFontToFile,
|
FONT3D_OT_SaveFontToFile,
|
||||||
FONT3D_OT_CreateFontFromObjects,
|
FONT3D_OT_CreateFontFromObjects,
|
||||||
HelloWorldPanel,
|
FONT3D_PT_RightPropertiesPanel,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@persistent
|
||||||
|
def load_handler(self, dummy):
|
||||||
|
bpy.app.timers.register(execute_queued_functions)
|
||||||
|
|
||||||
|
def load_handler_unload():
|
||||||
|
bpy.app.timers.unregister(execute_queued_functions)
|
||||||
|
|
||||||
def register():
|
def register():
|
||||||
for cls in classes:
|
for cls in classes:
|
||||||
bpy.utils.register_class(cls)
|
bpy.utils.register_class(cls)
|
||||||
bpy.types.Scene.font3d = bpy.props.PointerProperty(type=FONT3D_settings)
|
bpy.types.Scene.font3d = bpy.props.PointerProperty(type=FONT3D_settings)
|
||||||
bpy.types.Scene.font3d_data = bpy.props.PointerProperty(type=FONT3D_data)
|
bpy.types.Scene.font3d_data = bpy.props.PointerProperty(type=FONT3D_data)
|
||||||
bpy.types.Object.__del__ = lambda self: print(f"Bye {self.name}")
|
# bpy.types.Object.__del__ = lambda self: print(f"Bye {self.name}")
|
||||||
print(f"REGISTER {bl_info['name']}")
|
print(f"REGISTER {bl_info['name']}")
|
||||||
bpy.app.timers.register(execute_queued_functions)
|
|
||||||
|
|
||||||
# would love to properly auto start this, but IT DOES NOT WORK
|
# auto start
|
||||||
# if load_handler not in bpy.app.handlers.load_post:
|
if load_handler not in bpy.app.handlers.load_post:
|
||||||
# bpy.app.handlers.load_post.append(load_handler)
|
bpy.app.handlers.load_post.append(load_handler)
|
||||||
|
|
||||||
# clear available fonts
|
# clear available fonts
|
||||||
def clear_available_fonts():
|
def clear_available_fonts():
|
||||||
bpy.context.scene.font3d_data.available_fonts.clear()
|
bpy.context.scene.font3d_data.available_fonts.clear()
|
||||||
|
|
||||||
|
def load_available_fonts():
|
||||||
|
global shared
|
||||||
|
preferences = getPreferences(bpy.context)
|
||||||
|
|
||||||
|
currentObjects = []
|
||||||
|
for ob in bpy.data.objects:
|
||||||
|
currentObjects.append(ob.name)
|
||||||
|
|
||||||
|
print(f"assets folder: {preferences.assets_dir}")
|
||||||
|
font_dir = f"{preferences.assets_dir}/fonts"
|
||||||
|
for file in os.listdir(font_dir):
|
||||||
|
if file.endswith(".glb"):
|
||||||
|
font_path = os.path.join(font_dir, file)
|
||||||
|
bpy.ops.import_scene.gltf(filepath=font_path)
|
||||||
|
|
||||||
|
fontcollection = bpy.data.collections.get("Font3D")
|
||||||
|
if fontcollection is None:
|
||||||
|
fontcollection = bpy.data.collections.new("Font3D")
|
||||||
|
|
||||||
|
remove_list = []
|
||||||
|
all_objects = []
|
||||||
|
for o in bpy.data.objects:
|
||||||
|
all_objects.append(o)
|
||||||
|
for o in all_objects:
|
||||||
|
if o.name not in currentObjects:
|
||||||
|
# must be new
|
||||||
|
if ("glyph" in o.keys()
|
||||||
|
and "face_name" in o.keys()
|
||||||
|
and "font_name" in o.keys()):
|
||||||
|
glyph_id = o["glyph"]
|
||||||
|
font_name = o["font_name"]
|
||||||
|
face_name = o["face_name"]
|
||||||
|
butils.move_in_fontcollection(
|
||||||
|
o,
|
||||||
|
fontcollection)
|
||||||
|
Font.add_glyph(
|
||||||
|
font_name,
|
||||||
|
face_name,
|
||||||
|
glyph_id,
|
||||||
|
o)
|
||||||
|
|
||||||
|
font3d_data = bpy.context.scene.font3d_data
|
||||||
|
found = False
|
||||||
|
for f in font3d_data.available_fonts.values():
|
||||||
|
if f.font_name == font_name:
|
||||||
|
found = True
|
||||||
|
break
|
||||||
|
if not found:
|
||||||
|
f = font3d_data.available_fonts.add()
|
||||||
|
f.font_name = font_name
|
||||||
|
print(f"font3d added {font_name}")
|
||||||
|
else:
|
||||||
|
remove_list.append(o)
|
||||||
|
for o in remove_list:
|
||||||
|
bpy.data.objects.remove(o, do_unlink=True)
|
||||||
|
|
||||||
run_in_main_thread(clear_available_fonts)
|
run_in_main_thread(clear_available_fonts)
|
||||||
|
run_in_main_thread(load_available_fonts)
|
||||||
|
|
||||||
def unregister():
|
def unregister():
|
||||||
# would love to properly auto start this, but IT DOES NOT WORK
|
|
||||||
# if load_handler in bpy.app.handlers.load_post:
|
|
||||||
# bpy.app.handlers.load_post.remove(load_handler)
|
|
||||||
for cls in classes:
|
for cls in classes:
|
||||||
bpy.utils.unregister_class(cls)
|
bpy.utils.unregister_class(cls)
|
||||||
bpy.app.timers.unregister(execute_queued_functions)
|
|
||||||
|
if load_handler in bpy.app.handlers.load_post:
|
||||||
|
bpy.app.handlers.load_post.remove(load_handler)
|
||||||
|
load_handler_unload()
|
||||||
|
|
||||||
del bpy.types.Scene.font3d
|
del bpy.types.Scene.font3d
|
||||||
del bpy.types.Scene.font3d_data
|
del bpy.types.Scene.font3d_data
|
||||||
|
|
95
butils.py
95
butils.py
|
@ -89,8 +89,8 @@ def align_rotations_auto_pivot(mask, input_rotations, vectors, factors, local_ma
|
||||||
old_rotation = input_rotation.to_matrix()
|
old_rotation = input_rotation.to_matrix()
|
||||||
old_axis = (old_rotation @ local_main_axis).normalized()
|
old_axis = (old_rotation @ local_main_axis).normalized()
|
||||||
new_axis = vector
|
new_axis = vector
|
||||||
rotation_axis = (-(old_axis) + new_axis).normalized()
|
# rotation_axis = (-(old_axis) + new_axis).normalized()
|
||||||
# rotation_axis = old_axis.cross(new_axis).normalized()
|
rotation_axis = old_axis.cross(new_axis).normalized()
|
||||||
|
|
||||||
if rotation_axis.length < 1e-6:
|
if rotation_axis.length < 1e-6:
|
||||||
# Vectors are linearly dependent, fallback to another axis
|
# Vectors are linearly dependent, fallback to another axis
|
||||||
|
@ -276,9 +276,6 @@ def find_font_face_object(font_obj, face_name):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def move_in_fontcollection(obj, fontcollection):
|
def move_in_fontcollection(obj, fontcollection):
|
||||||
# print(turn_collection_hierarchy_into_path(obj))
|
|
||||||
# if scene.collection.objects.find(obj.name) >= 0:
|
|
||||||
# scene.collection.objects.unlink(obj)
|
|
||||||
for c in obj.users_collection:
|
for c in obj.users_collection:
|
||||||
c.objects.unlink(obj)
|
c.objects.unlink(obj)
|
||||||
if fontcollection.objects.find(obj.name) < 0:
|
if fontcollection.objects.find(obj.name) < 0:
|
||||||
|
@ -305,6 +302,7 @@ def move_in_fontcollection(obj, fontcollection):
|
||||||
face_obj.empty_display_type = 'PLAIN_AXES'
|
face_obj.empty_display_type = 'PLAIN_AXES'
|
||||||
face_obj["is_face"] = True
|
face_obj["is_face"] = True
|
||||||
fontcollection.objects.link(face_obj)
|
fontcollection.objects.link(face_obj)
|
||||||
|
|
||||||
# ensure custom properties are set
|
# ensure custom properties are set
|
||||||
face_obj["face_name"] = obj["face_name"]
|
face_obj["face_name"] = obj["face_name"]
|
||||||
face_obj["font_name"] = obj["font_name"]
|
face_obj["font_name"] = obj["font_name"]
|
||||||
|
@ -367,22 +365,39 @@ def ShowMessageBox(title = "Message Box", icon = 'INFO', message=""):
|
||||||
bpy.context.window_manager.popup_menu(draw, title = title, icon = icon)
|
bpy.context.window_manager.popup_menu(draw, title = title, icon = icon)
|
||||||
|
|
||||||
def set_text_on_curve(text_properties):
|
def set_text_on_curve(text_properties):
|
||||||
|
print(f"set text on curve {utils.get_timestamp()} with {text_properties.letter_spacing} and {text_properties.get('letter_spacingor')}")
|
||||||
mom = text_properties.text_object
|
mom = text_properties.text_object
|
||||||
if mom.type != "CURVE":
|
if mom.type != "CURVE":
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
regenerate = False
|
||||||
glyph_objects = []
|
glyph_objects = []
|
||||||
for g in text_properties.glyphs:
|
for g in text_properties.glyphs:
|
||||||
glyph_objects.append(g.glyph_object)
|
glyph_objects.append(g.glyph_object)
|
||||||
|
|
||||||
context_override = bpy.context.copy()
|
# check if perhaps one glyph was deleted
|
||||||
context_override["selected_objects"] = list(glyph_objects)
|
if (type(g.glyph_object) == type(None)
|
||||||
with bpy.context.temp_override(**context_override):
|
or type(g.glyph_object.parent) == type(None)
|
||||||
bpy.ops.object.delete()
|
or g.glyph_object.parent.users_collection != g.glyph_object.users_collection):
|
||||||
for g in glyph_objects:
|
regenerate = True
|
||||||
bpy.data.objects.remove(g, do_unlink=True)
|
|
||||||
# bpy.ops.object.delete({"selected_objects": glyph_objects})
|
if len(text_properties.text) != len(text_properties.glyphs):
|
||||||
text_properties.glyphs.clear()
|
regenerate = True
|
||||||
|
|
||||||
|
# if we regenerate.... delete objects
|
||||||
|
if regenerate:
|
||||||
|
context_override = bpy.context.copy()
|
||||||
|
context_override["selected_objects"] = list(glyph_objects)
|
||||||
|
with bpy.context.temp_override(**context_override):
|
||||||
|
bpy.ops.object.delete()
|
||||||
|
|
||||||
|
# remove deleted objects
|
||||||
|
# this is necessary
|
||||||
|
for g in glyph_objects:
|
||||||
|
if type(g) != type(None):
|
||||||
|
bpy.data.objects.remove(g, do_unlink=True)
|
||||||
|
|
||||||
|
text_properties.glyphs.clear()
|
||||||
|
|
||||||
#TODO: fix selection with context_override
|
#TODO: fix selection with context_override
|
||||||
previous_selection = bpy.context.selected_objects
|
previous_selection = bpy.context.selected_objects
|
||||||
|
@ -394,7 +409,6 @@ def set_text_on_curve(text_properties):
|
||||||
glyph_advance = 0
|
glyph_advance = 0
|
||||||
is_command = False
|
is_command = False
|
||||||
for i, c in enumerate(text_properties.text):
|
for i, c in enumerate(text_properties.text):
|
||||||
print(f"trying letter ({c})")
|
|
||||||
if c == '\\':
|
if c == '\\':
|
||||||
is_command = True
|
is_command = True
|
||||||
continue
|
continue
|
||||||
|
@ -407,16 +421,21 @@ def set_text_on_curve(text_properties):
|
||||||
continue
|
continue
|
||||||
is_command = False
|
is_command = False
|
||||||
glyph_id = c
|
glyph_id = c
|
||||||
|
|
||||||
glyph = Font.get_glyph(text_properties.font_name,
|
glyph = Font.get_glyph(text_properties.font_name,
|
||||||
text_properties.font_face,
|
text_properties.font_face,
|
||||||
glyph_id)
|
glyph_id)
|
||||||
|
|
||||||
if glyph == None:
|
ob = None
|
||||||
self.report({'ERROR'}, f"Glyph not found for {font_name} {font_face} {glyph_id}")
|
if regenerate:
|
||||||
continue
|
if glyph == None:
|
||||||
|
self.report({'ERROR'}, f"Glyph not found for {font_name} {font_face} {glyph_id}")
|
||||||
|
continue
|
||||||
|
|
||||||
ob = bpy.data.objects.new(f"{glyph_id}", glyph.data)
|
ob = bpy.data.objects.new(f"{glyph_id}", glyph.data)
|
||||||
ob['linked_textobject'] = text_properties.text_index
|
ob['linked_textobject'] = text_properties.text_id
|
||||||
|
else:
|
||||||
|
ob = text_properties.glyphs[i]['glyph_object']
|
||||||
|
|
||||||
distribution_type = 'CALCULATE'
|
distribution_type = 'CALCULATE'
|
||||||
if distribution_type == 'FOLLOW_PATH':
|
if distribution_type == 'FOLLOW_PATH':
|
||||||
|
@ -431,7 +450,7 @@ def set_text_on_curve(text_properties):
|
||||||
location, tangent = calc_point_on_bezier_curve(mom, advance, True)
|
location, tangent = calc_point_on_bezier_curve(mom, advance, True)
|
||||||
ob.location = mom.matrix_world @ location
|
ob.location = mom.matrix_world @ location
|
||||||
mask = [0]
|
mask = [0]
|
||||||
input_rotations = [mathutils.Vector((radians(90.0), 0.0, 0.0))]
|
input_rotations = [mathutils.Vector((0.0, 0.0, 0.0))]
|
||||||
vectors = [tangent]
|
vectors = [tangent]
|
||||||
factors = [1.0]
|
factors = [1.0]
|
||||||
local_main_axis = mathutils.Vector((1.0, 0.0, 0.0))
|
local_main_axis = mathutils.Vector((1.0, 0.0, 0.0))
|
||||||
|
@ -442,37 +461,29 @@ def set_text_on_curve(text_properties):
|
||||||
local_main_axis)
|
local_main_axis)
|
||||||
if ob.rotation_mode != 'QUATERNION':
|
if ob.rotation_mode != 'QUATERNION':
|
||||||
ob.rotation_mode = 'QUATERNION'
|
ob.rotation_mode = 'QUATERNION'
|
||||||
ob.rotation_quaternion = (mom.matrix_world @ motor[0]).to_quaternion()
|
q = mathutils.Quaternion()
|
||||||
|
q.rotate(mathutils.Euler((radians(90),0,0)))
|
||||||
|
ob.rotation_quaternion = (mom.matrix_world @ motor[0] @ q.to_matrix().to_4x4()).to_quaternion()
|
||||||
|
|
||||||
scalor = 0.001
|
scalor = 0.001
|
||||||
|
|
||||||
glyph_advance = (-1 * glyph.bound_box[0][0] + glyph.bound_box[4][0]) * scalor + text_properties.letter_spacing
|
glyph_advance = (-1 * glyph.bound_box[0][0] + glyph.bound_box[4][0]) * scalor + text_properties.letter_spacing
|
||||||
|
|
||||||
ob.scale = (scalor, scalor, scalor)
|
ob.scale = (scalor, scalor, scalor)
|
||||||
mom.users_collection[0].objects.link(ob)
|
|
||||||
|
|
||||||
advance = advance + glyph_advance
|
advance = advance + glyph_advance
|
||||||
|
|
||||||
glyph_data = text_properties.glyphs.add()
|
if regenerate:
|
||||||
glyph_data.glyph_id = glyph_id
|
mom.users_collection[0].objects.link(ob)
|
||||||
glyph_data.glyph_object = ob
|
glyph_data = text_properties.glyphs.add()
|
||||||
glyph_data.letter_spacing = 0
|
glyph_data.glyph_id = glyph_id
|
||||||
ob.select_set(True)
|
glyph_data.glyph_object = ob
|
||||||
# selected_objects.append(ob)
|
glyph_data.letter_spacing = 0
|
||||||
# selected_objects.append(mom)
|
ob.select_set(True)
|
||||||
|
|
||||||
mom.select_set(True)
|
|
||||||
bpy.context.view_layer.objects.active = mom
|
|
||||||
bpy.ops.object.parent_set(type='OBJECT')
|
|
||||||
# bpy.ops.object.select_all(action='DESELECT')
|
|
||||||
# for o in previous_selection:
|
|
||||||
# o.select_set(True)
|
|
||||||
|
|
||||||
# context_override = bpy.context.copy()
|
|
||||||
# context_override["selected_objects"] = selected_objects
|
|
||||||
# context_override["active_object"] = mom
|
|
||||||
# with bpy.context.temp_override(**context_override):
|
|
||||||
# bpy.ops.object.parent_set(type='OBJECT')
|
|
||||||
|
|
||||||
|
if regenerate:
|
||||||
|
mom.select_set(True)
|
||||||
|
bpy.context.view_layer.objects.active = mom
|
||||||
|
bpy.ops.object.parent_set(type='OBJECT')
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
Loading…
Reference in a new issue