@@ -169,6 +169,95 @@ def execute(self, context):
169
169
return {'FINISHED' }
170
170
171
171
172
+ class DOW_OT_select_all_actions (bpy .types .Operator ):
173
+ """Change selection for multiple actions"""
174
+
175
+ bl_idname = 'object.dow_select_all_actions'
176
+ bl_label = 'Select all actions'
177
+ bl_options = {'REGISTER' }
178
+
179
+ status : bpy .props .BoolProperty ()
180
+
181
+ def execute (self , context ):
182
+ for i in context .popup_operator .actions :
183
+ i .force_invisible = self .status
184
+ return {'FINISHED' }
185
+
186
+
187
+ class DOW_UL_action_settings (bpy .types .UIList ):
188
+ def draw_item (self , context , layout , data , item , icon , active_data , active_propname ):
189
+ row = layout .row ()
190
+ row = row .split (factor = 0.02 )
191
+ row .prop (item , 'force_invisible' , icon_only = True , text = '' )
192
+ row .label (text = item .name )
193
+
194
+
195
+ class ActionSettings (bpy .types .PropertyGroup ):
196
+ name : bpy .props .StringProperty ()
197
+ force_invisible : bpy .props .BoolProperty ()
198
+
199
+
200
+ class DOW_OT_configure_invisible (bpy .types .Operator ):
201
+ """Configure force_invisible for multiple animations"""
202
+
203
+ bl_idname = 'object.dow_batch_configure_force_invisible'
204
+ bl_label = 'Batch configure force_invisible'
205
+ bl_options = {'REGISTER' }
206
+
207
+ prop_name : bpy .props .StringProperty ()
208
+ actions : bpy .props .CollectionProperty (type = ActionSettings )
209
+ selected_index : bpy .props .IntProperty ()
210
+
211
+ @classmethod
212
+ def poll (cls , context ):
213
+ return (
214
+ context .active_object .type == 'MESH'
215
+ and props .get_mesh_prop_owner (context .active_object ) is not None
216
+ )
217
+
218
+ def execute (self , context ):
219
+ fcurve_data_paths = [f'["{ self .prop_name } "]' , f"['{ self .prop_name } ']" ]
220
+ for d in self .actions :
221
+ if d .name not in bpy .data .actions :
222
+ continue
223
+ action = bpy .data .actions .get (d .name )
224
+ for fcurve in action .fcurves :
225
+ if fcurve .is_empty :
226
+ continue
227
+ if any (fcurve .data_path == p for p in fcurve_data_paths ):
228
+ action .fcurves .remove (fcurve )
229
+ if d .force_invisible :
230
+ fcurve = action .fcurves .new (fcurve_data_paths [0 ])
231
+ fcurve .keyframe_points .insert (0 , 1 )
232
+ return {'FINISHED' }
233
+
234
+ def invoke (self , context , event ):
235
+ wm = context .window_manager
236
+ fcurve_data_paths = [f'["{ self .prop_name } "]' , f"['{ self .prop_name } ']" ]
237
+ for action in bpy .data .actions :
238
+ it = self .actions .add ()
239
+ it .name = action .name
240
+ for fcurve in action .fcurves :
241
+ if fcurve .is_empty :
242
+ continue
243
+ if any (fcurve .data_path == p for p in fcurve_data_paths ):
244
+ keyframes = fcurve .keyframe_points
245
+ if not keyframes :
246
+ continue
247
+ it .force_invisible = bool (keyframes [0 ].co [1 ])
248
+ break
249
+ return wm .invoke_props_dialog (self , width = 500 )
250
+
251
+ def draw (self , context ):
252
+ layout = self .layout
253
+ layout .row ().label (text = 'Actions' )
254
+ layout .template_list ('DOW_UL_action_settings' , '' , self , 'actions' , self , 'selected_index' )
255
+ row = layout .row ()
256
+ row .context_pointer_set (name = 'popup_operator' , data = self )
257
+ row .operator (DOW_OT_select_all_actions .bl_idname , text = 'Deselect All' ).status = False
258
+ row .operator (DOW_OT_select_all_actions .bl_idname , text = 'Select All' ).status = True
259
+
260
+
172
261
class DowTools (bpy .types .Panel ):
173
262
bl_label = 'DoW Tools'
174
263
bl_idname = 'VIEW3D_PT_dow_tools'
@@ -187,13 +276,19 @@ def draw(self, context):
187
276
layout .row ().label (text = 'Mesh is not parented to an armature' , icon = 'ERROR' )
188
277
else :
189
278
for prop in props .REMOTE_PROPS ['MESH' ]:
279
+ prop_name = props .create_prop_name (prop , context .active_object .name )
280
+ row = layout .row ()
190
281
make_prop_row (
191
- layout ,
282
+ row ,
192
283
remote_prop_owner ,
193
- prop_name = props . create_prop_name ( prop , context . active_object . name ) ,
284
+ prop_name = prop_name ,
194
285
display_name = prop ,
195
286
driver_obj = context .active_object ,
196
287
)
288
+ if prop == 'force_invisible' and prop_name in remote_prop_owner :
289
+ op = row .operator (DOW_OT_configure_invisible .bl_idname , text = '' , icon = 'OPTIONS' )
290
+ op .prop_name = prop_name
291
+
197
292
make_prop_row (layout , context .active_object , 'xref_source' )
198
293
if context .active_pose_bone is not None :
199
294
layout .row ().prop (context .active_pose_bone , 'name' )
@@ -333,6 +428,10 @@ def register():
333
428
bpy .utils .register_class (DOW_OT_attach_object )
334
429
bpy .utils .register_class (DOW_OT_detach_object )
335
430
bpy .utils .register_class (DOW_OT_convert_to_marker )
431
+ bpy .utils .register_class (DOW_OT_select_all_actions )
432
+ bpy .utils .register_class (DOW_UL_action_settings )
433
+ bpy .utils .register_class (ActionSettings )
434
+ bpy .utils .register_class (DOW_OT_configure_invisible )
336
435
for t in [
337
436
bpy .types .Object ,
338
437
bpy .types .Material ,
@@ -364,6 +463,10 @@ def unregister():
364
463
bpy .types .PoseBone ,
365
464
]:
366
465
delattr (t , 'dow_name' )
466
+ bpy .utils .unregister_class (DOW_OT_configure_invisible )
467
+ bpy .utils .unregister_class (ActionSettings )
468
+ bpy .utils .unregister_class (DOW_UL_action_settings )
469
+ bpy .utils .unregister_class (DOW_OT_select_all_actions )
367
470
bpy .utils .unregister_class (DOW_OT_convert_to_marker )
368
471
bpy .utils .unregister_class (DOW_OT_detach_object )
369
472
bpy .utils .unregister_class (DOW_OT_attach_object )
0 commit comments