Blender V5.0
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#include "ED_undo.hh"
33
34#include "UI_interface_icons.hh"
35#include "UI_resources.hh"
36
37#include "BLT_translation.hh"
38
39#include "ANIM_action.hh"
41#include "ANIM_armature.hh"
42#include "ANIM_keyframing.hh"
43#include "ANIM_pose.hh"
44#include "ANIM_rna.hh"
45
46#include "AS_asset_catalog.hh"
48#include "AS_asset_library.hh"
50
51#include "anim_intern.hh"
52
54
56 PointerRNA * /*ptr*/,
57 PropertyRNA * /*prop*/,
58 bool *r_free)
59{
61 true);
62 *r_free = true;
63 BLI_assert(items != nullptr);
64 return items;
65}
66
68{
69 BLI_assert(bone_pointer.type == &RNA_PoseBone);
70
72 paths.append({"location"});
73 paths.append({"scale"});
74 bPoseChannel *pose_bone = static_cast<bPoseChannel *>(bone_pointer.data);
75 switch (pose_bone->rotmode) {
76 case ROT_MODE_QUAT:
77 paths.append({"rotation_quaternion"});
78 break;
80 paths.append({"rotation_axis_angle"});
81 break;
82 case ROT_MODE_XYZ:
83 case ROT_MODE_XZY:
84 case ROT_MODE_YXZ:
85 case ROT_MODE_YZX:
86 case ROT_MODE_ZXY:
87 case ROT_MODE_ZYX:
88 paths.append({"rotation_euler"});
89 default:
90 break;
91 }
92
93 paths.extend({{"bbone_curveinx"},
94 {"bbone_curveoutx"},
95 {"bbone_curveinz"},
96 {"bbone_curveoutz"},
97 {"bbone_rollin"},
98 {"bbone_rollout"},
99 {"bbone_scalein"},
100 {"bbone_scaleout"},
101 {"bbone_easein"},
102 {"bbone_easeout"}});
103
105
106 return paths;
107}
108
110 const blender::Span<Object *> pose_objects)
111{
112 /* This currently only looks at the pose and not other things that could go onto different
113 * slots on the same action. */
114
115 using namespace blender::animrig;
116 Action &action = action_add(bmain, "pose_create");
117 Layer &layer = action.layer_add("pose");
118 Strip &strip = layer.strip_add(action, Strip::Type::Keyframe);
119 StripKeyframeData &strip_data = strip.data<StripKeyframeData>(action);
121
122 for (Object *pose_object : pose_objects) {
123 BLI_assert(pose_object->pose);
124 Slot &slot = action.slot_add_for_id(pose_object->id);
125 const bArmature *armature = static_cast<bArmature *>(pose_object->data);
126
127 Set<RNAPath> existing_paths;
128 if (pose_object->adt && pose_object->adt->action &&
129 pose_object->adt->slot_handle != Slot::unassigned)
130 {
131 Action &pose_object_action = pose_object->adt->action->wrap();
132 const slot_handle_t pose_object_slot = pose_object->adt->slot_handle;
133 foreach_fcurve_in_action_slot(pose_object_action, pose_object_slot, [&](FCurve &fcurve) {
134 RNAPath existing_path = {fcurve.rna_path, std::nullopt, fcurve.array_index};
135 existing_paths.add(existing_path);
136 });
137 }
138
139 LISTBASE_FOREACH (bPoseChannel *, pose_bone, &pose_object->pose->chanbase) {
140 if (!blender::animrig::bone_is_selected(armature, pose_bone)) {
141 continue;
142 }
144 &pose_object->id, &RNA_PoseBone, pose_bone);
145 Vector<RNAPath> rna_paths = construct_pose_rna_paths(bone_pointer);
146 for (const RNAPath &rna_path : rna_paths) {
147 PointerRNA resolved_pointer;
148 PropertyRNA *resolved_property;
149 if (!RNA_path_resolve(
150 &bone_pointer, rna_path.path.c_str(), &resolved_pointer, &resolved_property))
151 {
152 continue;
153 }
154 const Vector<float> values = blender::animrig::get_rna_values(&resolved_pointer,
155 resolved_property);
156 const std::optional<std::string> rna_path_id_to_prop = RNA_path_from_ID_to_property(
157 &resolved_pointer, resolved_property);
158 if (!rna_path_id_to_prop.has_value()) {
159 continue;
160 }
161 for (const int i : values.index_range()) {
162 if (RNA_property_is_idprop(resolved_property) &&
163 !existing_paths.contains({rna_path_id_to_prop.value(), std::nullopt, i}))
164 {
165 /* Skipping custom properties without animation. */
166 continue;
167 }
168 strip_data.keyframe_insert(
169 &bmain, slot, {rna_path_id_to_prop.value(), i}, {1, values[i]}, key_settings);
170 }
171 }
172 }
173 }
174 return action;
175}
176
184{
185 ScrArea *current_area = CTX_wm_area(&C);
186 if (!current_area || current_area->type->spaceid != SPACE_VIEW3D) {
187 /* Opening the asset shelf will only work from the 3D viewport. */
188 return;
189 }
190
192 LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
193 const bScreen *screen = WM_window_get_active_screen(win);
194 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
195 if (area->type->spaceid == SPACE_FILE) {
196 SpaceFile *sfile = reinterpret_cast<SpaceFile *>(area->spacedata.first);
197 if (sfile->browse_mode == FILE_BROWSE_MODE_ASSETS) {
198 /* Asset Browser is open. */
199 return;
200 }
201 continue;
202 }
203 const ARegion *shelf_region = BKE_area_find_region_type(area, RGN_TYPE_ASSET_SHELF);
204 if (!shelf_region) {
205 continue;
206 }
207 if (shelf_region->runtime->visible) {
208 /* A visible asset shelf was found. */
209 return;
210 }
211 }
212 }
213
214 /* At this point, no asset shelf or asset browser was visible anywhere. */
215 ARegion *shelf_region = BKE_area_find_region_type(current_area, RGN_TYPE_ASSET_SHELF);
216 if (!shelf_region) {
217 return;
218 }
219 shelf_region->flag &= ~RGN_FLAG_HIDDEN;
221}
222
224{
225 blender::Vector<PointerRNA> selected_objects;
226 CTX_data_selected_objects(C, &selected_objects);
227
228 blender::Vector<Object *> selected_pose_objects;
229 for (const PointerRNA &ptr : selected_objects) {
230 Object *object = reinterpret_cast<Object *>(ptr.owner_id);
231 if (!object->pose) {
232 continue;
233 }
234 selected_pose_objects.append(object);
235 }
236
237 Object *active_object = CTX_data_active_object(C);
238 /* The active object may not be selected, it should be added because you can still switch to pose
239 * mode. */
240 if (active_object && active_object->pose && !selected_pose_objects.contains(active_object)) {
241 selected_pose_objects.append(active_object);
242 }
243 return selected_pose_objects;
244}
245
247 wmOperator *op,
248 const StringRefNull name,
249 const AssetLibraryReference lib_ref)
250{
252
253 if (selected_pose_objects.is_empty()) {
254 return OPERATOR_CANCELLED;
255 }
256
257 Main *bmain = CTX_data_main(C);
258 /* Extract the pose into a new action. */
259 blender::animrig::Action &pose_action = extract_pose(*bmain, selected_pose_objects);
260 asset::mark_id(&pose_action.id);
261 if (!G.background) {
262 asset::generate_preview(C, &pose_action.id);
263 }
264 BKE_id_rename(*bmain, pose_action.id, name);
265
266 /* Add asset to catalog. */
267 char catalog_path_c[MAX_NAME];
268 RNA_string_get(op->ptr, "catalog_path", catalog_path_c);
269
270 AssetMetaData &meta_data = *pose_action.id.asset_data;
271 asset_system::AssetLibrary *library = AS_asset_library_load(bmain, lib_ref);
272 /* NOTE(@ChrisLend): I don't know if a local library can fail to load.
273 * Just being defensive here. */
274 BLI_assert(library);
275 if (catalog_path_c[0] && library) {
276 const asset_system::AssetCatalogPath catalog_path(catalog_path_c);
278 catalog_path);
279 BKE_asset_metadata_catalog_id_set(&meta_data, catalog.catalog_id, catalog.simple_name.c_str());
280 }
281
284
286
288
289 return OPERATOR_FINISHED;
290}
291
293 wmOperator *op,
294 const char name[MAX_NAME],
295 const AssetLibraryReference lib_ref)
296{
298 Main *bmain = CTX_data_main(C);
299
301 &U, lib_ref.custom_library_index);
302 BLI_assert_msg(user_library, "The passed lib_ref is expected to be a user library");
303 if (!user_library) {
304 return OPERATOR_CANCELLED;
305 }
306
307 asset_system::AssetLibrary *library = AS_asset_library_load(bmain, lib_ref);
308 if (!library) {
309 BKE_report(op->reports, RPT_ERROR, "Failed to load asset library");
310 return OPERATOR_CANCELLED;
311 }
312
314
315 if (selected_pose_objects.is_empty()) {
316 return OPERATOR_CANCELLED;
317 }
318
319 /* Temporary action in current main that will be exported and later deleted. */
320 blender::animrig::Action &pose_action = extract_pose(*bmain, selected_pose_objects);
321 asset::mark_id(&pose_action.id);
322 if (!G.background) {
323 asset::generate_preview(C, &pose_action.id);
324 }
325
326 /* Add asset to catalog. */
327 char catalog_path_c[MAX_NAME];
328 RNA_string_get(op->ptr, "catalog_path", catalog_path_c);
329
330 AssetMetaData &meta_data = *pose_action.id.asset_data;
331 if (catalog_path_c[0]) {
332 const asset_system::AssetCatalogPath catalog_path(catalog_path_c);
334 *library, catalog_path);
335 BKE_asset_metadata_catalog_id_set(&meta_data, catalog.catalog_id, catalog.simple_name.c_str());
336 }
337
338 AssetWeakReference pose_asset_reference;
339 const std::optional<std::string> final_full_asset_filepath = bke::asset_edit_id_save_as(
340 *bmain, pose_action.id, name, *user_library, pose_asset_reference, *op->reports);
341
342 library->catalog_service().write_to_disk(*final_full_asset_filepath);
345
346 BKE_id_free(bmain, &pose_action.id);
347
349
351
352 return OPERATOR_FINISHED;
353}
354
356{
357 char name[MAX_NAME] = "";
358 PropertyRNA *name_prop = RNA_struct_find_property(op->ptr, "pose_name");
359 if (RNA_property_is_set(op->ptr, name_prop)) {
360 RNA_property_string_get(op->ptr, name_prop, name);
361 }
362 if (name[0] == '\0') {
363 BKE_report(op->reports, RPT_ERROR, "No name set");
364 return OPERATOR_CANCELLED;
365 }
366
367 const int enum_value = RNA_enum_get(op->ptr, "asset_library_reference");
369
370 switch (lib_ref.type) {
372 return create_pose_asset_local(C, op, name, lib_ref);
373
375 return create_pose_asset_user_library(C, op, name, lib_ref);
376
377 default:
378 /* Only local and custom libraries should be exposed in the enum. */
380 break;
381 }
382
383 BKE_report(op->reports, RPT_ERROR, "Unexpected library type. Failed to create pose asset");
384
385 return OPERATOR_FINISHED;
386}
387
389 wmOperator *op,
390 const wmEvent * /*event*/)
391{
392 /* If the library isn't saved from the operator's last execution, use the first library. */
393 if (!RNA_struct_property_is_set_ex(op->ptr, "asset_library_reference", false)) {
395 *static_cast<const bUserAssetLibrary *>(U.asset_libraries.first));
396 RNA_enum_set(op->ptr,
397 "asset_library_reference",
399 }
400
401 return WM_operator_props_dialog_popup(C, op, 400, std::nullopt, IFACE_("Create"));
402}
403
405{
407 return false;
408 }
409 return true;
410}
411
413 const bContext *C,
415 PropertyRNA * /*prop*/,
416 const char *edit_text,
418{
419 const int enum_value = RNA_enum_get(ptr, "asset_library_reference");
421
423 *CTX_data_main(C), lib_ref, edit_text, visit_fn);
424}
425
427{
428 ot->name = "Create Pose Asset...";
429 ot->description = "Create a new asset from the selected bones in the scene";
430 ot->idname = "POSELIB_OT_create_pose_asset";
432
436
437 ot->prop = RNA_def_string(
438 ot->srna, "pose_name", nullptr, MAX_NAME, "Pose Name", "Name for the new pose asset");
439
440 PropertyRNA *prop = RNA_def_property(ot->srna, "asset_library_reference", PROP_ENUM, PROP_NONE);
442 RNA_def_property_ui_text(prop, "Library", "Asset library used to store the new pose");
443
444 prop = RNA_def_string(
445 ot->srna, "catalog_path", nullptr, MAX_NAME, "Catalog", "Catalog to use for the new asset");
448}
449
456
459 "ADJUST",
460 0,
461 "Adjust",
462 "Update existing channels in the pose asset but don't remove or add any channels"},
464 "REPLACE",
465 0,
466 "Replace with Selection",
467 "Completely replace all channels in the pose asset with the current selection"},
468 {MODIFY_ADD,
469 "ADD",
470 0,
471 "Add Selected Bones",
472 "Add channels of the selection to the pose asset. Existing channels will be updated"},
474 "REMOVE",
475 0,
476 "Remove Selected Bones",
477 "Remove channels of the selection from the pose asset"},
478 {0, nullptr, 0, nullptr, nullptr},
479};
480
481/* Gets the selected asset from the given `bContext`. If the asset is an action, returns a pointer
482 * to that action, else returns a nullptr. */
484{
486 if (!asset) {
487 return nullptr;
488 }
489
490 if (asset->get_id_type() != ID_AC) {
491 return nullptr;
492 }
493
494 AssetWeakReference asset_reference = asset->make_weak_reference();
495 Main *bmain = CTX_data_main(C);
496 return reinterpret_cast<bAction *>(
497 bke::asset_edit_id_from_weak_reference(*bmain, ID_AC, asset_reference));
498}
499
504
506{
507 Vector<PathValue> path_values;
508 const bArmature *armature = static_cast<bArmature *>(pose_object.data);
509 LISTBASE_FOREACH (bPoseChannel *, pose_bone, &pose_object.pose->chanbase) {
510 if (!blender::animrig::bone_is_selected(armature, pose_bone)) {
511 continue;
512 }
514 &pose_object.id, &RNA_PoseBone, pose_bone);
515 Vector<RNAPath> rna_paths = construct_pose_rna_paths(bone_pointer);
516
517 for (RNAPath &rna_path : rna_paths) {
518 PointerRNA resolved_pointer;
519 PropertyRNA *resolved_property;
520 if (!RNA_path_resolve(
521 &bone_pointer, rna_path.path.c_str(), &resolved_pointer, &resolved_property))
522 {
523 continue;
524 }
525 const std::optional<std::string> rna_path_id_to_prop = RNA_path_from_ID_to_property(
526 &resolved_pointer, resolved_property);
527 if (!rna_path_id_to_prop.has_value()) {
528 continue;
529 }
530 Vector<float> values = blender::animrig::get_rna_values(&resolved_pointer,
531 resolved_property);
532 int i = 0;
533 for (const float value : values) {
534 RNAPath path = {rna_path_id_to_prop.value(), std::nullopt, i};
535 path_values.append({path, value});
536 i++;
537 }
538 }
539 }
540 return path_values;
541}
542
543static inline void replace_pose_key(Main &bmain,
545 const blender::animrig::Slot &slot,
546 const float2 time_value,
547 const blender::animrig::FCurveDescriptor &fcurve_descriptor)
548{
549 using namespace blender::animrig;
550 Channelbag &channelbag = strip_data.channelbag_for_slot_ensure(slot);
551 FCurve &fcurve = channelbag.fcurve_ensure(&bmain, fcurve_descriptor);
552
553 /* Clearing all keys beforehand in case the pose was not defined on frame defined in
554 * `time_value`. */
557 insert_vert_fcurve(&fcurve, time_value, key_settings, INSERTKEY_NOFLAGS);
558}
559
561 blender::animrig::Action &pose_action,
562 Object &pose_object,
563 const AssetModifyMode mode)
564{
565 using namespace blender::animrig;
566 /* The frame on which an FCurve has a key to define a pose. */
567 constexpr int pose_frame = 1;
568 if (pose_action.slot_array_num < 1) {
569 /* All actions should have slots at this point. */
571 return;
572 }
573
574 Slot &slot = blender::animrig::get_best_pose_slot_for_id(pose_object.id, pose_action);
575 BLI_assert(pose_action.strip_keyframe_data().size() == 1);
576 BLI_assert(pose_action.layers().size() == 1);
577 StripKeyframeData *strip_data = pose_action.strip_keyframe_data()[0];
578 Vector<PathValue> path_values = generate_path_values(pose_object);
579
580 Set<RNAPath> existing_paths;
581 foreach_fcurve_in_action_slot(pose_action, slot.handle, [&](FCurve &fcurve) {
582 existing_paths.add({fcurve.rna_path, std::nullopt, fcurve.array_index});
583 });
584
585 switch (mode) {
586 case MODIFY_ADJUST: {
587 for (const PathValue &path_value : path_values) {
588 /* Only updating existing channels. */
589 if (existing_paths.contains(path_value.rna_path)) {
590 replace_pose_key(*bmain,
591 *strip_data,
592 slot,
593 {pose_frame, path_value.value},
594 {path_value.rna_path.path, path_value.rna_path.index.value()});
595 }
596 }
597 break;
598 }
599 case MODIFY_ADD: {
600 for (const PathValue &path_value : path_values) {
601 replace_pose_key(*bmain,
602 *strip_data,
603 slot,
604 {pose_frame, path_value.value},
605 {path_value.rna_path.path, path_value.rna_path.index.value()});
606 }
607 break;
608 }
609 case MODIFY_REPLACE: {
610 Channelbag *channelbag = strip_data->channelbag_for_slot(slot.handle);
611 if (!channelbag) {
612 /* No channels to remove. */
613 return;
614 }
615 channelbag->fcurves_clear();
616 for (const PathValue &path_value : path_values) {
617 replace_pose_key(*bmain,
618 *strip_data,
619 slot,
620 {pose_frame, path_value.value},
621 {path_value.rna_path.path, path_value.rna_path.index.value()});
622 }
623 break;
624 }
625 case MODIFY_REMOVE: {
626 Channelbag *channelbag = strip_data->channelbag_for_slot(slot.handle);
627 if (!channelbag) {
628 /* No channels to remove. */
629 return;
630 }
631 Map<RNAPath, FCurve *> fcurve_map;
633 pose_action, pose_action.slot_array[0]->handle, [&](FCurve &fcurve) {
634 fcurve_map.add({fcurve.rna_path, std::nullopt, fcurve.array_index}, &fcurve);
635 });
636 for (const PathValue &path_value : path_values) {
637 if (existing_paths.contains(path_value.rna_path)) {
638 FCurve *fcurve = fcurve_map.lookup(path_value.rna_path);
639 channelbag->fcurve_remove(*fcurve);
640 }
641 }
642 break;
643 }
644 }
645}
646
648{
650 BLI_assert_msg(action, "Poll should have checked action exists");
651 /* Get asset now. Asset browser might get tagged for refreshing through operations below, and not
652 * allow querying items from context until refreshed, see #140781. */
654
655 Main *bmain = CTX_data_main(C);
656 Object *pose_object = CTX_data_active_object(C);
657 if (!pose_object || !pose_object->pose) {
658 return OPERATOR_CANCELLED;
659 }
660
661 AssetModifyMode mode = AssetModifyMode(RNA_enum_get(op->ptr, "mode"));
662 update_pose_action_from_scene(bmain, action->wrap(), *pose_object, mode);
663 if (!G.background) {
664 asset::generate_preview(C, &action->id);
665 }
666 if (ID_IS_LINKED(action)) {
667 /* Not needed for local assets. */
668 bke::asset_edit_id_save(*bmain, action->id, *op->reports);
669 }
670 else {
671 /* Only create undo-step for local actions. Undoing external files isn't supported. */
672 ED_undo_push_op(C, op);
673 }
674
677
678 return OPERATOR_FINISHED;
679}
680
682{
684 CTX_wm_operator_poll_msg_set(C, "Pose assets can only be modified from Pose Mode");
685 return false;
686 }
687
689
690 if (!action) {
691 return false;
692 }
693
694 if (!ID_IS_LINKED(action)) {
695 return true;
696 }
697
698 if (!bke::asset_edit_id_is_editable(action->id)) {
699 CTX_wm_operator_poll_msg_set(C, "Action is not editable");
700 return false;
701 }
702
703 if (!bke::asset_edit_id_is_writable(action->id)) {
704 CTX_wm_operator_poll_msg_set(C, "Asset blend file is not editable");
705 return false;
706 }
707
708 return true;
709}
710
711static std::string pose_asset_modify_description(bContext * /* C */,
712 wmOperatorType * /* ot */,
714{
715 const int mode = RNA_enum_get(ptr, "mode");
716 return TIP_(std::string(prop_asset_overwrite_modes[mode].description));
717}
718
719/* Calling it overwrite instead of save because we aren't actually saving an opened asset. */
721{
722 ot->name = "Modify Pose Asset";
723 ot->description =
724 "Update the selected pose asset in the asset library from the currently selected bones. The "
725 "mode defines how the asset is updated";
726 ot->idname = "POSELIB_OT_asset_modify";
727
730 ot->get_description = pose_asset_modify_description;
731
732 RNA_def_enum(ot->srna,
733 "mode",
736 "Overwrite Mode",
737 "Specify which parts of the pose asset are overwritten");
738}
739
741{
743
744 if (!action) {
745 return false;
746 }
747
748 if (!ID_IS_LINKED(action)) {
749 return true;
750 }
751
752 if (!bke::asset_edit_id_is_editable(action->id)) {
753 CTX_wm_operator_poll_msg_set(C, "Action is not editable");
754 return false;
755 }
756
757 if (!bke::asset_edit_id_is_writable(action->id)) {
758 CTX_wm_operator_poll_msg_set(C, "Asset blend file is not editable");
759 return false;
760 }
761
762 return true;
763}
764
766{
768 if (!action) {
769 return OPERATOR_CANCELLED;
770 }
771
773 std::optional<AssetLibraryReference> library_ref =
774 asset->owner_asset_library().library_reference();
775
776 if (ID_IS_LINKED(action)) {
778 }
779 else {
780 asset::clear_id(&action->id);
781 /* Only create undo-step for local actions. Undoing external files isn't supported. */
782 ED_undo_push_op(C, op);
783 }
784
785 asset::refresh_asset_library(C, library_ref.value());
786
788
789 return OPERATOR_FINISHED;
790}
791
793 wmOperator *op,
794 const wmEvent * /*event*/)
795{
797
799 C,
800 op,
801 IFACE_("Delete Pose Asset"),
802 ID_IS_LINKED(action) ?
803 IFACE_("Permanently delete pose asset blend file? This cannot be undone.") :
804 IFACE_("The asset is local to the file. Deleting it will just clear the asset status."),
805 IFACE_("Delete"),
807 false);
808}
809
811{
812 ot->name = "Delete Pose Asset";
813 ot->description = "Delete the selected Pose Asset";
814 ot->idname = "POSELIB_OT_asset_delete";
815
819}
820
821} // 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:2392
struct bUserAssetLibrary * BKE_preferences_asset_library_find_index(const struct UserDef *userdef, int index) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT
@ RPT_ERROR
Definition BKE_report.hh:39
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:153
ARegion * BKE_area_find_region_type(const ScrArea *area, int region_type)
Definition screen.cc:846
#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 TIP_(msgid)
#define IFACE_(msgid)
#define ID_IS_LINKED(_id)
Definition DNA_ID.h:694
@ 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
@ ASSET_LIBRARY_CUSTOM
@ ASSET_LIBRARY_LOCAL
@ HD_AUTO
@ BEZT_IPO_BEZ
@ BEZT_KEYTYPE_KEYFRAME
#define MAX_NAME
Definition DNA_defs.h:50
@ RGN_TYPE_ASSET_SHELF
@ RGN_FLAG_HIDDEN
@ 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:2351
bool ED_operator_posemode_context(bContext *C)
void ED_undo_push_op(bContext *C, wmOperator *op)
Definition ed_undo.cc:359
@ PROP_STRING_SEARCH_SUGGESTION
Definition RNA_types.hh:792
@ PROP_ENUM
Definition RNA_types.hh:166
@ PROP_NONE
Definition RNA_types.hh:233
#define C
Definition RandGen.cpp:29
@ ALERT_ICON_WARNING
#define NA_ADDED
Definition WM_types.hh:586
@ OPTYPE_UNDO
Definition WM_types.hh:182
@ OPTYPE_REGISTER
Definition WM_types.hh:180
#define NA_EDITED
Definition WM_types.hh:584
#define NC_ASSET
Definition WM_types.hh:404
#define NA_REMOVED
Definition WM_types.hh:587
#define ND_ASSET_LIST
Definition WM_types.hh:548
#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 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)
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
bool bone_is_selected(const bArmature *armature, const Bone *bone)
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:160
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
const char * name
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)
std::string RNA_string_get(PointerRNA *ptr, const char *name)
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)
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:423
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:4238
wmOperatorType * ot
Definition wm_files.cc:4237
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, std::optional< std::string > message)
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)