Compare commits
12 commits
65710b05ee
...
36ae68761d
Author | SHA1 | Date | |
---|---|---|---|
|
36ae68761d | ||
|
56904287a3 | ||
|
a7e6bdf082 | ||
|
30251a635f | ||
|
4a10584710 | ||
|
77fdf7d93a | ||
|
5e74787bb0 | ||
|
c302676ae3 | ||
|
e8fd0d8243 | ||
|
b6d76ae958 | ||
|
e5e8a1b053 | ||
|
dfd08de27d |
8 changed files with 3893 additions and 342 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -5,3 +5,4 @@ venv
|
||||||
# vim
|
# vim
|
||||||
*.swo
|
*.swo
|
||||||
*.swp
|
*.swp
|
||||||
|
/abc3d_updater/*
|
||||||
|
|
|
@ -5,6 +5,12 @@ source venv/bin/activate
|
||||||
pip install bpy
|
pip install bpy
|
||||||
```
|
```
|
||||||
|
|
||||||
|
to install mathutils, this was necessary for me:
|
||||||
|
```
|
||||||
|
sudo xbps-install -Sy python3.11-devel
|
||||||
|
CFLAGS=$(python3.11-config --cflags) LDFLAGS=$(python3.11-config --ldflags) pip install mathutils
|
||||||
|
```
|
||||||
|
|
||||||
# install addon:
|
# install addon:
|
||||||
```bash
|
```bash
|
||||||
cd <root directory>
|
cd <root directory>
|
||||||
|
|
395
__init__.py
395
__init__.py
|
@ -4,13 +4,21 @@
|
||||||
A 3D font helper
|
A 3D font helper
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
from bpy.app.handlers import persistent
|
||||||
|
from bpy.types import Panel
|
||||||
|
import functools
|
||||||
|
import io
|
||||||
|
import bpy
|
||||||
|
import importlib
|
||||||
|
|
||||||
bl_info = {
|
bl_info = {
|
||||||
"name": "ABC3D",
|
"name": "ABC3D",
|
||||||
"author": "Jakob Schlötter, Studio Pointer*",
|
"author": "Jakob Schlötter, Studio Pointer*",
|
||||||
"version": (0, 0, 1),
|
"version": (0, 0, 2),
|
||||||
"blender": (4, 1, 0),
|
"blender": (4, 1, 0),
|
||||||
"location": "VIEW3D",
|
"location": "VIEW3D",
|
||||||
"description": "Does ABC3D stuff",
|
"description": "Convenience addon for 3D fonts",
|
||||||
"category": "Typography",
|
"category": "Typography",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,39 +26,26 @@ bl_info = {
|
||||||
# when registering
|
# when registering
|
||||||
# handy for development
|
# handy for development
|
||||||
# first import dependencies for the method
|
# first import dependencies for the method
|
||||||
import importlib
|
if "Font" in locals():
|
||||||
|
|
||||||
# then import dependencies for our addon
|
|
||||||
if "bpy" in locals():
|
|
||||||
importlib.reload(Font)
|
importlib.reload(Font)
|
||||||
importlib.reload(utils)
|
importlib.reload(utils)
|
||||||
importlib.reload(butils)
|
importlib.reload(butils)
|
||||||
importlib.reload(bimport)
|
importlib.reload(bimport)
|
||||||
|
importlib.reload(addon_updater_ops)
|
||||||
else:
|
else:
|
||||||
from .common import Font
|
from .common import Font
|
||||||
from .common import utils
|
from .common import utils
|
||||||
from . import butils
|
from . import butils
|
||||||
from . import bimport
|
from . import bimport
|
||||||
|
from . import addon_updater_ops
|
||||||
|
|
||||||
import bpy
|
|
||||||
import math
|
|
||||||
import mathutils
|
|
||||||
import io
|
|
||||||
import functools
|
|
||||||
from bpy.types import Panel
|
|
||||||
from bpy.app.handlers import persistent
|
|
||||||
from random import uniform
|
|
||||||
|
|
||||||
import time
|
|
||||||
import datetime
|
|
||||||
|
|
||||||
import os
|
|
||||||
import re
|
|
||||||
|
|
||||||
def getPreferences(context):
|
def getPreferences(context):
|
||||||
preferences = context.preferences
|
preferences = context.preferences
|
||||||
return preferences.addons[__name__].preferences
|
return preferences.addons[__name__].preferences
|
||||||
|
|
||||||
|
|
||||||
|
@addon_updater_ops.make_annotations
|
||||||
class ABC3D_addonPreferences(bpy.types.AddonPreferences):
|
class ABC3D_addonPreferences(bpy.types.AddonPreferences):
|
||||||
"""ABC3D Addon Preferences
|
"""ABC3D Addon Preferences
|
||||||
|
|
||||||
|
@ -58,6 +53,39 @@ class ABC3D_addonPreferences(bpy.types.AddonPreferences):
|
||||||
|
|
||||||
bl_idname = __name__
|
bl_idname = __name__
|
||||||
|
|
||||||
|
# Addon updater preferences.
|
||||||
|
auto_check_update = bpy.props.BoolProperty(
|
||||||
|
name="Auto-check for Update",
|
||||||
|
description="If enabled, auto-check for updates using an interval",
|
||||||
|
default=False)
|
||||||
|
|
||||||
|
updater_interval_months = bpy.props.IntProperty(
|
||||||
|
name='Months',
|
||||||
|
description="Number of months between checking for updates",
|
||||||
|
default=0,
|
||||||
|
min=0)
|
||||||
|
|
||||||
|
updater_interval_days = bpy.props.IntProperty(
|
||||||
|
name='Days',
|
||||||
|
description="Number of days between checking for updates",
|
||||||
|
default=7,
|
||||||
|
min=0,
|
||||||
|
max=31)
|
||||||
|
|
||||||
|
updater_interval_hours = bpy.props.IntProperty(
|
||||||
|
name='Hours',
|
||||||
|
description="Number of hours between checking for updates",
|
||||||
|
default=0,
|
||||||
|
min=0,
|
||||||
|
max=23)
|
||||||
|
|
||||||
|
updater_interval_minutes = bpy.props.IntProperty(
|
||||||
|
name='Minutes',
|
||||||
|
description="Number of minutes between checking for updates",
|
||||||
|
default=0,
|
||||||
|
min=0,
|
||||||
|
max=59)
|
||||||
|
|
||||||
def get_default_assets_dir():
|
def get_default_assets_dir():
|
||||||
return bpy.utils.user_resource(
|
return bpy.utils.user_resource(
|
||||||
'DATAFILES',
|
'DATAFILES',
|
||||||
|
@ -92,6 +120,13 @@ class ABC3D_addonPreferences(bpy.types.AddonPreferences):
|
||||||
layout.label(text="Directory for storage of fonts and other assets:")
|
layout.label(text="Directory for storage of fonts and other assets:")
|
||||||
layout.prop(self, "assets_dir")
|
layout.prop(self, "assets_dir")
|
||||||
|
|
||||||
|
# Works best if a column, or even just self.layout.
|
||||||
|
mainrow = layout.row()
|
||||||
|
col = mainrow.column()
|
||||||
|
|
||||||
|
# Updater draw function, could also pass in col as third arg.
|
||||||
|
addon_updater_ops.update_settings_ui(self, context)
|
||||||
|
|
||||||
|
|
||||||
class ABC3D_available_font(bpy.types.PropertyGroup):
|
class ABC3D_available_font(bpy.types.PropertyGroup):
|
||||||
font_name: bpy.props.StringProperty(name="")
|
font_name: bpy.props.StringProperty(name="")
|
||||||
|
@ -121,15 +156,15 @@ class ABC3D_text_properties(bpy.types.PropertyGroup):
|
||||||
if len(d.available_fonts) > 0:
|
if len(d.available_fonts) > 0:
|
||||||
if len(d.available_fonts) > d.active_text_index:
|
if len(d.available_fonts) > d.active_text_index:
|
||||||
f = d.available_fonts[d.active_text_index]
|
f = d.available_fonts[d.active_text_index]
|
||||||
return 0 #f"{f.font_name} {f.face_name}"
|
return 0 # f"{f.font_name} {f.face_name}"
|
||||||
else:
|
else:
|
||||||
f = d.available_fonts[0]
|
f = d.available_fonts[0]
|
||||||
return 0 #f"{f.font_name} {f.face_name}"
|
return 0 # f"{f.font_name} {f.face_name}"
|
||||||
|
|
||||||
if type(self.font_name) != type(None) and type(self.face_name) != type(None):
|
if type(self.font_name) != type(None) and type(self.face_name) != type(None):
|
||||||
return 0 #f"{self.font_name} {self.face_name}"
|
return 0 # f"{self.font_name} {self.face_name}"
|
||||||
else:
|
else:
|
||||||
return 0 #""
|
return 0 # ""
|
||||||
|
|
||||||
def glyphs_update_callback(self, context):
|
def glyphs_update_callback(self, context):
|
||||||
butils.prepare_text(self.font_name,
|
butils.prepare_text(self.font_name,
|
||||||
|
@ -206,9 +241,13 @@ class ABC3D_text_properties(bpy.types.PropertyGroup):
|
||||||
distribution_type: bpy.props.StringProperty()
|
distribution_type: bpy.props.StringProperty()
|
||||||
glyphs: bpy.props.CollectionProperty(type=ABC3D_glyph_properties)
|
glyphs: bpy.props.CollectionProperty(type=ABC3D_glyph_properties)
|
||||||
|
|
||||||
#TODO: simply, merge, cut cut cut
|
# TODO: simply, merge, cut cut cut
|
||||||
|
|
||||||
|
|
||||||
class ABC3D_data(bpy.types.PropertyGroup):
|
class ABC3D_data(bpy.types.PropertyGroup):
|
||||||
available_fonts: bpy.props.CollectionProperty(type=ABC3D_available_font, name="Available fonts")
|
available_fonts: bpy.props.CollectionProperty(
|
||||||
|
type=ABC3D_available_font, name="Available fonts")
|
||||||
|
|
||||||
def active_font_index_update(self, context):
|
def active_font_index_update(self, context):
|
||||||
if len(self.available_fonts) <= self.active_font_index:
|
if len(self.available_fonts) <= self.active_font_index:
|
||||||
self.active_font_index = len(self.available_fonts) - 1
|
self.active_font_index = len(self.available_fonts) - 1
|
||||||
|
@ -217,14 +256,16 @@ class ABC3D_data(bpy.types.PropertyGroup):
|
||||||
default=-1,
|
default=-1,
|
||||||
update=active_font_index_update,
|
update=active_font_index_update,
|
||||||
)
|
)
|
||||||
available_texts: bpy.props.CollectionProperty(type=ABC3D_text_properties, name="Available texts")
|
available_texts: bpy.props.CollectionProperty(
|
||||||
|
type=ABC3D_text_properties, name="Available texts")
|
||||||
|
|
||||||
def active_text_index_update(self, context):
|
def active_text_index_update(self, context):
|
||||||
if self.active_text_index != -1:
|
if self.active_text_index != -1:
|
||||||
o = self.available_texts[self.active_text_index].text_object
|
o = self.available_texts[self.active_text_index].text_object
|
||||||
# active_text_index changed. so let's update the selection
|
# active_text_index changed. so let's update the selection
|
||||||
# check if it is already selected
|
# check if it is already selected
|
||||||
# or perhaps one of the glyphs
|
# or perhaps one of the glyphs
|
||||||
if not o.select_get() and not len([ c for c in o.children if c.select_get() ]) > 0:
|
if 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")
|
bpy.ops.object.select_all(action="DESELECT")
|
||||||
o.select_set(True)
|
o.select_set(True)
|
||||||
bpy.context.view_layer.objects.active = o
|
bpy.context.view_layer.objects.active = o
|
||||||
|
@ -253,20 +294,24 @@ class ABC3D_data(bpy.types.PropertyGroup):
|
||||||
|
|
||||||
class ABC3D_UL_fonts(bpy.types.UIList):
|
class ABC3D_UL_fonts(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):
|
||||||
layout.label(text=f"{index}: {item.font_name} {item.face_name}") # avoids renaming the item by accident
|
# avoids renaming the item by accident
|
||||||
|
layout.label(text=f"{index}: {item.font_name} {item.face_name}")
|
||||||
|
|
||||||
def invoke(self, context, event):
|
def invoke(self, context, event):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class ABC3D_UL_texts(bpy.types.UIList):
|
class ABC3D_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="Id: %d" % (item.text_id))
|
split.label(text="Id: %d" % (item.text_id))
|
||||||
split.label(text=f"{item.text}") # avoids renaming the item by accident
|
# avoids renaming the item by accident
|
||||||
|
split.label(text=f"{item.text}")
|
||||||
|
|
||||||
def invoke(self, context, event):
|
def invoke(self, context, event):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class ABC3D_PT_Panel(bpy.types.Panel):
|
class ABC3D_PT_Panel(bpy.types.Panel):
|
||||||
bl_label = f"{__name__} panel"
|
bl_label = f"{__name__} panel"
|
||||||
bl_category = "ABC3D"
|
bl_category = "ABC3D"
|
||||||
|
@ -281,7 +326,10 @@ class ABC3D_PT_Panel(bpy.types.Panel):
|
||||||
icon = 'ERROR'
|
icon = 'ERROR'
|
||||||
layout.row().label(text='no fonts loaded yet')
|
layout.row().label(text='no fonts loaded yet')
|
||||||
|
|
||||||
layout.operator(f"{__name__}.load_installed_fonts", text="load installed fonts", icon=icon)
|
layout.operator(f"{__name__}.load_installed_fonts",
|
||||||
|
text="load installed fonts", icon=icon)
|
||||||
|
layout.operator(f"{__name__}.open_asset_directory",
|
||||||
|
text="open asset directory", icon='FILEBROWSER')
|
||||||
|
|
||||||
|
|
||||||
class ABC3D_PT_LoadFontPanel(bpy.types.Panel):
|
class ABC3D_PT_LoadFontPanel(bpy.types.Panel):
|
||||||
|
@ -320,13 +368,16 @@ class ABC3D_PT_FontList(bpy.types.Panel):
|
||||||
abc3d_data = scene.abc3d_data
|
abc3d_data = scene.abc3d_data
|
||||||
|
|
||||||
layout.label(text="Available Fonts")
|
layout.label(text="Available Fonts")
|
||||||
layout.template_list("ABC3D_UL_fonts", "", abc3d_data, "available_fonts", abc3d_data, "active_font_index")
|
layout.template_list("ABC3D_UL_fonts", "", abc3d_data,
|
||||||
|
"available_fonts", abc3d_data, "active_font_index")
|
||||||
if abc3d_data.active_font_index >= 0:
|
if abc3d_data.active_font_index >= 0:
|
||||||
available_font = abc3d_data.available_fonts[abc3d_data.active_font_index]
|
available_font = abc3d_data.available_fonts[abc3d_data.active_font_index]
|
||||||
font_name = available_font.font_name
|
font_name = available_font.font_name
|
||||||
face_name = available_font.face_name
|
face_name = available_font.face_name
|
||||||
available_glyphs = sorted(Font.fonts[font_name].faces[face_name].glyphs_in_fontfile)
|
available_glyphs = sorted(
|
||||||
loaded_glyphs = sorted(Font.fonts[font_name].faces[face_name].loaded_glyphs)
|
Font.fonts[font_name].faces[face_name].glyphs_in_fontfile)
|
||||||
|
loaded_glyphs = sorted(
|
||||||
|
Font.fonts[font_name].faces[face_name].loaded_glyphs)
|
||||||
box = layout.box()
|
box = layout.box()
|
||||||
box.row().label(text=f"Font Name: {font_name}")
|
box.row().label(text=f"Font Name: {font_name}")
|
||||||
box.row().label(text=f"Face Name: {face_name}")
|
box.row().label(text=f"Face Name: {face_name}")
|
||||||
|
@ -335,20 +386,26 @@ class ABC3D_PT_FontList(bpy.types.Panel):
|
||||||
box.row().label(text=f"Glyphs:")
|
box.row().label(text=f"Glyphs:")
|
||||||
subbox = box.box()
|
subbox = box.box()
|
||||||
for i in range(0, n_rows + 1):
|
for i in range(0, n_rows + 1):
|
||||||
text = ''.join([f"{u}" for ui, u in enumerate(available_glyphs) if ui < (i+1) * n and ui >= i * n])
|
text = ''.join([f"{u}" for ui, u in enumerate(
|
||||||
|
available_glyphs) if ui < (i+1) * n and ui >= i * n])
|
||||||
scale_y = 0.5
|
scale_y = 0.5
|
||||||
row = subbox.row(); row.scale_y = scale_y; row.alignment = 'CENTER'
|
row = subbox.row()
|
||||||
|
row.scale_y = scale_y
|
||||||
|
row.alignment = 'CENTER'
|
||||||
row.label(text=text)
|
row.label(text=text)
|
||||||
n_rows = int(len(loaded_glyphs) / n)
|
n_rows = int(len(loaded_glyphs) / n)
|
||||||
box.row().label(text=f"Loaded/Used Glyphs:")
|
box.row().label(text=f"Loaded/Used Glyphs:")
|
||||||
subbox = box.box()
|
subbox = box.box()
|
||||||
for i in range(0, n_rows + 1):
|
for i in range(0, n_rows + 1):
|
||||||
text = ''.join([f"{u}" for ui, u in enumerate(loaded_glyphs) if ui < (i+1) * n and ui >= i * n])
|
text = ''.join([f"{u}" for ui, u in enumerate(
|
||||||
|
loaded_glyphs) if ui < (i+1) * n and ui >= i * n])
|
||||||
scale_y = 0.5
|
scale_y = 0.5
|
||||||
row = subbox.row(); row.scale_y = scale_y
|
row = subbox.row()
|
||||||
|
row.scale_y = scale_y
|
||||||
row.label(text=text)
|
row.label(text=text)
|
||||||
row = layout.row()
|
row = layout.row()
|
||||||
oper = row.operator(f"{__name__}.load_font", text='Load all glyphs in memory')
|
oper = row.operator(f"{__name__}.load_font",
|
||||||
|
text='Load all glyphs in memory')
|
||||||
oper.font_name = font_name
|
oper.font_name = font_name
|
||||||
oper.face_name = face_name
|
oper.face_name = face_name
|
||||||
|
|
||||||
|
@ -384,6 +441,7 @@ class ABC3D_PT_TextPlacement(bpy.types.Panel):
|
||||||
layout.label(text="Cannot place Text.")
|
layout.label(text="Cannot place Text.")
|
||||||
layout.label(text="Select a curve as active object.")
|
layout.label(text="Select a curve as active object.")
|
||||||
|
|
||||||
|
|
||||||
class ABC3D_PT_TextManagement(bpy.types.Panel):
|
class ABC3D_PT_TextManagement(bpy.types.Panel):
|
||||||
bl_label = "Text Management"
|
bl_label = "Text Management"
|
||||||
bl_parent_id = "ABC3D_PT_Panel"
|
bl_parent_id = "ABC3D_PT_Panel"
|
||||||
|
@ -398,6 +456,7 @@ class ABC3D_PT_TextManagement(bpy.types.Panel):
|
||||||
scene = context.scene
|
scene = context.scene
|
||||||
abc3d_data = scene.abc3d_data
|
abc3d_data = scene.abc3d_data
|
||||||
# TODO: update available_texts
|
# TODO: update available_texts
|
||||||
|
|
||||||
def update():
|
def update():
|
||||||
if bpy.context.screen.is_animation_playing:
|
if bpy.context.screen.is_animation_playing:
|
||||||
return
|
return
|
||||||
|
@ -416,7 +475,8 @@ class ABC3D_PT_TextManagement(bpy.types.Panel):
|
||||||
# these might be there in t.glyphs, but linked to removed objects
|
# these might be there in t.glyphs, but linked to removed objects
|
||||||
# or they might be lost
|
# or they might be lost
|
||||||
if type(next((g for g in t.glyphs if type(g.glyph_object) == type(None)), None)) == type(None):
|
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)
|
g = next((g for g in t.glyphs if type(
|
||||||
|
g.glyph_object) == type(None)), None)
|
||||||
# for g in t.glyphs:
|
# for g in t.glyphs:
|
||||||
# if type(g) == type(None):
|
# if type(g) == type(None):
|
||||||
# print("IS NONE")
|
# print("IS NONE")
|
||||||
|
@ -433,17 +493,18 @@ class ABC3D_PT_TextManagement(bpy.types.Panel):
|
||||||
for i in remove_list:
|
for i in remove_list:
|
||||||
if type(abc3d_data.available_texts[i].text_object) != type(None):
|
if type(abc3d_data.available_texts[i].text_object) != type(None):
|
||||||
mom = abc3d_data.available_texts[i].text_object
|
mom = abc3d_data.available_texts[i].text_object
|
||||||
|
|
||||||
def delif(o, p):
|
def delif(o, p):
|
||||||
if p in o:
|
if p in o:
|
||||||
del o[p]
|
del o[p]
|
||||||
delif(mom,f"{utils.prefix()}_linked_textobject")
|
delif(mom, f"{utils.prefix()}_linked_textobject")
|
||||||
delif(mom,f"{utils.prefix()}_font_name")
|
delif(mom, f"{utils.prefix()}_font_name")
|
||||||
delif(mom,f"{utils.prefix()}_face_name")
|
delif(mom, f"{utils.prefix()}_face_name")
|
||||||
delif(mom,f"{utils.prefix()}_font_size")
|
delif(mom, f"{utils.prefix()}_font_size")
|
||||||
delif(mom,f"{utils.prefix()}_letter_spacing")
|
delif(mom, f"{utils.prefix()}_letter_spacing")
|
||||||
delif(mom,f"{utils.prefix()}_orientation")
|
delif(mom, f"{utils.prefix()}_orientation")
|
||||||
delif(mom,f"{utils.prefix()}_translation")
|
delif(mom, f"{utils.prefix()}_translation")
|
||||||
delif(mom,f"{utils.prefix()}_offset")
|
delif(mom, f"{utils.prefix()}_offset")
|
||||||
abc3d_data.available_texts.remove(i)
|
abc3d_data.available_texts.remove(i)
|
||||||
|
|
||||||
for i, t in enumerate(abc3d_data.available_texts):
|
for i, t in enumerate(abc3d_data.available_texts):
|
||||||
|
@ -468,8 +529,11 @@ class ABC3D_PT_TextManagement(bpy.types.Panel):
|
||||||
abc3d_data = scene.abc3d_data
|
abc3d_data = scene.abc3d_data
|
||||||
|
|
||||||
layout.label(text="Text Objects")
|
layout.label(text="Text Objects")
|
||||||
layout.template_list("ABC3D_UL_texts", "", abc3d_data, "available_texts", abc3d_data, "active_text_index")
|
layout.template_list("ABC3D_UL_texts", "", abc3d_data,
|
||||||
layout.row().operator(f"{__name__}.remove_text", text="Remove Textobject")
|
"available_texts", abc3d_data, "active_text_index")
|
||||||
|
layout.row().operator(
|
||||||
|
f"{__name__}.remove_text", text="Remove Textobject")
|
||||||
|
|
||||||
|
|
||||||
class ABC3D_PT_FontCreation(bpy.types.Panel):
|
class ABC3D_PT_FontCreation(bpy.types.Panel):
|
||||||
bl_label = "Font Creation"
|
bl_label = "Font Creation"
|
||||||
|
@ -486,22 +550,29 @@ class ABC3D_PT_FontCreation(bpy.types.Panel):
|
||||||
|
|
||||||
abc3d_data = scene.abc3d_data
|
abc3d_data = scene.abc3d_data
|
||||||
|
|
||||||
layout.row().operator(f"{__name__}.create_font_from_objects", text='Create/Extend Font')
|
layout.row().operator(
|
||||||
|
f"{__name__}.create_font_from_objects", text='Create/Extend Font')
|
||||||
box = layout.box()
|
box = layout.box()
|
||||||
box.row().label(text="Exporting a fontfile")
|
box.row().label(text="Exporting a fontfile")
|
||||||
box.row().label(text="1. Select export directory:")
|
box.row().label(text="1. Select export directory:")
|
||||||
box.prop(abc3d_data, 'export_dir')
|
box.prop(abc3d_data, 'export_dir')
|
||||||
box.row().label(text="2. More options and export:")
|
box.row().label(text="2. More options and export:")
|
||||||
|
|
||||||
box.row().operator(f"{__name__}.save_font_to_file", text='Export Font To File')
|
box.row().operator(f"{__name__}.save_font_to_file",
|
||||||
layout.row().operator(f"{__name__}.toggle_abc3d_collection", text='Toggle Collection')
|
text='Export Font To File')
|
||||||
|
layout.row().operator(
|
||||||
|
f"{__name__}.toggle_abc3d_collection", text='Toggle Collection')
|
||||||
box = layout.box()
|
box = layout.box()
|
||||||
box.label(text="metrics")
|
box.label(text="metrics")
|
||||||
box.row().operator(f"{__name__}.add_default_metrics", text='Add Default Metrics')
|
box.row().operator(
|
||||||
|
f"{__name__}.add_default_metrics", text='Add Default Metrics')
|
||||||
box.row().operator(f"{__name__}.remove_metrics", text='Remove Metrics')
|
box.row().operator(f"{__name__}.remove_metrics", text='Remove Metrics')
|
||||||
box.row().operator(f"{__name__}.align_metrics", text='Align Metrics')
|
box.row().operator(f"{__name__}.align_metrics", text='Align Metrics')
|
||||||
box.row().operator(f"{__name__}.align_metrics_to_active_object", text='Align Metrics to Active Object')
|
box.row().operator(
|
||||||
layout.row().operator(f"{__name__}.temporaryhelper", text='Debug Function Do Not Use')
|
f"{__name__}.align_metrics_to_active_object", text='Align Metrics to Active Object')
|
||||||
|
layout.row().operator(
|
||||||
|
f"{__name__}.temporaryhelper", text='Debug Function Do Not Use')
|
||||||
|
|
||||||
|
|
||||||
class ABC3D_PT_TextPropertiesPanel(bpy.types.Panel):
|
class ABC3D_PT_TextPropertiesPanel(bpy.types.Panel):
|
||||||
bl_label = "Text Properties"
|
bl_label = "Text Properties"
|
||||||
|
@ -511,7 +582,8 @@ class ABC3D_PT_TextPropertiesPanel(bpy.types.Panel):
|
||||||
bl_region_type = "UI"
|
bl_region_type = "UI"
|
||||||
|
|
||||||
def get_active_text_properties(self):
|
def get_active_text_properties(self):
|
||||||
if type(bpy.context.active_object) != type(None):# and bpy.context.object.select_get():
|
# and bpy.context.object.select_get():
|
||||||
|
if type(bpy.context.active_object) != type(None):
|
||||||
for t in bpy.context.scene.abc3d_data.available_texts:
|
for t in bpy.context.scene.abc3d_data.available_texts:
|
||||||
if bpy.context.active_object == t.text_object:
|
if bpy.context.active_object == t.text_object:
|
||||||
return t
|
return t
|
||||||
|
@ -547,7 +619,7 @@ class ABC3D_PT_TextPropertiesPanel(bpy.types.Panel):
|
||||||
# )
|
# )
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def poll(self,context):
|
def poll(self, context):
|
||||||
return type(self.get_active_text_properties(self)) != type(None)
|
return type(self.get_active_text_properties(self)) != type(None)
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
|
@ -575,6 +647,7 @@ class ABC3D_PT_TextPropertiesPanel(bpy.types.Panel):
|
||||||
layout.column().prop(props, "translation")
|
layout.column().prop(props, "translation")
|
||||||
layout.column().prop(props, "orientation")
|
layout.column().prop(props, "orientation")
|
||||||
|
|
||||||
|
|
||||||
class ABC3D_OT_InstallFont(bpy.types.Operator):
|
class ABC3D_OT_InstallFont(bpy.types.Operator):
|
||||||
"""Install or load Fontfile from path above.
|
"""Install or load Fontfile from path above.
|
||||||
(Format must be *.glb or *.gltf)"""
|
(Format must be *.glb or *.gltf)"""
|
||||||
|
@ -614,7 +687,8 @@ class ABC3D_OT_InstallFont(bpy.types.Operator):
|
||||||
layout.row().prop(self, "install_in_assets")
|
layout.row().prop(self, "install_in_assets")
|
||||||
if not self.install_in_assets and not self.load_into_memory:
|
if not self.install_in_assets and not self.load_into_memory:
|
||||||
layout.label(text="If the fontfile is not installed,")
|
layout.label(text="If the fontfile is not installed,")
|
||||||
layout.label(text="and the font is not loaded in memory completely,")
|
layout.label(
|
||||||
|
text="and the font is not loaded in memory completely,")
|
||||||
layout.label(text="the fontfile should not be moved.")
|
layout.label(text="the fontfile should not be moved.")
|
||||||
layout.row().prop(self, "load_into_memory")
|
layout.row().prop(self, "load_into_memory")
|
||||||
if self.load_into_memory:
|
if self.load_into_memory:
|
||||||
|
@ -674,6 +748,29 @@ class ABC3D_OT_InstallFont(bpy.types.Operator):
|
||||||
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
|
class ABC3D_OT_OpenAssetDirectory(bpy.types.Operator):
|
||||||
|
"""Open Asset Directory"""
|
||||||
|
bl_idname = f"{__name__}.open_asset_directory"
|
||||||
|
bl_label = "Opens asset directory."
|
||||||
|
bl_options = {'REGISTER', 'UNDO'}
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
preferences = getPreferences(context)
|
||||||
|
directory = os.path.realpath(preferences.assets_dir)
|
||||||
|
if os.path.exists(directory):
|
||||||
|
utils.open_file_browser(directory)
|
||||||
|
return {'FINISHED'}
|
||||||
|
else:
|
||||||
|
butils.ShowMessageBox(
|
||||||
|
title=f"{__name__} Warning",
|
||||||
|
icon="ERROR",
|
||||||
|
message=("Asset directory does not exist.",
|
||||||
|
f"Command failed trying to access '{directory}'.",
|
||||||
|
"Please, make sure it exists or chose another directory."))
|
||||||
|
return {'CANCELLED'}
|
||||||
|
|
||||||
|
|
||||||
class ABC3D_OT_LoadInstalledFonts(bpy.types.Operator):
|
class ABC3D_OT_LoadInstalledFonts(bpy.types.Operator):
|
||||||
"""Load installed fontfiles from datapath."""
|
"""Load installed fontfiles from datapath."""
|
||||||
bl_idname = f"{__name__}.load_installed_fonts"
|
bl_idname = f"{__name__}.load_installed_fonts"
|
||||||
|
@ -714,6 +811,7 @@ class ABC3D_OT_LoadInstalledFonts(bpy.types.Operator):
|
||||||
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
class ABC3D_OT_LoadFont(bpy.types.Operator):
|
class ABC3D_OT_LoadFont(bpy.types.Operator):
|
||||||
"""Load all glyphs from a specific font in memory.\nThis can take a while and slow down Blender."""
|
"""Load all glyphs from a specific font in memory.\nThis can take a while and slow down Blender."""
|
||||||
bl_idname = f"{__name__}.load_font"
|
bl_idname = f"{__name__}.load_font"
|
||||||
|
@ -729,6 +827,7 @@ class ABC3D_OT_LoadFont(bpy.types.Operator):
|
||||||
butils.load_font_from_filepath(f)
|
butils.load_font_from_filepath(f)
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
class ABC3D_OT_AddDefaultMetrics(bpy.types.Operator):
|
class ABC3D_OT_AddDefaultMetrics(bpy.types.Operator):
|
||||||
"""Add default metrics to selected objects"""
|
"""Add default metrics to selected objects"""
|
||||||
bl_idname = f"{__name__}.add_default_metrics"
|
bl_idname = f"{__name__}.add_default_metrics"
|
||||||
|
@ -740,6 +839,7 @@ class ABC3D_OT_AddDefaultMetrics(bpy.types.Operator):
|
||||||
butils.add_default_metrics_to_objects(objects)
|
butils.add_default_metrics_to_objects(objects)
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
class ABC3D_OT_RemoveMetrics(bpy.types.Operator):
|
class ABC3D_OT_RemoveMetrics(bpy.types.Operator):
|
||||||
"""Remove metrics from selected objects"""
|
"""Remove metrics from selected objects"""
|
||||||
bl_idname = f"{__name__}.remove_metrics"
|
bl_idname = f"{__name__}.remove_metrics"
|
||||||
|
@ -751,6 +851,7 @@ class ABC3D_OT_RemoveMetrics(bpy.types.Operator):
|
||||||
butils.remove_metrics_from_objects(objects)
|
butils.remove_metrics_from_objects(objects)
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
class ABC3D_OT_AlignMetricsToActiveObject(bpy.types.Operator):
|
class ABC3D_OT_AlignMetricsToActiveObject(bpy.types.Operator):
|
||||||
"""Align metrics of selected objects to metrics of active object"""
|
"""Align metrics of selected objects to metrics of active object"""
|
||||||
bl_idname = f"{__name__}.align_metrics_to_active_object"
|
bl_idname = f"{__name__}.align_metrics_to_active_object"
|
||||||
|
@ -762,6 +863,7 @@ class ABC3D_OT_AlignMetricsToActiveObject(bpy.types.Operator):
|
||||||
butils.align_metrics_of_objects_to_active_object(objects)
|
butils.align_metrics_of_objects_to_active_object(objects)
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
class ABC3D_OT_AlignMetrics(bpy.types.Operator):
|
class ABC3D_OT_AlignMetrics(bpy.types.Operator):
|
||||||
"""Align metrics of selected objects to each other"""
|
"""Align metrics of selected objects to each other"""
|
||||||
bl_idname = f"{__name__}.align_metrics"
|
bl_idname = f"{__name__}.align_metrics"
|
||||||
|
@ -773,6 +875,7 @@ class ABC3D_OT_AlignMetrics(bpy.types.Operator):
|
||||||
butils.align_metrics_of_objects(objects)
|
butils.align_metrics_of_objects(objects)
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
class ABC3D_OT_TemporaryHelper(bpy.types.Operator):
|
class ABC3D_OT_TemporaryHelper(bpy.types.Operator):
|
||||||
"""Temporary Helper ABC3D\nThis could do anything.\nIt's just there to make random functions available for testing."""
|
"""Temporary Helper ABC3D\nThis could do anything.\nIt's just there to make random functions available for testing."""
|
||||||
bl_idname = f"{__name__}.temporaryhelper"
|
bl_idname = f"{__name__}.temporaryhelper"
|
||||||
|
@ -800,6 +903,7 @@ class ABC3D_OT_TemporaryHelper(bpy.types.Operator):
|
||||||
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
class ABC3D_OT_RemoveText(bpy.types.Operator):
|
class ABC3D_OT_RemoveText(bpy.types.Operator):
|
||||||
"""Remove Text 3D"""
|
"""Remove Text 3D"""
|
||||||
bl_idname = f"{__name__}.remove_text"
|
bl_idname = f"{__name__}.remove_text"
|
||||||
|
@ -827,17 +931,18 @@ class ABC3D_OT_RemoveText(bpy.types.Operator):
|
||||||
i = abc3d_data.active_text_index
|
i = abc3d_data.active_text_index
|
||||||
if type(abc3d_data.available_texts[i].text_object) != type(None):
|
if type(abc3d_data.available_texts[i].text_object) != type(None):
|
||||||
mom = abc3d_data.available_texts[i].text_object
|
mom = abc3d_data.available_texts[i].text_object
|
||||||
|
|
||||||
def delif(o, p):
|
def delif(o, p):
|
||||||
if p in o:
|
if p in o:
|
||||||
del o[p]
|
del o[p]
|
||||||
delif(mom,f"{utils.prefix()}_linked_textobject")
|
delif(mom, f"{utils.prefix()}_linked_textobject")
|
||||||
delif(mom,f"{utils.prefix()}_font_name")
|
delif(mom, f"{utils.prefix()}_font_name")
|
||||||
delif(mom,f"{utils.prefix()}_face_name")
|
delif(mom, f"{utils.prefix()}_face_name")
|
||||||
delif(mom,f"{utils.prefix()}_font_size")
|
delif(mom, f"{utils.prefix()}_font_size")
|
||||||
delif(mom,f"{utils.prefix()}_letter_spacing")
|
delif(mom, f"{utils.prefix()}_letter_spacing")
|
||||||
delif(mom,f"{utils.prefix()}_orientation")
|
delif(mom, f"{utils.prefix()}_orientation")
|
||||||
delif(mom,f"{utils.prefix()}_translation")
|
delif(mom, f"{utils.prefix()}_translation")
|
||||||
delif(mom,f"{utils.prefix()}_offset")
|
delif(mom, f"{utils.prefix()}_offset")
|
||||||
if self.remove_objects:
|
if self.remove_objects:
|
||||||
remove_list = []
|
remove_list = []
|
||||||
for g in abc3d_data.available_texts[i].glyphs:
|
for g in abc3d_data.available_texts[i].glyphs:
|
||||||
|
@ -973,6 +1078,7 @@ class ABC3D_OT_PlaceText(bpy.types.Operator):
|
||||||
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
class ABC3D_OT_ToggleABC3DCollection(bpy.types.Operator):
|
class ABC3D_OT_ToggleABC3DCollection(bpy.types.Operator):
|
||||||
"""Toggle ABC3D Collection"""
|
"""Toggle ABC3D Collection"""
|
||||||
bl_idname = f"{__name__}.toggle_abc3d_collection"
|
bl_idname = f"{__name__}.toggle_abc3d_collection"
|
||||||
|
@ -984,7 +1090,8 @@ class ABC3D_OT_ToggleABC3DCollection(bpy.types.Operator):
|
||||||
fontcollection = bpy.data.collections.get("ABC3D")
|
fontcollection = bpy.data.collections.get("ABC3D")
|
||||||
|
|
||||||
if fontcollection is None:
|
if fontcollection is None:
|
||||||
self.report({'INFO'}, f"{bl_info['name']}: There is no collection. Did you use or create any glyphs yet?")
|
self.report(
|
||||||
|
{'INFO'}, f"{bl_info['name']}: There is no collection. Did you use or create any glyphs yet?")
|
||||||
elif scene.collection.children.find(fontcollection.name) < 0:
|
elif scene.collection.children.find(fontcollection.name) < 0:
|
||||||
scene.collection.children.link(fontcollection)
|
scene.collection.children.link(fontcollection)
|
||||||
self.report({'INFO'}, f"{bl_info['name']}: show collection")
|
self.report({'INFO'}, f"{bl_info['name']}: show collection")
|
||||||
|
@ -1006,27 +1113,32 @@ class ABC3D_OT_SaveFontToFile(bpy.types.Operator):
|
||||||
preferences = getPreferences(context)
|
preferences = getPreferences(context)
|
||||||
abc3d_data = context.scene.abc3d_data
|
abc3d_data = context.scene.abc3d_data
|
||||||
if abc3d_data.export_dir == "":
|
if abc3d_data.export_dir == "":
|
||||||
abc3d_data.export_dir = os.path.join(preferences.assets_dir, "fonts")
|
abc3d_data.export_dir = os.path.join(
|
||||||
|
preferences.assets_dir, "fonts")
|
||||||
return wm.invoke_props_dialog(self)
|
return wm.invoke_props_dialog(self)
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
abc3d_data = context.scene.abc3d_data
|
abc3d_data = context.scene.abc3d_data
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
layout.label(text="Available Fonts")
|
layout.label(text="Available Fonts")
|
||||||
layout.template_list("ABC3D_UL_fonts", "", abc3d_data, "available_fonts", abc3d_data, "active_font_index")
|
layout.template_list("ABC3D_UL_fonts", "", abc3d_data,
|
||||||
|
"available_fonts", abc3d_data, "active_font_index")
|
||||||
available_font = abc3d_data.available_fonts[abc3d_data.active_font_index]
|
available_font = abc3d_data.available_fonts[abc3d_data.active_font_index]
|
||||||
font_name = available_font.font_name
|
font_name = available_font.font_name
|
||||||
face_name = available_font.face_name
|
face_name = available_font.face_name
|
||||||
loaded_glyphs = sorted(Font.fonts[font_name].faces[face_name].loaded_glyphs)
|
loaded_glyphs = sorted(
|
||||||
|
Font.fonts[font_name].faces[face_name].loaded_glyphs)
|
||||||
n = 16
|
n = 16
|
||||||
n_rows = int(len(loaded_glyphs) / n)
|
n_rows = int(len(loaded_glyphs) / n)
|
||||||
box = layout.box()
|
box = layout.box()
|
||||||
box.row().label(text=f"Glyphs to be exported:")
|
box.row().label(text=f"Glyphs to be exported:")
|
||||||
subbox = box.box()
|
subbox = box.box()
|
||||||
for i in range(0, n_rows + 1):
|
for i in range(0, n_rows + 1):
|
||||||
text = ''.join([f"{u}" for ui, u in enumerate(loaded_glyphs) if ui < (i+1) * n and ui >= i * n])
|
text = ''.join([f"{u}" for ui, u in enumerate(
|
||||||
|
loaded_glyphs) if ui < (i+1) * n and ui >= i * n])
|
||||||
scale_y = 0.5
|
scale_y = 0.5
|
||||||
row = subbox.row(); row.scale_y = scale_y
|
row = subbox.row()
|
||||||
|
row.scale_y = scale_y
|
||||||
row.label(text=text)
|
row.label(text=text)
|
||||||
layout.prop(abc3d_data, 'export_dir')
|
layout.prop(abc3d_data, 'export_dir')
|
||||||
|
|
||||||
|
@ -1043,15 +1155,18 @@ class ABC3D_OT_SaveFontToFile(bpy.types.Operator):
|
||||||
return {'CANCELLED'}
|
return {'CANCELLED'}
|
||||||
|
|
||||||
if abc3d_data.active_font_index < 0:
|
if abc3d_data.active_font_index < 0:
|
||||||
self.report({'INFO'}, f"{bl_info['name']}: There is no active font")
|
self.report(
|
||||||
|
{'INFO'}, f"{bl_info['name']}: There is no active font")
|
||||||
return {'CANCELLED'}
|
return {'CANCELLED'}
|
||||||
|
|
||||||
if len(abc3d_data.available_fonts) <= abc3d_data.active_font_index:
|
if len(abc3d_data.available_fonts) <= abc3d_data.active_font_index:
|
||||||
self.report({'INFO'}, f"{bl_info['name']}: Active font is not available")
|
self.report(
|
||||||
|
{'INFO'}, f"{bl_info['name']}: Active font is not available")
|
||||||
return {'CANCELLED'}
|
return {'CANCELLED'}
|
||||||
|
|
||||||
# save state to restore later
|
# save state to restore later
|
||||||
was_fontcollection_linked = scene.collection.children.find(fontcollection.name) >= 0
|
was_fontcollection_linked = scene.collection.children.find(
|
||||||
|
fontcollection.name) >= 0
|
||||||
was_selection = []
|
was_selection = []
|
||||||
for obj in bpy.context.selected_objects:
|
for obj in bpy.context.selected_objects:
|
||||||
was_selection.append(obj)
|
was_selection.append(obj)
|
||||||
|
@ -1063,7 +1178,8 @@ class ABC3D_OT_SaveFontToFile(bpy.types.Operator):
|
||||||
selected_font = abc3d_data.available_fonts[abc3d_data.active_font_index]
|
selected_font = abc3d_data.available_fonts[abc3d_data.active_font_index]
|
||||||
|
|
||||||
# print(selected_font.font_name)
|
# print(selected_font.font_name)
|
||||||
self.report({'INFO'}, f"{bl_info['name']}: {selected_font.font_name} {selected_font.face_name}")
|
self.report(
|
||||||
|
{'INFO'}, f"{bl_info['name']}: {selected_font.font_name} {selected_font.face_name}")
|
||||||
preferences = getPreferences(context)
|
preferences = getPreferences(context)
|
||||||
print(f"assets folder: {preferences.assets_dir}")
|
print(f"assets folder: {preferences.assets_dir}")
|
||||||
|
|
||||||
|
@ -1102,12 +1218,14 @@ class ABC3D_OT_SaveFontToFile(bpy.types.Operator):
|
||||||
bpy.ops.export_scene.gltf(
|
bpy.ops.export_scene.gltf(
|
||||||
filepath=filepath,
|
filepath=filepath,
|
||||||
check_existing=False,
|
check_existing=False,
|
||||||
export_format='GLB', # GLB or GLTF_SEPARATE (also change filepath)
|
# GLB or GLTF_SEPARATE (also change filepath)
|
||||||
|
export_format='GLB',
|
||||||
export_extras=True,
|
export_extras=True,
|
||||||
use_selection=True,
|
use_selection=True,
|
||||||
use_active_scene=True,
|
use_active_scene=True,
|
||||||
)
|
)
|
||||||
bpy.app.timers.register(lambda: bpy.ops.scene.delete(), first_interval=1)
|
bpy.app.timers.register(
|
||||||
|
lambda: bpy.ops.scene.delete(), first_interval=1)
|
||||||
|
|
||||||
# bpy.ops.scene.delete()
|
# bpy.ops.scene.delete()
|
||||||
# restore()
|
# restore()
|
||||||
|
@ -1162,29 +1280,42 @@ class ABC3D_OT_CreateFontFromObjects(bpy.types.Operator):
|
||||||
row.prop(self, 'autodetect_names')
|
row.prop(self, 'autodetect_names')
|
||||||
if self.autodetect_names:
|
if self.autodetect_names:
|
||||||
scale_y = 0.5
|
scale_y = 0.5
|
||||||
row = layout.row(); row.scale_y = scale_y
|
row = layout.row()
|
||||||
row.label(text="Watch out, follow convention in naming your meshes:")
|
row.scale_y = scale_y
|
||||||
row = layout.row(); row.scale_y = scale_y
|
row.label(
|
||||||
|
text="Watch out, follow convention in naming your meshes:")
|
||||||
|
row = layout.row()
|
||||||
|
row.scale_y = scale_y
|
||||||
row.label(text="'<glyph id>_<font name>_<face name>'")
|
row.label(text="'<glyph id>_<font name>_<face name>'")
|
||||||
row = layout.row(); row.scale_y = scale_y
|
row = layout.row()
|
||||||
|
row.scale_y = scale_y
|
||||||
row.label(text=" - glyph id: unicode glyph name or raw glyph")
|
row.label(text=" - glyph id: unicode glyph name or raw glyph")
|
||||||
row = layout.row(); row.scale_y = scale_y
|
row = layout.row()
|
||||||
|
row.scale_y = scale_y
|
||||||
row.label(text=" - font name: font name with underscore")
|
row.label(text=" - font name: font name with underscore")
|
||||||
row = layout.row(); row.scale_y = scale_y
|
row = layout.row()
|
||||||
|
row.scale_y = scale_y
|
||||||
row.label(text=" - face name: face name")
|
row.label(text=" - face name: face name")
|
||||||
row = layout.row(); row.scale_y = scale_y
|
row = layout.row()
|
||||||
|
row.scale_y = scale_y
|
||||||
row.label(text="working examples:")
|
row.label(text="working examples:")
|
||||||
row = layout.row(); row.scale_y = scale_y
|
row = layout.row()
|
||||||
|
row.scale_y = scale_y
|
||||||
row.label(text="- 'A_NM_Origin_Tender'")
|
row.label(text="- 'A_NM_Origin_Tender'")
|
||||||
row = layout.row(); row.scale_y = scale_y
|
row = layout.row()
|
||||||
|
row.scale_y = scale_y
|
||||||
row.label(text="- 'B_NM_Origin_Tender'")
|
row.label(text="- 'B_NM_Origin_Tender'")
|
||||||
row = layout.row(); row.scale_y = scale_y
|
row = layout.row()
|
||||||
|
row.scale_y = scale_y
|
||||||
row.label(text="- 'arrowright_NM_Origin_Tender'")
|
row.label(text="- 'arrowright_NM_Origin_Tender'")
|
||||||
row = layout.row(); row.scale_y = scale_y
|
row = layout.row()
|
||||||
|
row.scale_y = scale_y
|
||||||
row.label(text="- '→_NM_Origin_Tender' (equal to above)")
|
row.label(text="- '→_NM_Origin_Tender' (equal to above)")
|
||||||
row = layout.row(); row.scale_y = scale_y
|
row = layout.row()
|
||||||
|
row.scale_y = scale_y
|
||||||
row.label(text="- 'quotesingle_NM_Origin_Tender.001'")
|
row.label(text="- 'quotesingle_NM_Origin_Tender.001'")
|
||||||
row = layout.row(); row.scale_y = scale_y
|
row = layout.row()
|
||||||
|
row.scale_y = scale_y
|
||||||
row.label(text="- 'colon_NM_Origin_Tender_2'")
|
row.label(text="- 'colon_NM_Origin_Tender_2'")
|
||||||
box = layout.box()
|
box = layout.box()
|
||||||
box.enabled = not self.autodetect_names
|
box.enabled = not self.autodetect_names
|
||||||
|
@ -1197,8 +1328,10 @@ class ABC3D_OT_CreateFontFromObjects(bpy.types.Operator):
|
||||||
character = ""
|
character = ""
|
||||||
if Font.known_misspellings[k] in Font.name_to_glyph_d:
|
if Font.known_misspellings[k] in Font.name_to_glyph_d:
|
||||||
character = f" ({Font.name_to_glyph_d[Font.known_misspellings[k]]})"
|
character = f" ({Font.name_to_glyph_d[Font.known_misspellings[k]]})"
|
||||||
row = layout.row(); row.scale_y = 0.5
|
row = layout.row()
|
||||||
row.label(text=f"{k} → {Font.known_misspellings[k]}{character}")
|
row.scale_y = 0.5
|
||||||
|
row.label(
|
||||||
|
text=f"{k} → {Font.known_misspellings[k]}{character}")
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
print(f"executing {self.bl_idname}")
|
print(f"executing {self.bl_idname}")
|
||||||
|
@ -1233,7 +1366,8 @@ class ABC3D_OT_CreateFontFromObjects(bpy.types.Operator):
|
||||||
if self.autodetect_names:
|
if self.autodetect_names:
|
||||||
ifxsplit = o.name.split('_')
|
ifxsplit = o.name.split('_')
|
||||||
if len(ifxsplit) < 4:
|
if len(ifxsplit) < 4:
|
||||||
print(f"whoops name could not be autodetected {o.name}")
|
print(
|
||||||
|
f"whoops name could not be autodetected {o.name}")
|
||||||
continue
|
continue
|
||||||
font_name = f"{ifxsplit[1]}_{ifxsplit[2]}"
|
font_name = f"{ifxsplit[1]}_{ifxsplit[2]}"
|
||||||
face_name = ifxsplit[3]
|
face_name = ifxsplit[3]
|
||||||
|
@ -1247,7 +1381,7 @@ class ABC3D_OT_CreateFontFromObjects(bpy.types.Operator):
|
||||||
name = o.name.split('_')[0]
|
name = o.name.split('_')[0]
|
||||||
glyph_id = Font.name_to_glyph(name)
|
glyph_id = Font.name_to_glyph(name)
|
||||||
|
|
||||||
if type(glyph_id )!= type(None):
|
if type(glyph_id) != type(None):
|
||||||
o["glyph"] = glyph_id
|
o["glyph"] = glyph_id
|
||||||
o["font_name"] = font_name
|
o["font_name"] = font_name
|
||||||
o["face_name"] = face_name
|
o["face_name"] = face_name
|
||||||
|
@ -1261,7 +1395,7 @@ class ABC3D_OT_CreateFontFromObjects(bpy.types.Operator):
|
||||||
glyph_id,
|
glyph_id,
|
||||||
o)
|
o)
|
||||||
|
|
||||||
#TODO: is there a better way to iterate over a CollectionProperty?
|
# TODO: is there a better way to iterate over a CollectionProperty?
|
||||||
found = False
|
found = False
|
||||||
for f in abc3d_data.available_fonts.values():
|
for f in abc3d_data.available_fonts.values():
|
||||||
if (f.font_name == font_name
|
if (f.font_name == font_name
|
||||||
|
@ -1274,11 +1408,14 @@ class ABC3D_OT_CreateFontFromObjects(bpy.types.Operator):
|
||||||
f.face_name = face_name
|
f.face_name = face_name
|
||||||
|
|
||||||
else:
|
else:
|
||||||
print(f"import warning: did not understand glyph {name}")
|
print(
|
||||||
self.report({'INFO'}, f"did not understand glyph {name}")
|
f"import warning: did not understand glyph {name}")
|
||||||
|
self.report(
|
||||||
|
{'INFO'}, f"did not understand glyph {name}")
|
||||||
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
class ABC3D_PT_RightPropertiesPanel(bpy.types.Panel):
|
class ABC3D_PT_RightPropertiesPanel(bpy.types.Panel):
|
||||||
"""Creates a Panel in the Object properties window"""
|
"""Creates a Panel in the Object properties window"""
|
||||||
bl_label = f"{bl_info['name']}"
|
bl_label = f"{bl_info['name']}"
|
||||||
|
@ -1288,10 +1425,12 @@ class ABC3D_PT_RightPropertiesPanel(bpy.types.Panel):
|
||||||
bl_context = "object"
|
bl_context = "object"
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def poll(self,context):
|
def poll(self, context):
|
||||||
# only show the panel, if it's a textobject or a glyph
|
# only show the panel, if it's a textobject or a glyph
|
||||||
is_text = type(next((t for t in context.scene.abc3d_data.available_texts if t.text_object == context.active_object), None)) != type(None)
|
is_text = type(next((t for t in context.scene.abc3d_data.available_texts if t.text_object ==
|
||||||
is_glyph = type(next((t for t in context.scene.abc3d_data.available_texts if t.text_object == context.active_object.parent), None)) != type(None)
|
context.active_object), None)) != type(None)
|
||||||
|
is_glyph = type(next((t for t in context.scene.abc3d_data.available_texts if t.text_object ==
|
||||||
|
context.active_object.parent), None)) != type(None)
|
||||||
return is_text or is_glyph
|
return is_text or is_glyph
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
|
@ -1303,6 +1442,7 @@ class ABC3D_PT_RightPropertiesPanel(bpy.types.Panel):
|
||||||
|
|
||||||
def is_it_text():
|
def is_it_text():
|
||||||
return type(next((t for t in context.scene.abc3d_data.available_texts if t.text_object == context.active_object), None)) != type(None)
|
return type(next((t for t in context.scene.abc3d_data.available_texts if t.text_object == context.active_object), None)) != type(None)
|
||||||
|
|
||||||
def is_it_glyph():
|
def is_it_glyph():
|
||||||
return type(next((t for t in context.scene.abc3d_data.available_texts if t.text_object == context.active_object.parent), None)) != type(None)
|
return type(next((t for t in context.scene.abc3d_data.available_texts if t.text_object == context.active_object.parent), None)) != type(None)
|
||||||
|
|
||||||
|
@ -1334,6 +1474,7 @@ class ABC3D_PT_RightPropertiesPanel(bpy.types.Panel):
|
||||||
if is_glyph:
|
if is_glyph:
|
||||||
layout.row().label(text="Glyph Properties:")
|
layout.row().label(text="Glyph Properties:")
|
||||||
|
|
||||||
|
|
||||||
class ABC3D_OT_Reporter(bpy.types.Operator):
|
class ABC3D_OT_Reporter(bpy.types.Operator):
|
||||||
bl_idname = f"{__name__}.reporter"
|
bl_idname = f"{__name__}.reporter"
|
||||||
bl_label = "Report"
|
bl_label = "Report"
|
||||||
|
@ -1348,12 +1489,13 @@ class ABC3D_OT_Reporter(bpy.types.Operator):
|
||||||
)
|
)
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
#this is where I send the message
|
# this is where I send the message
|
||||||
self.report({'INFO'}, 'whatever')
|
self.report({'INFO'}, 'whatever')
|
||||||
for i in range(0,10):
|
for i in range(0, 10):
|
||||||
butils.ShowMessageBox('whatever','INFO','INFO')
|
butils.ShowMessageBox('whatever', 'INFO', 'INFO')
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
classes = (
|
classes = (
|
||||||
bimport.ImportGLTF2,
|
bimport.ImportGLTF2,
|
||||||
bimport.GetFontFacesInFile,
|
bimport.GetFontFacesInFile,
|
||||||
|
@ -1371,6 +1513,7 @@ classes = (
|
||||||
ABC3D_PT_TextManagement,
|
ABC3D_PT_TextManagement,
|
||||||
ABC3D_PT_FontCreation,
|
ABC3D_PT_FontCreation,
|
||||||
ABC3D_PT_TextPropertiesPanel,
|
ABC3D_PT_TextPropertiesPanel,
|
||||||
|
ABC3D_OT_OpenAssetDirectory,
|
||||||
ABC3D_OT_LoadInstalledFonts,
|
ABC3D_OT_LoadInstalledFonts,
|
||||||
ABC3D_OT_LoadFont,
|
ABC3D_OT_LoadFont,
|
||||||
ABC3D_OT_AddDefaultMetrics,
|
ABC3D_OT_AddDefaultMetrics,
|
||||||
|
@ -1386,7 +1529,8 @@ classes = (
|
||||||
ABC3D_OT_CreateFontFromObjects,
|
ABC3D_OT_CreateFontFromObjects,
|
||||||
ABC3D_PT_RightPropertiesPanel,
|
ABC3D_PT_RightPropertiesPanel,
|
||||||
ABC3D_OT_Reporter,
|
ABC3D_OT_Reporter,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def compare_text_object_with_object(t, o, strict=False):
|
def compare_text_object_with_object(t, o, strict=False):
|
||||||
for k in o.keys():
|
for k in o.keys():
|
||||||
|
@ -1394,7 +1538,7 @@ def compare_text_object_with_object(t, o, strict=False):
|
||||||
if o[k] != "textobject":
|
if o[k] != "textobject":
|
||||||
return False
|
return False
|
||||||
elif k.startswith(f"{utils.prefix()}_"):
|
elif k.startswith(f"{utils.prefix()}_"):
|
||||||
p = k.replace(f"{utils.prefix()}_","")
|
p = k.replace(f"{utils.prefix()}_", "")
|
||||||
if p in t.keys():
|
if p in t.keys():
|
||||||
if t[p] != o[k]:
|
if t[p] != o[k]:
|
||||||
return False
|
return False
|
||||||
|
@ -1406,6 +1550,7 @@ def compare_text_object_with_object(t, o, strict=False):
|
||||||
# if
|
# if
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def detect_text():
|
def detect_text():
|
||||||
scene = bpy.context.scene
|
scene = bpy.context.scene
|
||||||
abc3d_data = scene.abc3d_data
|
abc3d_data = scene.abc3d_data
|
||||||
|
@ -1415,9 +1560,11 @@ def detect_text():
|
||||||
if len(abc3d_data.available_texts) > linked_textobject \
|
if len(abc3d_data.available_texts) > linked_textobject \
|
||||||
and abc3d_data.available_texts[linked_textobject].text_object == o:
|
and abc3d_data.available_texts[linked_textobject].text_object == o:
|
||||||
t = abc3d_data.available_texts[linked_textobject]
|
t = abc3d_data.available_texts[linked_textobject]
|
||||||
a = test_availability(o["font_name"], o["face_name"], o["text"])
|
a = test_availability(
|
||||||
|
o["font_name"], o["face_name"], o["text"])
|
||||||
butils.transfer_blender_object_to_text_properties(o, t)
|
butils.transfer_blender_object_to_text_properties(o, t)
|
||||||
|
|
||||||
|
|
||||||
def load_used_glyphs():
|
def load_used_glyphs():
|
||||||
print("LOAD USED GLYPHS")
|
print("LOAD USED GLYPHS")
|
||||||
scene = bpy.context.scene
|
scene = bpy.context.scene
|
||||||
|
@ -1451,18 +1598,39 @@ def load_handler(self, dummy):
|
||||||
butils.run_in_main_thread(bpy.ops.abc3d.load_installed_fonts)
|
butils.run_in_main_thread(bpy.ops.abc3d.load_installed_fonts)
|
||||||
butils.run_in_main_thread(load_used_glyphs)
|
butils.run_in_main_thread(load_used_glyphs)
|
||||||
|
|
||||||
|
|
||||||
def load_handler_unload():
|
def load_handler_unload():
|
||||||
if bpy.app.timers.is_registered(butils.execute_queued_functions):
|
if bpy.app.timers.is_registered(butils.execute_queued_functions):
|
||||||
bpy.app.timers.unregister(butils.execute_queued_functions)
|
bpy.app.timers.unregister(butils.execute_queued_functions)
|
||||||
|
|
||||||
|
|
||||||
@persistent
|
@persistent
|
||||||
def on_frame_changed(self, dummy):
|
def on_frame_changed(self, dummy):
|
||||||
for t in bpy.context.scene.abc3d_data.available_texts:
|
for t in bpy.context.scene.abc3d_data.available_texts:
|
||||||
# TODO PERFORMANCE: only on demand
|
# TODO PERFORMANCE: only on demand
|
||||||
butils.set_text_on_curve(t)
|
butils.set_text_on_curve(t)
|
||||||
|
|
||||||
|
|
||||||
|
@persistent
|
||||||
|
def on_depsgraph_update(scene, depsgraph):
|
||||||
|
for u in depsgraph.updates:
|
||||||
|
if f"{utils.prefix()}_linked_textobject" in u.id.keys() \
|
||||||
|
and f"{utils.prefix()}_type" in u.id.keys() \
|
||||||
|
and u.id[f"{utils.prefix()}_type"] == 'textobject':
|
||||||
|
linked_textobject = u.id[f"{utils.prefix()}_linked_textobject"]
|
||||||
|
if u.is_updated_geometry and len(scene.abc3d_data.available_texts) > linked_textobject and not "prevent_recursion" in u.id:
|
||||||
|
u.id["prevent_recursion"] = True
|
||||||
|
butils.set_text_on_curve(
|
||||||
|
scene.abc3d_data.available_texts[linked_textobject])
|
||||||
|
elif "prevent_recursion" in u.id.keys():
|
||||||
|
del u.id["prevent_recursion"]
|
||||||
|
|
||||||
|
|
||||||
def register():
|
def register():
|
||||||
|
addon_updater_ops.register(bl_info)
|
||||||
|
|
||||||
for cls in classes:
|
for cls in classes:
|
||||||
|
addon_updater_ops.make_annotations(cls) # Avoid blender 2.8 warnings.
|
||||||
bpy.utils.register_class(cls)
|
bpy.utils.register_class(cls)
|
||||||
bpy.types.Scene.abc3d_data = bpy.props.PointerProperty(type=ABC3D_data)
|
bpy.types.Scene.abc3d_data = bpy.props.PointerProperty(type=ABC3D_data)
|
||||||
# bpy.types.Object.__del__ = lambda self: print(f"Bye {self.name}")
|
# bpy.types.Object.__del__ = lambda self: print(f"Bye {self.name}")
|
||||||
|
@ -1477,16 +1645,23 @@ def register():
|
||||||
if on_frame_changed not in bpy.app.handlers.frame_change_post:
|
if on_frame_changed not in bpy.app.handlers.frame_change_post:
|
||||||
bpy.app.handlers.frame_change_post.append(on_frame_changed)
|
bpy.app.handlers.frame_change_post.append(on_frame_changed)
|
||||||
|
|
||||||
|
if on_depsgraph_update not in bpy.app.handlers.depsgraph_update_post:
|
||||||
|
bpy.app.handlers.depsgraph_update_post.append(on_depsgraph_update)
|
||||||
|
|
||||||
butils.run_in_main_thread(butils.clear_available_fonts)
|
butils.run_in_main_thread(butils.clear_available_fonts)
|
||||||
# butils.run_in_main_thread(butils.load_installed_fonts)
|
# butils.run_in_main_thread(butils.load_installed_fonts)
|
||||||
butils.run_in_main_thread(butils.update_available_fonts)
|
butils.run_in_main_thread(butils.update_available_fonts)
|
||||||
|
butils.run_in_main_thread(butils.update_types)
|
||||||
|
|
||||||
# bpy.ops.abc3d.load_installed_fonts()
|
# bpy.ops.abc3d.load_installed_fonts()
|
||||||
|
|
||||||
Font.name_to_glyph_d = Font.generate_name_to_glyph_d()
|
Font.name_to_glyph_d = Font.generate_name_to_glyph_d()
|
||||||
|
|
||||||
|
|
||||||
def unregister():
|
def unregister():
|
||||||
for cls in classes:
|
addon_updater_ops.unregister()
|
||||||
|
|
||||||
|
for cls in reversed(classes):
|
||||||
bpy.utils.unregister_class(cls)
|
bpy.utils.unregister_class(cls)
|
||||||
|
|
||||||
# remove autostart when loading blend file
|
# remove autostart when loading blend file
|
||||||
|
@ -1501,6 +1676,6 @@ def unregister():
|
||||||
del bpy.types.Scene.abc3d_data
|
del bpy.types.Scene.abc3d_data
|
||||||
print(f"UNREGISTER {bl_info['name']}")
|
print(f"UNREGISTER {bl_info['name']}")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
register()
|
register()
|
||||||
|
|
||||||
|
|
|
@ -6,12 +6,15 @@ let g:jedi#environment_path = "venv"
|
||||||
|
|
||||||
""""""""""""""""""""""""""""""""" ALE
|
""""""""""""""""""""""""""""""""" ALE
|
||||||
|
|
||||||
"let g:ale_python_pylint_executable = '/home/jrkb/git/pointer/neomatter/font3d/font3d_blender_addon/venv/bin/pylint'
|
"let g:ale_python_pylint_executable = '/home/jrkb/git/pointer/neomatter/font3d/abc3d/venv/bin/pylint'
|
||||||
"let g:ale_python_executable='/home/jrkb/git/pointer/neomatter/font3d/font3d_blender_addon/venv/bin/python'
|
"let g:ale_python_executable='/home/jrkb/git/pointer/neomatter/font3d/abc3d/venv/bin/python'
|
||||||
"let g:ale_python_pylint_use_global=1
|
"let g:ale_python_pylint_use_global=1
|
||||||
"let g:ale_use_global_executables=1
|
"let g:ale_use_global_executables=1
|
||||||
"let g:ale_python_auto_pipenv=1
|
"let g:ale_python_auto_pipenv=1
|
||||||
"let g:ale_python_auto_virtualenv=1
|
"let g:ale_python_auto_virtualenv=1
|
||||||
"let g:ale_virtualenv_dir_names = ['venv']
|
"let g:ale_virtualenv_dir_names = ['venv']
|
||||||
|
|
||||||
|
"let g:ale_linters = { 'javascript': ['eslint', 'tsserver'], 'python': ['jedils', 'pylint', 'flake8'], 'cpp': ['cc', 'clangcheck', 'clangd', 'clangtidy', 'clazy', 'cppcheck', 'cpplint', 'cquery', 'cspell', 'flawfinder'], 'php': ['php_cs_fixer'] }
|
||||||
|
"let g:ale_fixers = { '*': ['remove_trailing_lines', 'trim_whitespace'], 'python': ['autopep8'], 'cpp': ['uncrustify'], 'javascript': js_fixers, 'css': ['prettier'], 'json': ['prettier'], 'php': ['php_cs_fixer'] }
|
||||||
|
|
||||||
let g:ale_pattern_options = {'\.py$': {'ale_enabled': 0}}
|
let g:ale_pattern_options = {'\.py$': {'ale_enabled': 0}}
|
||||||
|
|
1787
addon_updater.py
Normal file
1787
addon_updater.py
Normal file
File diff suppressed because it is too large
Load diff
1539
addon_updater_ops.py
Normal file
1539
addon_updater_ops.py
Normal file
File diff suppressed because it is too large
Load diff
35
butils.py
35
butils.py
|
@ -605,9 +605,21 @@ def is_mesh(o):
|
||||||
return type(o.data) == bpy.types.Mesh
|
return type(o.data) == bpy.types.Mesh
|
||||||
|
|
||||||
def is_metrics_object(o):
|
def is_metrics_object(o):
|
||||||
|
if f"{utils.prefix()}_type" in o:
|
||||||
|
return o[f"{utils.prefix()}_type"] == 'metrics'
|
||||||
return (re.match(".*_metrics$", o.name) != None or re.match(".*_metrics.[\d]{3}$", o.name) != None) and is_mesh(o)
|
return (re.match(".*_metrics$", o.name) != None or re.match(".*_metrics.[\d]{3}$", o.name) != None) and is_mesh(o)
|
||||||
|
|
||||||
|
def is_text_object(o):
|
||||||
|
if f"{utils.prefix()}_type" in o:
|
||||||
|
return o[f"{utils.prefix()}_type"] == 'textobject'
|
||||||
|
for t in bpy.context.scene.abc3d_data.available_texts:
|
||||||
|
if o == t.text_object:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
def is_glyph(o):
|
def is_glyph(o):
|
||||||
|
if f"{utils.prefix()}_type" in o:
|
||||||
|
return o[f"{utils.prefix()}_type"] == 'glyph'
|
||||||
try:
|
try:
|
||||||
return type(o.parent) is not type(None) \
|
return type(o.parent) is not type(None) \
|
||||||
and "glyphs" in o.parent.name \
|
and "glyphs" in o.parent.name \
|
||||||
|
@ -616,6 +628,14 @@ def is_glyph(o):
|
||||||
except ReferenceError as e:
|
except ReferenceError as e:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def update_types():
|
||||||
|
scene = bpy.context.scene
|
||||||
|
abc3d_data = scene.abc3d_data
|
||||||
|
for t in abc3d_data.available_texts:
|
||||||
|
t.text_object[f"{utils.prefix()}_type"] = "textobject"
|
||||||
|
for g in t.glyphs:
|
||||||
|
g.glyph_object[f"{utils.prefix()}_type"] = "glyph"
|
||||||
|
|
||||||
# blender bound_box vertices
|
# blender bound_box vertices
|
||||||
#
|
#
|
||||||
# 3------7.
|
# 3------7.
|
||||||
|
@ -678,6 +698,11 @@ def set_text_on_curve(text_properties, recursive=True):
|
||||||
if len(text_properties.text) != len(text_properties.glyphs):
|
if len(text_properties.text) != len(text_properties.glyphs):
|
||||||
regenerate = True
|
regenerate = True
|
||||||
|
|
||||||
|
# blender bug
|
||||||
|
# https://projects.blender.org/blender/blender/issues/100661
|
||||||
|
if mom.data.use_path:
|
||||||
|
regenerate = True
|
||||||
|
|
||||||
# if we regenerate.... delete objects
|
# if we regenerate.... delete objects
|
||||||
if regenerate:
|
if regenerate:
|
||||||
completely_delete_objects(glyph_objects)
|
completely_delete_objects(glyph_objects)
|
||||||
|
@ -749,7 +774,12 @@ def set_text_on_curve(text_properties, recursive=True):
|
||||||
location, tangent, spline_index = calc_point_on_bezier_curve(mom, advance, True, True)
|
location, tangent, spline_index = calc_point_on_bezier_curve(mom, advance, True, True)
|
||||||
if spline_index != previous_spline_index:
|
if spline_index != previous_spline_index:
|
||||||
is_newline = True
|
is_newline = True
|
||||||
|
|
||||||
|
if regenerate:
|
||||||
ob.location = mom.matrix_world @ (location + text_properties.translation)
|
ob.location = mom.matrix_world @ (location + text_properties.translation)
|
||||||
|
else:
|
||||||
|
ob.location = (location + text_properties.translation)
|
||||||
|
|
||||||
if not text_properties.ignore_orientation:
|
if not text_properties.ignore_orientation:
|
||||||
mask = [0]
|
mask = [0]
|
||||||
input_rotations = [mathutils.Vector((0.0, 0.0, 0.0))]
|
input_rotations = [mathutils.Vector((0.0, 0.0, 0.0))]
|
||||||
|
@ -765,7 +795,10 @@ def set_text_on_curve(text_properties, recursive=True):
|
||||||
ob.rotation_mode = 'QUATERNION'
|
ob.rotation_mode = 'QUATERNION'
|
||||||
q = mathutils.Quaternion()
|
q = mathutils.Quaternion()
|
||||||
q.rotate(text_properties.orientation)
|
q.rotate(text_properties.orientation)
|
||||||
|
if regenerate:
|
||||||
ob.rotation_quaternion = (mom.matrix_world @ motor[0] @ q.to_matrix().to_4x4()).to_quaternion()
|
ob.rotation_quaternion = (mom.matrix_world @ motor[0] @ q.to_matrix().to_4x4()).to_quaternion()
|
||||||
|
else:
|
||||||
|
ob.rotation_quaternion = (motor[0] @ q.to_matrix().to_4x4()).to_quaternion()
|
||||||
else:
|
else:
|
||||||
q = mathutils.Quaternion()
|
q = mathutils.Quaternion()
|
||||||
q.rotate(text_properties.orientation)
|
q.rotate(text_properties.orientation)
|
||||||
|
@ -812,6 +845,8 @@ def set_text_on_curve(text_properties, recursive=True):
|
||||||
|
|
||||||
if regenerate:
|
if regenerate:
|
||||||
mom.select_set(True)
|
mom.select_set(True)
|
||||||
|
# https://projects.blender.org/blender/blender/issues/100661
|
||||||
|
mom.data.use_path = False
|
||||||
mom[f"{utils.prefix()}_type"] = "textobject"
|
mom[f"{utils.prefix()}_type"] = "textobject"
|
||||||
mom[f"{utils.prefix()}_linked_textobject"] = text_properties.text_id
|
mom[f"{utils.prefix()}_linked_textobject"] = text_properties.text_id
|
||||||
mom[f"{utils.prefix()}_font_name"] = text_properties.font_name
|
mom[f"{utils.prefix()}_font_name"] = text_properties.font_name
|
||||||
|
|
|
@ -4,7 +4,7 @@ def get_version_major():
|
||||||
def get_version_minor():
|
def get_version_minor():
|
||||||
return 0
|
return 0
|
||||||
def get_version_patch():
|
def get_version_patch():
|
||||||
return 1
|
return 2
|
||||||
def get_version_string():
|
def get_version_string():
|
||||||
return f"{get_version_major()}.{get_version_minor()}.{get_version_patch}"
|
return f"{get_version_major()}.{get_version_minor()}.{get_version_patch}"
|
||||||
def prefix():
|
def prefix():
|
||||||
|
@ -30,6 +30,8 @@ def mapRange(in_value, in_min, in_max, out_min, out_max, clamp=False):
|
||||||
return max(out_max, min(out_min, output))
|
return max(out_max, min(out_min, output))
|
||||||
else:
|
else:
|
||||||
return output
|
return output
|
||||||
|
|
||||||
|
|
||||||
import warnings
|
import warnings
|
||||||
import functools
|
import functools
|
||||||
|
|
||||||
|
@ -47,6 +49,9 @@ def deprecated(func):
|
||||||
return func(*args, **kwargs)
|
return func(*args, **kwargs)
|
||||||
return new_func
|
return new_func
|
||||||
|
|
||||||
|
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
def open_file_browser(directory):
|
def open_file_browser(directory):
|
||||||
if sys.platform=='win32':
|
if sys.platform=='win32':
|
||||||
os.startfile(directory)
|
os.startfile(directory)
|
||||||
|
|
Loading…
Reference in a new issue