Skip to content

Commit 3e15857

Browse files
committed
Updated engon from monorepo commit fb392ce2ec7c6f941ea99a32e3466bae3f8d8161
1 parent af94cad commit 3e15857

26 files changed

+473
-660
lines changed

__init__.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,12 +132,12 @@
132132
bl_info = {
133133
"name": "engon",
134134
"author": "polygoniq xyz s.r.o.",
135-
"version": (1, 5, 0), # bump doc_url and version in register as well!
135+
"version": (1, 5, 1), # bump doc_url and version in register as well!
136136
"blender": (3, 6, 0),
137137
"location": "polygoniq tab in the sidebar of the 3D View window",
138138
"description": "Browse assets, filter and sort, scatter, animate, adjust rigs",
139139
"category": "Object",
140-
"doc_url": "https://docs.polygoniq.com/engon/1.5.0/",
140+
"doc_url": "https://docs.polygoniq.com/engon/1.5.1/",
141141
"tracker_url": "https://polygoniq.com/discord/",
142142
}
143143

@@ -158,7 +158,7 @@ def _post_register():
158158
def register():
159159
# We pass mock "bl_info" to the updater, as from Blender 4.2.0, the "bl_info" is
160160
# no longer available in this scope.
161-
addon_updater_ops.register({"version": (1, 5, 0)})
161+
addon_updater_ops.register({"version": (1, 5, 1)})
162162

163163
utils.register()
164164
pack_info_search_paths.register()

asset_helpers.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,12 @@
2020

2121
import typing
2222
import bpy
23+
import bisect
2324
import enum
2425
import os
2526
import glob
2627
import collections
28+
import random
2729
import logging
2830
from . import polib
2931
from . import asset_registry
@@ -55,6 +57,30 @@
5557
TQ_MODIFIER_LIBRARY_BLEND = "tq_Library_Modifiers.blend"
5658
TQ_EMERGENCY_LIGHTS_NODE_GROUP_NAME = "tq_Emergency_Lights"
5759
TQ_LICENSE_PLATE_NODE_GROUP_NAME_PREFIX = "tq_License-Plate_"
60+
# Mimics the distribution of car colors in the real world
61+
TQ_COLOR_DISTRIBUTION = (
62+
(0.0, (0.004, 0.004, 0.004)), # 0E0E0E
63+
(0.018, (0.063, 0.063, 0.063)), # 474747
64+
(0.031, (0.558, 0.558, 0.558)), # C5C5C5
65+
(0.041, (0.216, 0.004, 0.175)), # 800E74
66+
(0.043, (0.012, 0.001, 0.028)), # 1D042F
67+
(0.045, (0.295, 0.185, 0.0)), # 947700
68+
(0.053, (0.271, 0.22, 0.126441)), # 8E8164
69+
(0.060, (0.04, 0.099, 0.006)), # 385913
70+
(0.070, (0.006, 0.026, 0.002)), # 132D07
71+
(0.074, (0.106, 0.192, 0.009)), # 5C7918
72+
(0.078, (0.014, 0.183, 0.152)), # 1F766D
73+
(0.081, (0.043, 0.017, 0.003)), # 3B2309
74+
(0.101, (0.096, 0.0, 0.002)), # 570006
75+
(0.173, (0.333, 0.07, 0.0)), # 9C4B00
76+
(0.178, (0.282, 0.0, 0.0)), # 910000
77+
(0.2, (0.002, 0.011, 0.042)), # 071B3A
78+
(0.278, (0.006, 0.054, 0.264)), # 11428C
79+
(0.3, (0.187, 0.187, 0.187)), # 787878
80+
(0.45, (0.037, 0.037, 0.037)), # 363636
81+
(0.6, (0.558, 0.558, 0.558)), # C5C5C5
82+
(0.8, (0.004, 0.004, 0.004)), # 0E0E0E
83+
)
5884

5985

6086
PARTICLE_SYSTEM_PREFIX = f"engon_{polib.asset_pack.PARTICLE_SYSTEM_TOKEN}_"
@@ -271,3 +297,9 @@ def gather_instanced_objects(
271297
and instance_collection is not None
272298
):
273299
yield from instance_collection.all_objects
300+
301+
302+
def get_car_color() -> typing.Tuple[float, float, float]:
303+
value = random.random()
304+
idx = bisect.bisect(TQ_COLOR_DISTRIBUTION, value, key=lambda x: x[0]) - 1
305+
return TQ_COLOR_DISTRIBUTION[idx][1]

blend_maintenance/asset_changes.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,31 @@ class AssetPackMigrations(typing.NamedTuple):
2727

2828
# versions in the names reflect the last version of asset pack without given changes
2929

30+
_botaniq_7_0_0_larix_decidua_variant = {
31+
r"^bq_Tree_Larix-decidua_([ABC])_spring-summer-autumn": r"bq_Tree_Larix-decidua_\1_spring-summer",
32+
}
33+
34+
botaniq_7_0_0_larix_decidua_variant = AssetPackMigration(
35+
[
36+
RegexMapping(re.compile(f"{pattern}.blend$"), f"{replacement}.blend")
37+
for pattern, replacement in _botaniq_7_0_0_larix_decidua_variant.items()
38+
],
39+
{
40+
"collections": [
41+
RegexMapping(re.compile(pattern), replacement)
42+
for pattern, replacement in _botaniq_7_0_0_larix_decidua_variant.items()
43+
],
44+
"meshes": [
45+
RegexMapping(re.compile(pattern), replacement)
46+
for pattern, replacement in _botaniq_7_0_0_larix_decidua_variant.items()
47+
],
48+
"objects": [
49+
RegexMapping(re.compile(pattern), replacement)
50+
for pattern, replacement in _botaniq_7_0_0_larix_decidua_variant.items()
51+
],
52+
},
53+
)
54+
3055
_botaniq_7_0_0_drop_with_in_pps_names = {
3156
r"^bq_pps_Grass_With-flowers_A_spring-summer": r"bq_pps_Grass_Wildflowers_A_spring-summer",
3257
r"^bq_pps_Grass_With-flowers_B_spring-summer": r"bq_pps_Grass_Flowers-decorative_B_spring-summer",
@@ -349,6 +374,7 @@ class AssetPackMigrations(typing.NamedTuple):
349374
botaniq_6_8_0_decapitalize_cortaderia,
350375
botaniq_7_0_0_drop_dead_from_leaf_names,
351376
botaniq_7_0_0_drop_with_in_pps_names,
377+
botaniq_7_0_0_larix_decidua_variant,
352378
],
353379
),
354380
AssetPackMigrations(

blender_manifest.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
schema_version = "1.0.0"
22

33
id = "engon"
4-
version = "1.5.0"
4+
version = "1.5.1"
55
name = "engon"
66
tagline = "Browse assets, filter and sort, scatter, animate, adjust rigs"
77
maintainer = "polygoniq <[email protected]>"

clicker.py

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
# Code inspired by the 'CLICKR' addon by Oliver J Post
2222

2323
import bpy
24-
import bpy_extras
24+
import bpy_extras.view3d_utils
2525
import math
2626
import mathutils
2727
import typing
@@ -98,10 +98,6 @@ def __init__(self, *args, **kwargs):
9898
# Properties controlling the UI state - e. g. tint of the buttons, based on the events
9999
self.is_scaling = False
100100

101-
Clicker.draw_2d_handler_ref = bpy.types.SpaceView3D.draw_handler_add(
102-
self.draw_px, (), 'WINDOW', 'POST_PIXEL'
103-
)
104-
105101
@staticmethod
106102
def remove_draw_handlers() -> None:
107103
if hasattr(Clicker, "draw_2d_handler_ref") and Clicker.draw_2d_handler_ref is not None:
@@ -158,7 +154,12 @@ def draw_px(self):
158154

159155
@classmethod
160156
def poll(cls, context: bpy.types.Context) -> bool:
161-
return len(context.selected_objects) > 0 and context.mode == 'OBJECT'
157+
return (
158+
context.region_data is not None
159+
and isinstance(context.region_data, bpy.types.RegionView3D)
160+
and len(context.selected_objects) > 0
161+
and context.mode == 'OBJECT'
162+
)
162163

163164
def execute(self, context: bpy.types.Context):
164165
return {'FINISHED'}
@@ -210,7 +211,7 @@ def modal(self, context: bpy.types.Context, event: bpy.types.Event):
210211
context.window.cursor_modal_restore()
211212
return {'PASS_THROUGH'}
212213

213-
if area is not None and area.type != 'VIEW_3D':
214+
if area is None or area.type != 'VIEW_3D':
214215
context.window.cursor_modal_set('STOP')
215216
return {'RUNNING_MODAL'}
216217

@@ -473,6 +474,13 @@ def invoke(self, context: bpy.types.Context, event: bpy.types.Event):
473474
self.models_collection.hide_viewport = True
474475

475476
self.choose_next_object(context)
477+
478+
# Register the draw handler for the clicker help UI
479+
assert Clicker.draw_2d_handler_ref is None, "Clicker draw handler is already registered!"
480+
Clicker.draw_2d_handler_ref = bpy.types.SpaceView3D.draw_handler_add(
481+
self.draw_px, (), 'WINDOW', 'POST_PIXEL'
482+
)
483+
476484
context.window_manager.modal_handler_add(self)
477485
Clicker.is_running = True
478486
logger.info(

features/botaniq_animations/animations.py

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,14 @@ def copy_animation_data(source: bpy.types.Object, target: bpy.types.Object) -> b
283283
if target.animation_data is None:
284284
target.animation_data_create()
285285
assert target.animation_data is not None
286-
target.animation_data.action = source.animation_data.action.copy()
286+
action_copy = source.animation_data.action.copy()
287+
target.animation_data.action = action_copy
288+
# Force assign an action to a slot. In blender 4.4+ slots were introduced and in some cases
289+
# assigning an action fails to auto-assign a slot. We force assign a slot to prevent leaving
290+
# the datablocks in non-animated state
291+
# https://developer.blender.org/docs/release_notes/4.4/python_api/#breaking
292+
if bpy.app.version >= (4, 4, 0):
293+
target.animation_data.action_slot = action_copy.slots[0]
287294
animation_type = source.animation_data.action.name.rsplit("_", 1)[0]
288295
target.animation_data.action.name = f"{animation_type}_Instance"
289296
return target.animation_data.action
@@ -586,12 +593,12 @@ def change_preset(
586593
"""Changes preset of 'obj' by switching the action of the same animation type to 'preset'"""
587594
anim_type, _ = parse_action_name(obj.animation_data.action)
588595
anim_library = bpy.data.libraries.get(os.path.basename(animation_library_path), None)
589-
if anim_library is None:
596+
preset_action_name = f"bq_{anim_type}_{preset}"
597+
if anim_library is None or preset_action_name not in bpy.data.actions:
590598
anim_library, _, _ = link_animation_data(anim_type, animation_library_path)
591599

592600
assert anim_library is not None
593601

594-
preset_action_name = f"bq_{anim_type}_{preset}"
595602
preset_action = bpy.data.actions.get((preset_action_name, anim_library.filepath), None)
596603
assert preset_action is not None
597604

@@ -618,6 +625,12 @@ def change_preset(
618625
new_action = preset_action.copy()
619626
assert obj.animation_data is not None
620627
obj.animation_data.action = new_action
628+
# Force assign an action to a slot. In blender 4.4+ slots were introduced and in some cases
629+
# assigning an action fails to auto-assign a slot. We force assign a slot to prevent leaving
630+
# the datablocks in non-animated state
631+
# https://developer.blender.org/docs/release_notes/4.4/python_api/#breaking
632+
if bpy.app.version >= (4, 4, 0):
633+
obj.animation_data.action_slot = new_action.slots[0]
621634

622635
set_animation_strength(new_action, strength)
623636
# We know here that helper_objs didn't change while changing preset thus they should have
@@ -1528,7 +1541,14 @@ def duplicate_animation_instance(
15281541
# data is linked into it. This new collection can be used for further instantiation.
15291542
previous_object = original_collection.objects[0]
15301543
new_object = polib.asset_pack_bpy.copy_object_hierarchy(previous_object)
1531-
new_object.animation_data.action = new_object.animation_data.action.copy()
1544+
new_action = new_object.animation_data.action.copy()
1545+
new_object.animation_data.action = new_action
1546+
# Force assign an action to a slot. In blender 4.4+ slots were introduced and in some cases
1547+
# assigning an action fails to auto-assign a slot. We force assign a slot to prevent leaving
1548+
# the datablocks in non-animated state
1549+
# https://developer.blender.org/docs/release_notes/4.4/python_api/#breaking
1550+
if bpy.app.version >= (4, 4, 0):
1551+
new_object.animation_data.action_slot = new_action.slots[0]
15321552

15331553
new_collection = original_collection.copy()
15341554
polib.asset_pack_bpy.collection_unlink_hierarchy(new_collection, previous_object)

features/botaniq_animations/botaniq_animations.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import typing
2323
import os
2424
import enum
25+
import logging
2526

2627
from bpy.types import ID
2728
from . import animations
@@ -30,6 +31,7 @@
3031
from ... import polib
3132
from ... import preferences
3233

34+
logger = logging.getLogger(f"polygoniq.{__name__}")
3335

3436
MODULE_CLASSES = []
3537

@@ -413,6 +415,11 @@ def draw(self, context: bpy.types.Context):
413415
for mod_name, fmod_limits in sorted(
414416
animations.get_animation_state_control_modifiers(action), key=lambda x: x[0]
415417
):
418+
modifier = animated_object.modifiers.get(mod_name, None)
419+
if modifier is None:
420+
logger.warning(f"Modifier {mod_name} not found on object {animated_object.name}")
421+
continue
422+
416423
row = col.row(align=True)
417424
row.label(text=f"{mod_name[len('bq_'):]}")
418425

@@ -424,7 +431,7 @@ def draw(self, context: bpy.types.Context):
424431
else:
425432
amplitude_col.label(text="Not Controllable")
426433

427-
row.prop(animated_object.modifiers[mod_name], "show_viewport", text="")
434+
row.prop(modifier, "show_viewport", text="")
428435
# For some reason next icon from the desired one has to be used: AUTO => CHECKMARK
429436
row.prop(
430437
fmod_limits, "mute", text="", icon='AUTO' if fmod_limits.mute is True else 'BLANK1'

0 commit comments

Comments
 (0)