# SPDX-License-Identifier: GPL-2.0-only """ A 3D font helper """ bl_info = { "name": "Font3D", "author": "Jakob Schlötter, Studio Pointer*", "version": (0, 0, 1), "blender": (4, 1, 0), "location": "wherever it may be", "description": "Does Font3D stuff", "category": "Typography", } import bpy import math import io import functools from bpy.types import Panel from bpy.app.handlers import persistent from random import uniform import time import datetime def get_timestamp(): return datetime.datetime.fromtimestamp(time.time()).strftime('%Y.%m.%d-%H:%M:%S') class SharedVariables(): fonts: dict = {} def __init__(self, **kv): self.__dict__.update(kv) shared = SharedVariables() def mapRange(in_value, in_min, in_max, out_min, out_max, clamp=False): output = out_min + ((out_max - out_min) / (in_max - in_min)) * (in_value - in_min) if clamp: if out_min < out_max: return min(out_max, max(out_min, output)) else: return max(out_max, min(out_min, output)) else: return output class FONT3D_OT_Font3D(bpy.types.Operator): """Font 3D""" bl_idname = "font3d.font3d" bl_label = "Font 3D" bl_options = {'REGISTER', 'UNDO'} def execute(self, context): global shared print("Font3d execute()") scene = bpy.context.scene file_dir = scene.font3d.file_dir print(f"file_dir: {file_dir}") return {'FINISHED'} class FONT3D_settings(bpy.types.PropertyGroup): font_path: bpy.props.StringProperty(name="Font path", description="Where is the font", default="", maxlen=1024, subtype="FILE_PATH") class FONT3D_PT_panel(bpy.types.Panel): bl_label = "Panel for Font3D" bl_category = "Font3D" bl_space_type = "VIEW_3D" bl_region_type = "UI" def draw(self, context): layout = self.layout wm = context.window_manager scene = context.scene font3d = scene.font3d layout.label(text="Load FontFile:") layout.row().prop(font3d, "font_path") layout.row().operator('font3d.loadfont', text='Load Font') layout.label(text='DEBUG') layout.row().operator('font3d.testfont', text='Test Font') class FONT3D_OT_LoadFont(bpy.types.Operator): """Load Font 3D""" bl_idname = "font3d.loadfont" bl_label = "Load Font" bl_options = {'REGISTER', 'UNDO'} def execute(self, context): global shared scene = bpy.context.scene print(f"loading da font at path {scene.font3d.font_path}") currentObjects = [] for ob in bpy.data.objects: currentObjects.append(ob.name) bpy.ops.import_scene.gltf(filepath=scene.font3d.font_path) newObjects = [] fontcollection = bpy.data.collections.new("Font3D") scene.collection.children.link(fontcollection) font = { "name": "", "glyphs": [] } for o in bpy.data.objects: if o.name not in currentObjects: if (o.parent == None): print(f"found root node --> {o.name}") font['name'] = o.name elif o.parent.name.startswith("glyphs"): print(f"loading glyph --> {o.name}") font['glyphs'].append(o) newObjects.append(o.name) scene.collection.objects.unlink(o) fontcollection.objects.link(o) try: shared.fonts except: shared.fonts = {} shared.fonts[font['name']] = font return {'FINISHED'} class FONT3D_OT_TestFont(bpy.types.Operator): """Test Font 3D""" bl_idname = "font3d.testfont" bl_label = "Test Font" bl_options = {'REGISTER', 'UNDO'} def execute(self, context): global shared scene = bpy.context.scene print(shared.fonts) return {'FINISHED'} classes = ( FONT3D_OT_Font3D, FONT3D_settings, FONT3D_PT_panel, FONT3D_OT_TestFont, FONT3D_OT_LoadFont ) def register(): for cls in classes: bpy.utils.register_class(cls) bpy.types.Scene.font3d = bpy.props.PointerProperty(type=FONT3D_settings) # would love to properly auto start this, but IT DOES NOT WORK # if load_handler not in bpy.app.handlers.load_post: # bpy.app.handlers.load_post.append(load_handler) 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: bpy.utils.unregister_class(cls) del bpy.types.Scene.font3d if __name__ == '__main__': register()