Skip to content

Commit

Permalink
feat: add languages to blender addon scene settigns
Browse files Browse the repository at this point in the history
  • Loading branch information
vspdi committed Dec 4, 2023
1 parent c0f1773 commit 755f90a
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 114 deletions.
2 changes: 1 addition & 1 deletion apps/blender-addon/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
},
"configurations": {
"unix": {
"args": "--blenderPythonPath=$(BLENDER_PYTHON_PATH) --cwd=$(pwd)"
"args": "--blenderPythonPath=$BLENDER_PYTHON_PATH --cwd=$(pwd)"
},
"windows-powershell": {
"args": "--blenderPythonPath=%BLENDER_PYTHON_PATH% --cwd=%cd%"
Expand Down
115 changes: 19 additions & 96 deletions apps/blender-addon/src/components/translations.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,52 +3,32 @@
from bpy.props import StringProperty, IntProperty, CollectionProperty, PointerProperty, BoolProperty


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


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


class TranslationPropertyGroup(bpy.types.PropertyGroup):
bl_idname = "alcm.translations"
language_key: StringProperty(name="Language Key", description="Enter the language key", default="")
translation: StringProperty(name="Translation", description="Enter the translation", default="")
bl_idname = "alcm.i18n_translation"
code: StringProperty(name="Language Code", description="Language code", default="")
translation: StringProperty(name="Translation", description="Translation", default="")


class I18nPropertyGroup(bpy.types.PropertyGroup):
name = 'bnre'
bl_idname = "alcm.i18n"
value: CollectionProperty(type=TranslationPropertyGroup)
active_index: IntProperty(name="Active Index", default=0)


def is_i18n_property(obj, property_name):
return hasattr(obj, property_name) and isinstance(getattr(obj, property_name), I18nPropertyGroup)


def has_i18n_property(obj):
for attr in dir(obj):
if is_i18n_property(obj, attr):
return True


class TranslationUIList(bpy.types.UIList):
bl_idname = "ALCM_UL_TranslationList"

def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):

if self.layout_type in {'DEFAULT', 'COMPACT'}:
split = layout.split(factor=0.25)
split.prop(item, "language_key", text="", emboss=True, translate=False, icon="WORLD")
split = split.split(factor=1.0)
row = split.row(align=True)
row.prop(item, "translation", text="", emboss=True, translate=False, icon="TEXT")
op = row.operator(RemoveTranslationOperator.bl_idname, text="", icon="X")
op.index = index
op.property_name = 'data'

elif self.layout_type in {'GRID'}:
layout.alignment = 'CENTER'
layout.label(text="", icon_value=icon)
i18n: CollectionProperty(type=TranslationPropertyGroup)


class I18nPanel(bpy.types.Panel):
Expand All @@ -59,65 +39,8 @@ class I18nPanel(bpy.types.Panel):

@classmethod
def poll(cls, context):
if context.object is None:
return has_i18n_property(context.scene)
else:
return has_i18n_property(context.object)
return check_for_i18n_property(context, "studio_") or check_for_i18n_property(context.scene, "studio_")

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

target = context.scene if context.object is None else context.object
for attr in dir(target):
if is_i18n_property(target, attr):
attribute = getattr(target, attr)
attribute_name = attribute.name if attribute.name else attr
layout.label(text="Key: {}".format(attribute_name))

row = layout.row()
row.template_list(TranslationUIList.bl_idname, "", attribute, "value", attribute, "active_index")

row = layout.row()
op = row.operator(AddTranslationOperator.bl_idname, icon='ADD', text="Add Translation")
op.use_scene = context.object is None
op.property_name = attr


class AddTranslationOperator(bpy.types.Operator):
bl_idname = "alcm.scene_add_translation"
bl_label = "Add Translation"

use_scene: BoolProperty()
property_name: StringProperty()

def execute(self, context):
target = context.scene if self.use_scene else context.object
if is_i18n_property(target, self.property_name):
i18n_property = getattr(target, self.property_name)
i18n_property.value.add()
i18n_property.active_index = len(i18n_property.value) - 1
return {'FINISHED'}
else:
return {'CANCELLED'}


class RemoveTranslationOperator(bpy.types.Operator):
bl_idname = "alcm.scene_remove_translation"
bl_label = "Remove Translation"

use_scene: BoolProperty()
property_name: StringProperty()
index: bpy.props.IntProperty()

def execute(self, context):
target = context.scene if self.use_scene else context.object
if is_i18n_property(target, self.property_name):
i18n_property = getattr(target, self.property_name)
i18n_property.value.remove(self.index)
i18n_property.active_index = max(0, min(i18n_property.active_index, len(i18n_property.value) - 1))

return {'FINISHED'}
else:
return {'CANCELLED'}


4 changes: 3 additions & 1 deletion apps/blender-addon/src/highlight.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import bpy
from mathutils import Vector

from .components.translations import I18nPropertyGroup

def set_parent_keep_transform(child_obj, parent_obj):
# Store the world space matrix
Expand Down Expand Up @@ -58,6 +59,7 @@ class HighlightPropertyGroup(bpy.types.PropertyGroup):
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)
Expand Down Expand Up @@ -340,7 +342,7 @@ def draw(self, context):
row.label(text="Actions:")
row.operator("alcm.highlight_delete_operator", text=f"Delete Highlight {highlight_props.highlight_id}", icon='TRASH')

if hasattr(obj, 'studio_highlight_part'):
if hasattr(obj, 'studio_highlight_part') and obj.studio_highlight_part.highlight_id != "":
highlight_part_props = obj.studio_highlight_part

# Display the Highlight ID
Expand Down
72 changes: 56 additions & 16 deletions apps/blender-addon/src/settings.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,30 @@
import bpy

from bpy.props import PointerProperty, StringProperty, CollectionProperty
from bpy.props import PointerProperty, StringProperty, CollectionProperty, EnumProperty
from .components.translations import LanguageCodeItem


all_languages = [
("de", "German", "", 1),
("en", "English", "", 2)
]

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


def get_available_languages(self, context):
if hasattr(context.scene, "studio_settings") and hasattr(context.scene.studio_settings, "languages"):
used_language_codes = {lang.code for lang in context.scene.studio_settings.languages}
return [lang for lang in all_languages if lang[0] not in used_language_codes]
else:
return all_languages


class StudioSettingsPropertyGroup(bpy.types.PropertyGroup):
bl_idname = "alcm.studio_settings"
resource_id: StringProperty(name="Resource ID", description="Enter the resource ID", default="")
available_languages: CollectionProperty(type=LanguageCodeItem, name="Languages")
languages: CollectionProperty(type=LanguageCodeItem, name="Languages")
available_languages: EnumProperty(items=get_available_languages, name="Available Languages")


class StudioSettingsPanel(bpy.types.Panel):
Expand All @@ -24,27 +41,47 @@ def draw(self, context):

layout.prop(scene.studio_settings, "resource_id")

# UI List for available_languages
# UI BOX for languages
box = layout.box()
box.label(text="Available Languages:")
for i, lang_item in enumerate(studio_settings.available_languages):

row = box.row()
row.label(text="Languages:")
for i, lang_item in enumerate(studio_settings.languages):
row = box.row()
row.prop(lang_item, "code", text="Language Code")
row.label(text=f"{language_name_map.get(lang_item.code)}")
remove_op = row.operator("alcm.remove_language", text="", icon='X')
remove_op.index = i

# Add/Remove buttons
row = layout.row()
row.operator("alcm.add_language", text="Add Language", icon='ADD')

# Check if the enum has any items
enum_items = get_available_languages(self, context)
if enum_items:
box.label(text="Available Languages:")
row = box.row()
row.prop(studio_settings, "available_languages", text="Add")
# Add buttons
row = box.row()
op = row.operator("alcm.add_language", text="Add Language", icon='ADD')
op.code = studio_settings.available_languages
else:
layout.label(text="All available language keys are used.")


class AddLanguageOperator(bpy.types.Operator):
bl_idname = "alcm.add_language"
bl_label = "Add Language"

code: bpy.props.StringProperty()

def execute(self, context):
item = context.scene.studio_settings.available_languages.add()
item.code = "New Language"
studio_settings = context.scene.studio_settings
used_codes = [lang.code for lang in studio_settings.languages] + [self.code]
available_languages = [lang for lang in all_languages if lang[0] not in used_codes]

if available_languages:
studio_settings.available_languages = available_languages[0][0]

lang = studio_settings.languages.add()
lang.code = self.code
return {'FINISHED'}


Expand All @@ -56,16 +93,19 @@ class RemoveLanguageOperator(bpy.types.Operator):

@classmethod
def poll(cls, context):
return len(context.scene.studio_settings.available_languages) > 0
return len(context.scene.studio_settings.languages) > 0

def execute(self, context):
languages = context.scene.studio_settings.available_languages
studio_settings = context.scene.studio_settings
languages = studio_settings.languages
if self.index < len(languages):
languages.remove(self.index)
return {'FINISHED'}


def register():
bpy.types.Scene.studio_settings = PointerProperty(type=StudioSettingsPropertyGroup)
# bpy.types.Scene.i18nName = PointerProperty(type=I18nPropertyGroup, name="Name")
# bpy.types.Scene.i18nDescription = PointerProperty(type=I18nPropertyGroup, name="Description")


def unregister():
del bpy.types.Scene.studio_settings

0 comments on commit 755f90a

Please sign in to comment.