Blender V4.5
anim_asset_ops.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2025 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "BLI_listbase.h"
6
7#include "BKE_asset.hh"
8#include "BKE_asset_edit.hh"
9#include "BKE_context.hh"
10#include "BKE_fcurve.hh"
11#include "BKE_global.hh"
12#include "BKE_icons.h"
13#include "BKE_lib_id.hh"
14#include "BKE_preferences.h"
15#include "BKE_report.hh"
16#include "BKE_screen.hh"
17
18#include "WM_api.hh"
19
20#include "RNA_access.hh"
21#include "RNA_define.hh"
22#include "RNA_prototypes.hh"
23
24#include "ED_asset.hh"
25#include "ED_asset_library.hh"
26#include "ED_asset_list.hh"
29#include "ED_asset_shelf.hh"
30#include "ED_fileselect.hh"
31#include "ED_screen.hh"
32
33#include "UI_interface_icons.hh"
34#include "UI_resources.hh"
35
36#include "BLT_translation.hh"
37
38#include "ANIM_action.hh"
40#include "ANIM_armature.hh"
41#include "ANIM_keyframing.hh"
42#include "ANIM_pose.hh"
43#include "ANIM_rna.hh"
44
45#include "AS_asset_catalog.hh"
47#include "AS_asset_library.hh"
49
50#include "anim_intern.hh"
51
53
55 PointerRNA * /*ptr*/,
56 PropertyRNA * /*prop*/,
57 bool *r_free)
58{
60 true);
61 *r_free = true;
62 BLI_assert(items != nullptr);
63 return items;
64}
65
67{
68 BLI_assert(bone_pointer.type == &RNA_PoseBone);
69
71 paths.append({"location"});
72 paths.append({"scale"});
73 bPoseChannel *pose_bone = static_cast<bPoseChannel *>(bone_pointer.data);
74 switch (pose_bone->rotmode) {
75 case ROT_MODE_QUAT:
76 paths.append({"rotation_quaternion"});
77 break;
79 paths.append({"rotation_axis_angle"});
80 break;
81 case ROT_MODE_XYZ:
82 case ROT_MODE_XZY:
83 case ROT_MODE_YXZ:
84 case ROT_MODE_YZX:
85 case ROT_MODE_ZXY:
86 case ROT_MODE_ZYX:
87 paths.append({"rotation_euler"});
88 default:
89 break;
90 }
91
92 paths.extend({{"bbone_curveinx"},
93 {"bbone_curveoutx"},
94 {"bbone_curveinz"},
95 {"bbone_curveoutz"},
96 {"bbone_rollin"},
97 {"bbone_rollout"},
98 {"bbone_scalein"},
99 {"bbone_scaleout"},
100 {"bbone_easein"},
101 {"bbone_easeout"}});
102
104
105 return paths;
106}
107
109 const blender::Span<Object *> pose_objects)
110{
111 /* This currently only looks at the pose and not other things that could go onto different
112 * slots on the same action. */
113
114 using namespace blender::animrig;
115 Action &action = action_add(bmain, "pose_create");
116 Layer &layer = action.layer_add("pose");
117 Strip &strip = layer.strip_add(action, Strip::Type::Keyframe);
118 StripKeyframeData &strip_data = strip.data<StripKeyframeData>(action);
120
121 for (Object *pose_object : pose_objects) {
122 BLI_assert(pose_object->pose);
123 Slot &slot = action.slot_add_for_id(pose_object->id);
124 const bArmature *armature = static_cast<bArmature *>(pose_object->data);
125
126 Set<RNAPath> existing_paths;
127 if (pose_object->adt && pose_object->adt->action &&
128 pose_object->adt->slot_handle != Slot::unassigned)
129 {
130 Action &pose_object_action = pose_object->adt->action->wrap();
131 const slot_handle_t pose_object_slot = pose_object->adt->slot_handle;
132 foreach_fcurve_in_action_slot(pose_object_action, pose_object_slot, [&](FCurve &fcurve) {
133 RNAPath existing_path = {fcurve.rna_path, std::nullopt, fcurve.array_index};
134 existing_paths.add(existing_path);
135 });
136 }
137
138 LISTBASE_FOREACH (bPoseChannel *, pose_bone, &pose_object->pose->chanbase) {
139 if (!(pose_bone->bone->flag & BONE_SELECTED) ||
140 !blender::animrig::bone_is_visible(armature, pose_bone->bone))
141 {
142 continue;
143 }
145 &pose_object->id, &RNA_PoseBone, pose_bone);
146 Vector<RNAPath> rna_paths = construct_pose_rna_paths(bone_pointer);
147 for (const RNAPath &rna_path : rna_paths) {
148 PointerRNA resolved_pointer;
149 PropertyRNA *resolved_property;
150 if (!RNA_path_resolve(
151 &bone_pointer, rna_path.path.c_str(), &resolved_pointer, &resolved_property))
152 {
153 continue;
154 }
155 const Vector<float> values = blender::animrig::get_rna_values(&resolved_pointer,
156 resolved_property);
157 const std::optional<std::string> rna_path_id_to_prop = RNA_path_from_ID_to_property(
158 &resolved_pointer, resolved_property);
159 if (!rna_path_id_to_prop.has_value()) {
160 continue;
161 }
162 for (const int i : values.index_range()) {
163 if (RNA_property_is_idprop(resolved_property) &&
164 !existing_paths.contains({rna_path_id_to_prop.value(), std::nullopt, i}))
165 {
166 /* Skipping custom properties without animation. */
167 continue;
168 }
169 strip_data.keyframe_insert(
170 &bmain, slot, {rna_path_id_to_prop.value(), i}, {1, values[i]}, key_settings);
171 }
172 }
173 }
174 }
175 return action;
176}
177
178/* Check that the newly created asset is visible SOMEWHERE in Blender. If not already visible,
179 * open the asset shelf on the current 3D view. The reason for not always doing that is that it
180 * might be annoying in case you have 2 3D viewports open, but you want the asset shelf on only one
181 * of them, or you work out of the asset browser.*/
183{
184 ScrArea *current_area = CTX_wm_area(&C);
185 if (!current_area || current_area->type->spaceid != SPACE_VIEW3D) {
186 /* Opening the asset shelf will only work from the 3D viewport. */
187 return;
188 }
189
191 LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
192 const bScreen *screen = WM_window_get_active_screen(win);
193 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
194 if (area->type->spaceid == SPACE_FILE) {
195 SpaceFile *sfile = reinterpret_cast<SpaceFile *>(area->spacedata.first);
196 if (sfile->browse_mode == FILE_BROWSE_MODE_ASSETS) {
197 /* Asset Browser is open. */
198 return;
199 }
200 continue;
201 }
202 const ARegion *shelf_region = BKE_area_find_region_type(area, RGN_TYPE_ASSET_SHELF);
203 if (!shelf_region) {
204 continue;
205 }
206 if (shelf_region->runtime->visible) {
207 /* A visible asset shelf was found. */
208 return;
209 }
210 }
211 }
212
213 /* At this point, no asset shelf or asset browser was visible anywhere. */
214 ARegion *shelf_region = BKE_area_find_region_type(current_area, RGN_TYPE_ASSET_SHELF);
215 if (!shelf_region) {
216 return;
217 }
218 shelf_region->flag &= ~RGN_FLAG_HIDDEN;
220}
221
223{
224 blender::Vector<PointerRNA> selected_objects;
225 CTX_data_selected_objects(C, &selected_objects);
226
227 blender::Vector<Object *> selected_pose_objects;
228 for (const PointerRNA &ptr : selected_objects) {
229 Object *object = reinterpret_cast<Object *>(ptr.owner_id);
230 if (!object->pose) {
231 continue;
232 }
233 selected_pose_objects.append(object);
234 }
235
236 Object *active_object = CTX_data_active_object(C);
237 /* The active object may not be selected, it should be added because you can still switch to pose
238 * mode. */
239 if (active_object && active_object->pose && !selected_pose_objects.contains(active_object)) {
240 selected_pose_objects.append(active_object);
241 }
242 return selected_pose_objects;
243}
244
246 wmOperator *op,
247 const StringRefNull name,
248 const AssetLibraryReference lib_ref)
249{
251
252 if (selected_pose_objects.is_empty()) {
253 return OPERATOR_CANCELLED;
254 }
255
256 Main *bmain = CTX_data_main(C);
257 /* Extract the pose into a new action. */
258 blender::animrig::Action &pose_action = extract_pose(*bmain, selected_pose_objects);
259 asset::mark_id(&pose_action.id);
260 if (!G.background) {
261 asset::generate_preview(C, &pose_action.id);
262 }
263 BKE_id_rename(*bmain, pose_action.id, name);
264
265 /* Add asset to catalog. */
266 char catalog_path_c[MAX_NAME];
267 RNA_string_get(op->ptr, "catalog_path", catalog_path_c);
268
269 AssetMetaData &meta_data = *pose_action.id.asset_data;
270 asset_system::AssetLibrary *library = AS_asset_library_load(bmain, lib_ref);
271 /* NOTE(@ChrisLend): I don't know if a local library can fail to load.
272 * Just being defensive here. */
273 BLI_assert(library);
274 if (catalog_path_c[0] && library) {
275 const asset_system::AssetCatalogPath catalog_path(catalog_path_c);
277 catalog_path);
278 BKE_asset_metadata_catalog_id_set(&meta_data, catalog.catalog_id, catalog.simple_name.c_str());
279 }
280
283
285
287
288 return OPERATOR_FINISHED;
289}
290
292 wmOperator *op,
293 const char name[MAX_NAME],
294 const AssetLibraryReference lib_ref)
295{
297 Main *bmain = CTX_data_main(C);
298
300 &U, lib_ref.custom_library_index);
301 BLI_assert_msg(user_library, "The passed lib_ref is expected to be a user library");
302 if (!user_library) {
303 return OPERATOR_CANCELLED;
304 }
305
306 asset_system::AssetLibrary *library = AS_asset_library_load(bmain, lib_ref);
307 if (!library) {
308 BKE_report(op->reports, RPT_ERROR, "Failed to load asset library");
309 return OPERATOR_CANCELLED;
310 }
311
313
314 if (selected_pose_objects.is_empty()) {
315 return OPERATOR_CANCELLED;
316 }
317
318 /* Temporary action in current main that will be exported and later deleted. */
319 blender::animrig::Action &pose_action = extract_pose(*bmain, selected_pose_objects);
320 asset::mark_id(&pose_action.id);
321 if (!G.background) {
322 asset::generate_preview(C, &pose_action.id);
323 }
324
325 /* Add asset to catalog. */
326 char catalog_path_c[MAX_NAME];
327 RNA_string_get(op->ptr, "catalog_path", catalog_path_c);
328
329 AssetMetaData &meta_data = *pose_action.id.asset_data;
330 if (catalog_path_c[0]) {
331 const asset_system::AssetCatalogPath catalog_path(catalog_path_c);
333 *library, catalog_path);
334 BKE_asset_metadata_catalog_id_set(&meta_data, catalog.catalog_id, catalog.simple_name.c_str());
335 }
336
337 AssetWeakReference pose_asset_reference;
338 const std::optional<std::string> final_full_asset_filepath = bke::asset_edit_id_save_as(
339 *bmain, pose_action.id, name, *user_library, pose_asset_reference, *op->reports);
340
341 library->catalog_service().write_to_disk(*final_full_asset_filepath);
344
345 BKE_id_free(bmain, &pose_action.id);
346
348
350
351 return OPERATOR_FINISHED;
352}
353
355{
356 char name[MAX_NAME] = "";
357 PropertyRNA *name_prop = RNA_struct_find_property(op->ptr, "pose_name");
358 if (RNA_property_is_set(op->ptr, name_prop)) {
359 RNA_property_string_get(op->ptr, name_prop, name);
360 }
361 if (name[0] == '\0') {
362 BKE_report(op->reports, RPT_ERROR, "No name set");
363 return OPERATOR_CANCELLED;
364 }
365
366 const int enum_value = RNA_enum_get(op->ptr, "asset_library_reference");
368
369 switch (lib_ref.type) {
371 return create_pose_asset_local(C, op, name, lib_ref);
372
374 return create_pose_asset_user_library(C, op, name, lib_ref);
375
376 default:
377 /* Only local and custom libraries should be exposed in the enum. */
379 break;
380 }
381
382 BKE_report(op->reports, RPT_ERROR, "Unexpected library type. Failed to create pose asset");
383
384 return OPERATOR_FINISHED;
385}
386
388 wmOperator *op,
389 const wmEvent * /*event*/)
390{
391 /* If the library isn't saved from the operator's last execution, use the first library. */
392 if (!RNA_struct_property_is_set_ex(op->ptr, "asset_library_reference", false)) {
394 *static_cast<const bUserAssetLibrary *>(U.asset_libraries.first));
395 RNA_enum_set(op->ptr,
396 "asset_library_reference",
398 }
399
400 return WM_operator_props_dialog_popup(C, op, 400, std::nullopt, IFACE_("Create"));
401}
402
404{
406 return false;
407 }
408 return true;
409}
410
412 const bContext *C,
414 PropertyRNA * /*prop*/,
415 const char *edit_text,
417{
418 const int enum_value = RNA_enum_get(ptr, "asset_library_reference");
420
422 *CTX_data_main(C), lib_ref, edit_text, visit_fn);
423}
424
426{
427 ot->name = "Create Pose Asset...";
428 ot->description = "Create a new asset from the selected bones in the scene";
429 ot->idname = "POSELIB_OT_create_pose_asset";
430
434
435 ot->prop = RNA_def_string(
436 ot->srna, "pose_name", nullptr, MAX_NAME, "Pose Name", "Name for the new pose asset");
437
438 PropertyRNA *prop = RNA_def_property(ot->srna, "asset_library_reference", PROP_ENUM, PROP_NONE);
440 RNA_def_property_ui_text(prop, "Library", "Asset library used to store the new pose");
441
442 prop = RNA_def_string(
443 ot->srna, "catalog_path", nullptr, MAX_NAME, "Catalog", "Catalog to use for the new asset");
446
447 /* This property is just kept to have backwards compatibility and has no functionality. It should
448 * be removed in the 5.0 release. */
449 prop = RNA_def_boolean(ot->srna,
450 "activate_new_action",
451 false,
452 "Activate New Action",
453 "This property is deprecated and will be removed in the future");
455}
456
463
466 "ADJUST",
467 0,
468 "Adjust",
469 "Update existing channels in the pose asset but don't remove or add any channels"},
471 "REPLACE",
472 0,
473 "Replace with Selection",
474 "Completely replace all channels in the pose asset with the current selection"},
475 {MODIFY_ADD,
476 "ADD",
477 0,
478 "Add Selected Bones",
479 "Add channels of the selection to the pose asset. Existing channels will be updated"},
481 "REMOVE",
482 0,
483 "Remove Selected Bones",
484 "Remove channels of the selection from the pose asset"},
485 {0, nullptr, 0, nullptr, nullptr},
486};
487
488/* Gets the selected asset from the given `bContext`. If the asset is an action, returns a pointer
489 * to that action, else returns a nullptr. */
491{
493 if (!asset) {
494 return nullptr;
495 }
496
497 if (asset->get_id_type() != ID_AC) {
498 return nullptr;
499 }
500
501 AssetWeakReference asset_reference = asset->make_weak_reference();
502 Main *bmain = CTX_data_main(C);
503 return reinterpret_cast<bAction *>(
504 bke::asset_edit_id_from_weak_reference(*bmain, ID_AC, asset_reference));
505}
506
511
513{
514 Vector<PathValue> path_values;
515 const bArmature *armature = static_cast<bArmature *>(pose_object.data);
516 LISTBASE_FOREACH (bPoseChannel *, pose_bone, &pose_object.pose->chanbase) {
517 if (!(pose_bone->bone->flag & BONE_SELECTED) ||
518 !blender::animrig::bone_is_visible(armature, pose_bone->bone))
519 {
520 continue;
521 }
523 &pose_object.id, &RNA_PoseBone, pose_bone);
524 Vector<RNAPath> rna_paths = construct_pose_rna_paths(bone_pointer);
525
526 for (RNAPath &rna_path : rna_paths) {
527 PointerRNA resolved_pointer;
528 PropertyRNA *resolved_property;
529 if (!RNA_path_resolve(
530 &bone_pointer, rna_path.path.c_str(), &resolved_pointer, &resolved_property))
531 {
532 continue;
533 }
534 const std::optional<std::string> rna_path_id_to_prop = RNA_path_from_ID_to_property(
535 &resolved_pointer, resolved_property);
536 if (!rna_path_id_to_prop.has_value()) {
537 continue;
538 }
539 Vector<float> values = blender::animrig::get_rna_values(&resolved_pointer,
540 resolved_property);
541 int i = 0;
542 for (const float value : values) {
543 RNAPath path = {rna_path_id_to_prop.value(), std::nullopt, i};
544 path_values.append({path, value});
545 i++;
546 }
547 }
548 }
549 return path_values;
550}
551
552static inline void replace_pose_key(Main &bmain,
554 const blender::animrig::Slot &slot,
555 const float2 time_value,
556 const blender::animrig::FCurveDescriptor &fcurve_descriptor)
557{
558 using namespace blender::animrig;
559 Channelbag &channelbag = strip_data.channelbag_for_slot_ensure(slot);
560 FCurve &fcurve = channelbag.fcurve_ensure(&bmain, fcurve_descriptor);
561
562 /* Clearing all keys beforehand in case the pose was not defined on frame defined in
563 * `time_value`. */
566 insert_vert_fcurve(&fcurve, time_value, key_settings, INSERTKEY_NOFLAGS);
567}
568
570 blender::animrig::Action &pose_action,
571 Object &pose_object,
572 const AssetModifyMode mode)
573{
574 using namespace blender::animrig;
575 /* The frame on which an FCurve has a key to define a pose. */
576 constexpr int pose_frame = 1;
577 if (pose_action.slot_array_num < 1) {
578 /* All actions should have slots at this point. */
580 return;
581 }
582
583 Slot &slot = blender::animrig::get_best_pose_slot_for_id(pose_object.id, pose_action);
584 BLI_assert(pose_action.strip_keyframe_data().size() == 1);
585 BLI_assert(pose_action.layers().size() == 1);
586 StripKeyframeData *strip_data = pose_action.strip_keyframe_data()[0];
587 Vector<PathValue> path_values = generate_path_values(pose_object);
588
589 Set<RNAPath> existing_paths;
590 foreach_fcurve_in_action_slot(pose_action, slot.handle, [&](FCurve &fcurve) {
591 existing_paths.add({fcurve.rna_path, std::nullopt, fcurve.array_index});
592 });
593
594 switch (mode) {
595 case MODIFY_ADJUST: {
596 for (const PathValue &path_value : path_values) {
597 /* Only updating existing channels. */
598 if (existing_paths.contains(path_value.rna_path)) {
599 replace_pose_key(*bmain,
600 *strip_data,
601 slot,
602 {pose_frame, path_value.value},
603 {path_value.rna_path.path, path_value.rna_path.index.value()});
604 }
605 }
606 break;
607 }
608 case MODIFY_ADD: {
609 for (const PathValue &path_value : path_values) {
610 replace_pose_key(*bmain,
611 *strip_data,
612 slot,
613 {pose_frame, path_value.value},
614 {path_value.rna_path.path, path_value.rna_path.index.value()});
615 }
616 break;
617 }
618 case MODIFY_REPLACE: {
619 Channelbag *channelbag = strip_data->channelbag_for_slot(slot.handle);
620 if (!channelbag) {
621 /* No channels to remove. */
622 return;
623 }
624 channelbag->fcurves_clear();
625 for (const PathValue &path_value : path_values) {
626 replace_pose_key(*bmain,
627 *strip_data,
628 slot,
629 {pose_frame, path_value.value},
630 {path_value.rna_path.path, path_value.rna_path.index.value()});
631 }
632 break;
633 }
634 case MODIFY_REMOVE: {
635 Channelbag *channelbag = strip_data->channelbag_for_slot(slot.handle);
636 if (!channelbag) {
637 /* No channels to remove. */
638 return;
639 }
640 Map<RNAPath, FCurve *> fcurve_map;
642 pose_action, pose_action.slot_array[0]->handle, [&](FCurve &fcurve) {
643 fcurve_map.add({fcurve.rna_path, std::nullopt, fcurve.array_index}, &fcurve);
644 });
645 for (const PathValue &path_value : path_values) {
646 if (existing_paths.contains(path_value.rna_path)) {
647 FCurve *fcurve = fcurve_map.lookup(path_value.rna_path);
648 channelbag->fcurve_remove(*fcurve);
649 }
650 }
651 break;
652 }
653 }
654}
655
657{
659 BLI_assert_msg(action, "Poll should have checked action exists");
660 /* Get asset now. Asset browser might get tagged for refreshing through operations below, and not
661 * allow querying items from context until refreshed, see #140781. */
663
664 Main *bmain = CTX_data_main(C);
665 Object *pose_object = CTX_data_active_object(C);
666 if (!pose_object || !pose_object->pose) {
667 return OPERATOR_CANCELLED;
668 }
669
670 AssetModifyMode mode = AssetModifyMode(RNA_enum_get(op->ptr, "mode"));
671 update_pose_action_from_scene(bmain, action->wrap(), *pose_object, mode);
672 if (!G.background) {
673 asset::generate_preview(C, &action->id);
674 }
675 if (ID_IS_LINKED(action)) {
676 /* Not needed for local assets. */
677 bke::asset_edit_id_save(*bmain, action->id, *op->reports);
678 }
679
682
683 return OPERATOR_FINISHED;
684}
685
687{
689 CTX_wm_operator_poll_msg_set(C, "Pose assets can only be modified from Pose Mode");
690 return false;
691 }
692
694
695 if (!action) {
696 return false;
697 }
698
699 if (!ID_IS_LINKED(action)) {
700 return true;
701 }
702
703 if (!bke::asset_edit_id_is_editable(action->id)) {
704 CTX_wm_operator_poll_msg_set(C, "Action is not editable");
705 return false;
706 }
707
708 if (!bke::asset_edit_id_is_writable(action->id)) {
709 CTX_wm_operator_poll_msg_set(C, "Asset blend file is not editable");
710 return false;
711 }
712
713 return true;
714}
715
716static std::string pose_asset_modify_description(bContext * /* C */,
717 wmOperatorType * /* ot */,
719{
720 const int mode = RNA_enum_get(ptr, "mode");
721 return std::string(prop_asset_overwrite_modes[mode].description);
722}
723
724/* Calling it overwrite instead of save because we aren't actually saving an opened asset. */
726{
727 ot->name = "Modify Pose Asset";
728 ot->description =
729 "Update the selected pose asset in the asset library from the currently selected bones. The "
730 "mode defines how the asset is updated";
731 ot->idname = "POSELIB_OT_asset_modify";
732
735 ot->get_description = pose_asset_modify_description;
736
737 RNA_def_enum(ot->srna,
738 "mode",
741 "Overwrite Mode",
742 "Specify which parts of the pose asset are overwritten");
743}
744
746{
748
749 if (!action) {
750 return false;
751 }
752
753 if (!ID_IS_LINKED(action)) {
754 return true;
755 }
756
757 if (!bke::asset_edit_id_is_editable(action->id)) {
758 CTX_wm_operator_poll_msg_set(C, "Action is not editable");
759 return false;
760 }
761
762 if (!bke::asset_edit_id_is_writable(action->id)) {
763 CTX_wm_operator_poll_msg_set(C, "Asset blend file is not editable");
764 return false;
765 }
766
767 return true;
768}
769
771{
773 if (!action) {
774 return OPERATOR_CANCELLED;
775 }
776
778 std::optional<AssetLibraryReference> library_ref =
779 asset->owner_asset_library().library_reference();
780
781 if (ID_IS_LINKED(action)) {
783 }
784 else {
785 asset::clear_id(&action->id);
786 }
787
788 asset::refresh_asset_library(C, library_ref.value());
789
791
792 return OPERATOR_FINISHED;
793}
794
796 wmOperator *op,
797 const wmEvent * /*event*/)
798{
800
802 C,
803 op,
804 IFACE_("Delete Pose Asset"),
805 ID_IS_LINKED(action) ?
806 IFACE_("Permanently delete pose asset blend file? This cannot be undone.") :
807 IFACE_("The asset is local to the file. Deleting it will just clear the asset status."),
808 IFACE_("Delete"),
810 false);
811}
812
814{
815 ot->name = "Delete Pose Asset";
816 ot->description = "Delete the selected Pose Asset";
817 ot->idname = "POSELIB_OT_asset_delete";
818
822}
823
824} // namespace blender::ed::animrig
Functions and classes to work with Actions.
Functionality to iterate an Action in various ways.
Functions to deal with Armatures.
Functions to insert, delete or modify keyframes.
Functions to work with animation poses.
Helper functions for animation to interact with the RNA system.
blender::asset_system::AssetLibrary * AS_asset_library_load(const Main *bmain, const AssetLibraryReference &library_reference)
Main runtime representation of an asset.
void BKE_asset_metadata_catalog_id_set(AssetMetaData *asset_data, bUUID catalog_id, const char *catalog_simple_name)
void CTX_wm_operator_poll_msg_set(bContext *C, const char *msg)
ScrArea * CTX_wm_area(const bContext *C)
Object * CTX_data_active_object(const bContext *C)
class blender::asset_system::AssetRepresentation * CTX_wm_asset(const bContext *C)
bool CTX_data_selected_objects(const bContext *C, blender::Vector< PointerRNA > *list)
Main * CTX_data_main(const bContext *C)
wmWindowManager * CTX_wm_manager(const bContext *C)
void BKE_fcurve_delete_keys_all(FCurve *fcu)
void BKE_id_free(Main *bmain, void *idv)
IDNewNameResult BKE_id_rename(Main &bmain, ID &id, blender::StringRefNull name, const IDNewNameMode mode=IDNewNameMode::RenameExistingNever)
Definition lib_id.cc:2372
struct bUserAssetLibrary * BKE_preferences_asset_library_find_index(const struct UserDef *userdef, int index) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:126
ARegion * BKE_area_find_region_type(const ScrArea *area, int region_type)
Definition screen.cc:840
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
#define LISTBASE_FOREACH(type, var, list)
#define IFACE_(msgid)
@ ID_AC
@ ROT_MODE_XZY
@ ROT_MODE_QUAT
@ ROT_MODE_ZXY
@ ROT_MODE_AXISANGLE
@ ROT_MODE_ZYX
@ ROT_MODE_XYZ
@ ROT_MODE_YXZ
@ ROT_MODE_YZX
@ INSERTKEY_NOFLAGS
struct FCurve FCurve
@ BONE_SELECTED
@ ASSET_LIBRARY_CUSTOM
@ ASSET_LIBRARY_LOCAL
@ HD_AUTO
@ BEZT_IPO_BEZ
@ BEZT_KEYTYPE_KEYFRAME
@ RGN_FLAG_HIDDEN
@ RGN_TYPE_ASSET_SHELF
@ SPACE_FILE
@ SPACE_VIEW3D
@ FILE_BROWSE_MODE_ASSETS
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
void ED_region_visibility_change_update(bContext *C, ScrArea *area, ARegion *region)
Definition area.cc:2355
bool ED_operator_posemode_context(bContext *C)
@ PROP_STRING_SEARCH_SUGGESTION
Definition RNA_types.hh:701
@ PROP_ENUM
Definition RNA_types.hh:154
@ PROP_SKIP_SAVE
Definition RNA_types.hh:330
@ PROP_HIDDEN
Definition RNA_types.hh:324
@ PROP_NONE
Definition RNA_types.hh:221
#define C
Definition RandGen.cpp:29
@ ALERT_ICON_WARNING
#define NA_ADDED
Definition WM_types.hh:583
#define NA_EDITED
Definition WM_types.hh:581
#define NC_ASSET
Definition WM_types.hh:401
#define NA_REMOVED
Definition WM_types.hh:584
#define ND_ASSET_LIST
Definition WM_types.hh:545
#define U
bool contains(const Key &key) const
Definition BLI_set.hh:310
bool add(const Key &key)
Definition BLI_set.hh:248
bool contains(const T &value) const
void append(const T &value)
bool is_empty() const
IndexRange index_range() const
void extend(Span< T > array)
Slot & slot_add_for_id(const ID &animated_id)
blender::Span< const Layer * > layers() const
Span< const StripKeyframeData * > strip_keyframe_data() const
Layer & layer_add(std::optional< StringRefNull > name)
bool fcurve_remove(FCurve &fcurve_to_remove)
FCurve & fcurve_ensure(Main *bmain, const FCurveDescriptor &fcurve_descriptor)
static constexpr slot_handle_t unassigned
SingleKeyingResult keyframe_insert(Main *bmain, const Slot &slot, const FCurveDescriptor &fcurve_descriptor, float2 time_value, const KeyframeSettings &settings, eInsertKeyFlags insert_key_flags=INSERTKEY_NOFLAGS, std::optional< float2 > cycle_range=std::nullopt)
Channelbag & channelbag_for_slot_ensure(const Slot &slot)
bool write_to_disk(const CatalogFilePath &blend_file_path)
AssetCatalogService & catalog_service() const
#define ID_IS_LINKED(_id)
#define MAX_NAME
#define G(x, y, z)
void foreach_fcurve_in_action_slot(Action &action, slot_handle_t handle, FunctionRef< void(FCurve &fcurve)> callback)
Action & action_add(Main &bmain, StringRefNull name)
bool bone_is_visible(const bArmature *armature, const Bone *bone)
Vector< RNAPath > get_keyable_id_property_paths(const PointerRNA &ptr)
Definition anim_rna.cc:126
Vector< float > get_rna_values(PointerRNA *ptr, PropertyRNA *prop)
Definition anim_rna.cc:25
decltype(::ActionSlot::handle) slot_handle_t
SingleKeyingResult insert_vert_fcurve(FCurve *fcu, const float2 position, const KeyframeSettings &settings, eInsertKeyFlags flag)
Main Key-framing API call.
Slot & get_best_pose_slot_for_id(const ID &id, Action &pose_data)
Definition pose.cc:161
ID * asset_edit_id_from_weak_reference(Main &global_main, ID_Type id_type, const AssetWeakReference &weak_ref)
std::optional< std::string > asset_edit_id_save_as(Main &global_main, const ID &id, StringRefNull name, const bUserAssetLibrary &user_library, AssetWeakReference &r_weak_ref, ReportList &reports)
bool asset_edit_id_delete(Main &global_main, ID &id, ReportList &reports)
bool asset_edit_id_is_writable(const ID &id)
bool asset_edit_id_is_editable(const ID &id)
bool asset_edit_id_save(Main &global_main, const ID &id, ReportList &reports)
static blender::Vector< Object * > get_selected_pose_objects(bContext *C)
static wmOperatorStatus pose_asset_delete_invoke(bContext *C, wmOperator *op, const wmEvent *)
static blender::animrig::Action & extract_pose(Main &bmain, const blender::Span< Object * > pose_objects)
static wmOperatorStatus pose_asset_delete_exec(bContext *C, wmOperator *op)
static bool pose_asset_delete_poll(bContext *C)
static void ensure_asset_ui_visible(bContext &C)
static bool pose_asset_create_poll(bContext *C)
static const EnumPropertyItem * rna_asset_library_reference_itemf(bContext *, PointerRNA *, PropertyRNA *, bool *r_free)
static Vector< PathValue > generate_path_values(Object &pose_object)
static wmOperatorStatus pose_asset_create_exec(bContext *C, wmOperator *op)
static wmOperatorStatus pose_asset_modify_exec(bContext *C, wmOperator *op)
void POSELIB_OT_asset_delete(wmOperatorType *ot)
static std::string pose_asset_modify_description(bContext *, wmOperatorType *, PointerRNA *ptr)
static wmOperatorStatus create_pose_asset_user_library(bContext *C, wmOperator *op, const char name[MAX_NAME], const AssetLibraryReference lib_ref)
static bool pose_asset_modify_poll(bContext *C)
void POSELIB_OT_create_pose_asset(wmOperatorType *ot)
static void replace_pose_key(Main &bmain, blender::animrig::StripKeyframeData &strip_data, const blender::animrig::Slot &slot, const float2 time_value, const blender::animrig::FCurveDescriptor &fcurve_descriptor)
static wmOperatorStatus pose_asset_create_invoke(bContext *C, wmOperator *op, const wmEvent *)
static Vector< RNAPath > construct_pose_rna_paths(const PointerRNA &bone_pointer)
static void update_pose_action_from_scene(Main *bmain, blender::animrig::Action &pose_action, Object &pose_object, const AssetModifyMode mode)
static void visit_library_prop_catalogs_catalog_for_search_fn(const bContext *C, PointerRNA *ptr, PropertyRNA *, const char *edit_text, FunctionRef< void(StringPropertySearchVisitParams)> visit_fn)
static wmOperatorStatus create_pose_asset_local(bContext *C, wmOperator *op, const StringRefNull name, const AssetLibraryReference lib_ref)
static const EnumPropertyItem prop_asset_overwrite_modes[]
void POSELIB_OT_asset_modify(wmOperatorType *ot)
static bAction * get_action_of_selected_asset(bContext *C)
void show_catalog_in_visible_shelves(const bContext &C, const StringRefNull catalog_path)
int library_reference_to_enum_value(const AssetLibraryReference *library)
const EnumPropertyItem * library_reference_to_rna_enum_itemf(bool include_readonly, bool include_current_file)
void refresh_asset_library(const bContext *C, const AssetLibraryReference &library_ref)
AssetLibraryReference library_reference_from_enum_value(int value)
void generate_preview(const bContext *C, ID *id)
void visit_library_catalogs_catalog_for_search(const Main &bmain, const AssetLibraryReference lib, const StringRef edit_text, const FunctionRef< void(StringPropertySearchVisitParams)> visit_fn)
void refresh_asset_library_from_asset(const bContext *C, const blender::asset_system::AssetRepresentation &asset)
AssetLibraryReference user_library_to_library_ref(const bUserAssetLibrary &user_library)
blender::asset_system::AssetCatalog & library_ensure_catalogs_in_path(blender::asset_system::AssetLibrary &library, const blender::asset_system::AssetCatalogPath &path)
VecBase< float, 2 > float2
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
bool RNA_struct_property_is_set_ex(PointerRNA *ptr, const char *identifier, bool use_ghost)
bool RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop)
void RNA_string_get(PointerRNA *ptr, const char *name, char *value)
bool RNA_property_is_idprop(const PropertyRNA *prop)
std::string RNA_property_string_get(PointerRNA *ptr, PropertyRNA *prop)
void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
PointerRNA RNA_pointer_create_discrete(ID *id, StructRNA *type, void *data)
int RNA_enum_get(PointerRNA *ptr, const char *name)
PropertyRNA * RNA_def_string(StructOrFunctionRNA *cont_, const char *identifier, const char *default_value, const int maxlen, const char *ui_name, const char *ui_description)
void RNA_def_property_string_search_func_runtime(PropertyRNA *prop, StringPropertySearchFunc search_fn, const eStringPropertySearchFlag search_flag)
void RNA_def_property_ui_text(PropertyRNA *prop, const char *name, const char *description)
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
PropertyRNA * RNA_def_property(StructOrFunctionRNA *cont_, const char *identifier, int type, int subtype)
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, const bool default_value, const char *ui_name, const char *ui_description)
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
void RNA_def_enum_funcs(PropertyRNA *prop, EnumPropertyItemFunc itemfunc)
std::optional< std::string > RNA_path_from_ID_to_property(const PointerRNA *ptr, PropertyRNA *prop)
Definition rna_path.cc:1173
bool RNA_path_resolve(const PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop)
Definition rna_path.cc:532
ARegionRuntimeHandle * runtime
The meta-data of an asset. By creating and giving this for a data-block (ID.asset_data),...
char * rna_path
int array_index
struct AssetMetaData * asset_data
Definition DNA_ID.h:413
struct bPose * pose
StructRNA * type
Definition RNA_types.hh:52
void * data
Definition RNA_types.hh:53
struct SpaceType * type
StripData * data
ListBase chanbase
ListBase areabase
struct ReportList * reports
struct PointerRNA * ptr
i
Definition text_draw.cc:230
void WM_main_add_notifier(uint type, void *reference)
PointerRNA * ptr
Definition wm_files.cc:4226
wmOperatorType * ot
Definition wm_files.cc:4225
wmOperatorStatus WM_operator_props_dialog_popup(bContext *C, wmOperator *op, int width, std::optional< std::string > title, std::optional< std::string > confirm_text, const bool cancel_default)
wmOperatorStatus WM_operator_confirm_ex(bContext *C, wmOperator *op, const char *title, const char *message, const char *confirm_text, int icon, bool cancel_default)
bScreen * WM_window_get_active_screen(const wmWindow *win)