Skip to content

Commit

Permalink
feat: add translation inputs and highlight options
Browse files Browse the repository at this point in the history
  • Loading branch information
vspdi committed Dec 4, 2023
1 parent 755f90a commit 1857891
Show file tree
Hide file tree
Showing 5 changed files with 176 additions and 61 deletions.
1 change: 1 addition & 0 deletions apps/blender-addon/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
requests
3 changes: 2 additions & 1 deletion apps/blender-addon/src/components/messagebox.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import bpy

from bpy.props import StringProperty

class MessageBoxOperator(bpy.types.Operator):
bl_idname = "alcm.message_box_operator"
bl_label = "WebGL Studio Message"

message: bpy.props.StringProperty(default="Message")
message: StringProperty(default="Message")

def execute(self, context):
self.report({'INFO'}, self.message)
Expand Down
91 changes: 73 additions & 18 deletions apps/blender-addon/src/components/translations.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,19 @@
import bpy

from bpy.props import StringProperty, IntProperty, CollectionProperty, PointerProperty, BoolProperty
from bpy.props import StringProperty, CollectionProperty


def check_for_i18n_property(obj, prop_name_prefix):
if hasattr(obj, "__annotations__"):
for prop_name, prop_type in obj.__annotations__.items():
if prop_name.startswith(prop_name_prefix) and prop_type == bpy.types.I18nPropertyGroup:
return True
elif hasattr(obj, prop_name):
sub_obj = getattr(obj, prop_name)
if check_for_i18n_property(sub_obj, ""):
return True
return False
all_languages = [
("de", "German", "", 1),
("en", "English", "", 2)
]

language_name_map = {code: name for code, name, _, _ in all_languages}


class LanguageCodeItem(bpy.types.PropertyGroup):
bl_idname = "alcm.i18n_language_code"
code: bpy.props.StringProperty(name="Language Code", default="")
code: StringProperty(name="Language Code", default="")


class TranslationPropertyGroup(bpy.types.PropertyGroup):
Expand All @@ -31,16 +27,75 @@ class I18nPropertyGroup(bpy.types.PropertyGroup):
i18n: CollectionProperty(type=TranslationPropertyGroup)


class I18nPanel(bpy.types.Panel):
bl_idname = "ALCM_PT_i18n"
class I18nPanelBase:
bl_label = "Translations"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"

@classmethod
def poll(cls, context):
return check_for_i18n_property(context, "studio_") or check_for_i18n_property(context.scene, "studio_")
@staticmethod
def has_i18n_property_group(blender_data):
if blender_data:
for prop_name, prop_type in blender_data.bl_rna.properties.items():
if prop_name.startswith("studio_"):
prop_group = getattr(blender_data, prop_name, None)
show_i18n_method = getattr(prop_group, "show_i18n", None)
if isinstance(prop_group, bpy.types.PropertyGroup) and callable(show_i18n_method) and show_i18n_method():
for group_prop_name, _ in prop_group.bl_rna.properties.items():
group_prop = getattr(prop_group, group_prop_name, None)
if isinstance(group_prop, I18nPropertyGroup):
return True

return False

def draw(self, context):
layout = self.layout


layout.progress(text="Loading...", type="RING")

obj = context.object or context.scene
studio_settings = context.scene.studio_settings

i18n_props_by_lang = self.gather_i18n_properties(obj, studio_settings.languages)

if i18n_props_by_lang:
for lang_code, props in i18n_props_by_lang.items():
box = layout.box()
box.label(text=f"{language_name_map.get(lang_code, 'Unknown')} Translations", icon='WORLD_DATA')
for prop_name, prop in props.items():
row = box.row()
row.prop(prop, "translation", text=prop_name.replace('_', ' ').title())
else:
layout.label(text="No i18n properties found.")

def gather_i18n_properties(self, obj, languages):
i18n_props_by_lang = {lang.code: {} for lang in languages}
for prop_name, _ in obj.bl_rna.properties.items():
if prop_name.startswith("studio_") and isinstance(getattr(obj, prop_name, None), bpy.types.PropertyGroup):
studio_prop_group = getattr(obj, prop_name)
show_i18n_method = getattr(studio_prop_group, "show_i18n", None)
if callable(show_i18n_method) and show_i18n_method():
for group_prop_name, _ in studio_prop_group.bl_rna.properties.items():
prop = getattr(studio_prop_group, group_prop_name, None)
if isinstance(prop, I18nPropertyGroup):
for lang in prop.i18n:
if lang.code in i18n_props_by_lang:
i18n_props_by_lang[lang.code][group_prop_name] = lang
return i18n_props_by_lang


class I18nObjectPanel(I18nPanelBase, bpy.types.Panel):
bl_idname = "ALCM_PT_i18n_object"
bl_context = "object"

@classmethod
def poll(cls, context):
return context.object and cls.has_i18n_property_group(context.object)


class I18nScenePanel(I18nPanelBase, bpy.types.Panel):
bl_idname = "ALCM_PT_i18n_scene"
bl_context = "scene"

@classmethod
def poll(cls, context):
return context.scene and cls.has_i18n_property_group(context.scene)
48 changes: 32 additions & 16 deletions apps/blender-addon/src/highlight.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import bpy

from bpy.props import StringProperty, FloatProperty, PointerProperty

from mathutils import Vector

from .components.translations import I18nPropertyGroup


def set_parent_keep_transform(child_obj, parent_obj):
# Store the world space matrix
child_world_matrix = child_obj.matrix_world.copy()
Expand Down Expand Up @@ -44,7 +48,7 @@ def update_highlight_scale(self, context):
class HighlightSettingsPropertyGroup(bpy.types.PropertyGroup):
name = "Global Highlight Settings"
bl_idname = "alcm.highlight_settings"
scale: bpy.props.FloatProperty(
scale: FloatProperty(
name="Scale",
default=0.5,
min=0.01,
Expand All @@ -55,32 +59,42 @@ class HighlightSettingsPropertyGroup(bpy.types.PropertyGroup):
class HighlightPropertyGroup(bpy.types.PropertyGroup):
name = "Highlight"
bl_idname = "alcm.highlight"
highlight_id: bpy.props.StringProperty(
highlight_id: StringProperty(
name="Id",
update=update_highlight_id
)
name: I18nPropertyGroup
camera_object: bpy.props.PointerProperty(name="Camera Object", type=bpy.types.Object)
click_zone_object: bpy.props.PointerProperty(name="Click Zone Object", type=bpy.types.Object)
target_object: bpy.props.PointerProperty(name="Target Object", type=bpy.types.Object)
title: PointerProperty(name="Title", type=I18nPropertyGroup)
content: PointerProperty(name="Content", type=I18nPropertyGroup)
camera_object: PointerProperty(name="Camera Object", type=bpy.types.Object)
click_zone_object: PointerProperty(name="Click Zone Object", type=bpy.types.Object)
target_object: PointerProperty(name="Target Object", type=bpy.types.Object)

def show_i18n(self):
"""Determine whether to show the I18n panel based on highlight_id."""
return (
self.highlight_id != "" and
self.camera_object is not None and
self.click_zone_object is not None and
self.target_object is not None
)


class HighlightPartPropertyGroup(bpy.types.PropertyGroup):
name = "Highlight Part"
bl_idname = "alcm.highlight_part"
highlight_id: bpy.props.StringProperty(
highlight_id: StringProperty(
name="Id",
update=update_highlight_id
)
main_object: bpy.props.PointerProperty(name="Camera Object", type=bpy.types.Object)
main_object: PointerProperty(name="Camera Object", type=bpy.types.Object)


class AddHighlightOperator(bpy.types.Operator):
bl_idname = "alcm.highlight_add_operator"
bl_label = "Add Highlight"
bl_options = {'REGISTER', 'UNDO'}

highlight_id: bpy.props.StringProperty(name="Highlight ID")
highlight_id: StringProperty(name="Highlight ID")

def invoke(self, context, event):
return context.window_manager.invoke_props_dialog(self)
Expand Down Expand Up @@ -247,7 +261,7 @@ class SelectHighlightChildOperator(bpy.types.Operator):
bl_idname = "alcm.highlight_select_child"
bl_label = "Select Highlight Object"

object_name: bpy.props.StringProperty()
object_name: StringProperty()

def execute(self, context):
# Deselect all objects
Expand All @@ -266,7 +280,7 @@ class SetActiveCameraOperator(bpy.types.Operator):
bl_idname = "alcm.set_active_camera"
bl_label = "Set Active Camera"

camera_name: bpy.props.StringProperty()
camera_name: StringProperty()

def execute(self, context):
camera = bpy.data.objects.get(self.camera_name)
Expand Down Expand Up @@ -312,7 +326,8 @@ class HighlightPanel(bpy.types.Panel):

@classmethod
def poll(cls, context):
return context.object and hasattr(context.object, "studio_highlight") or hasattr(context.object, "studio_highlight_part")
return context.object and hasattr(context.object, "studio_highlight") or hasattr(context.object,
"studio_highlight_part")

def draw(self, context):
layout = self.layout
Expand Down Expand Up @@ -340,7 +355,8 @@ def draw(self, context):
# Button to delete the highlight
row = layout.box()
row.label(text="Actions:")
row.operator("alcm.highlight_delete_operator", text=f"Delete Highlight {highlight_props.highlight_id}", icon='TRASH')
row.operator("alcm.highlight_delete_operator", text=f"Delete Highlight {highlight_props.highlight_id}",
icon='TRASH')

if hasattr(obj, 'studio_highlight_part') and obj.studio_highlight_part.highlight_id != "":
highlight_part_props = obj.studio_highlight_part
Expand Down Expand Up @@ -384,9 +400,9 @@ def draw_func(self, context):

def register():
bpy.types.VIEW3D_MT_add.append(draw_func)
bpy.types.Scene.studio_highlight_settings = bpy.props.PointerProperty(type=HighlightSettingsPropertyGroup)
bpy.types.Object.studio_highlight = bpy.props.PointerProperty(type=HighlightPropertyGroup)
bpy.types.Object.studio_highlight_part = bpy.props.PointerProperty(type=HighlightPartPropertyGroup)
bpy.types.Scene.studio_highlight_settings = PointerProperty(type=HighlightSettingsPropertyGroup)
bpy.types.Object.studio_highlight = PointerProperty(type=HighlightPropertyGroup)
bpy.types.Object.studio_highlight_part = PointerProperty(type=HighlightPartPropertyGroup)


def unregister():
Expand Down
Loading

0 comments on commit 1857891

Please sign in to comment.