Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorSybren A. Stüvel <sybren@blender.org>2021-07-12 14:23:59 +0300
committerSybren A. Stüvel <sybren@blender.org>2021-07-15 17:12:36 +0300
commit6e01b52100f3f9674c49127cbcc445e7e5c987d2 (patch)
treec7de8d08f05114c415d9431901b506b23c3509dc /source
parentf3610a23d12bc9e490bb8d58120336de9a6cb196 (diff)
Assets: temporarily apply pose when generating preview image
When generating a preview image for a pose, temporarily apply it to the armature. Contrary to the usual pose application, this ignores the selected bones and always applies the entire pose.
Diffstat (limited to 'source')
-rw-r--r--source/blender/editors/render/render_preview.c55
1 files changed, 55 insertions, 0 deletions
diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c
index 7f7ee45a803..9abf15d2198 100644
--- a/source/blender/editors/render/render_preview.c
+++ b/source/blender/editors/render/render_preview.c
@@ -54,7 +54,9 @@
#include "DNA_space_types.h"
#include "DNA_world_types.h"
+#include "BKE_animsys.h"
#include "BKE_appdir.h"
+#include "BKE_armature.h"
#include "BKE_brush.h"
#include "BKE_colortools.h"
#include "BKE_context.h"
@@ -93,6 +95,7 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "ED_armature.h"
#include "ED_datafiles.h"
#include "ED_render.h"
#include "ED_screen.h"
@@ -151,6 +154,10 @@ typedef struct IconPreview {
void *owner;
ID *id, *id_copy; /* May be NULL! (see ICON_TYPE_PREVIEW case in #ui_icon_ensure_deferred()) */
ListBase sizes;
+
+ /* May be NULL, is used for rendering IDs that require some other object for it to be applied on
+ * before the ID can be represented as an image, for example when rendering an Action. */
+ struct Object *active_object;
} IconPreview;
/** \} */
@@ -813,6 +820,47 @@ static void object_preview_render(IconPreview *preview, IconPreviewSize *preview
/** \name Action Preview
* \{ */
+static struct PoseBackup *action_preview_render_prepare(IconPreview *preview)
+{
+ Object *object = preview->active_object;
+ if (object == NULL) {
+ WM_report(RPT_WARNING, "No active object, unable to apply the Action before rendering");
+ return NULL;
+ }
+ if (object->pose == NULL) {
+ WM_reportf(RPT_WARNING,
+ "Object %s has no pose, unable to apply the Action before rendering",
+ object->id.name + 2);
+ return NULL;
+ }
+
+ /* Create a backup of the current pose. */
+ struct bAction *action = (struct bAction *)preview->id;
+ struct PoseBackup *pose_backup = ED_pose_backup_create_all_bones(object, action);
+
+ /* Apply the Action as pose, so that it can be rendered. This assumes the Action represents a
+ * single pose, and that thus the evaluation time doesn't matter. */
+ AnimationEvalContext anim_eval_context = {preview->depsgraph, 0.0f};
+ BKE_pose_apply_action_all_bones(object, action, &anim_eval_context);
+
+ /* Force evaluation of the new pose, before the preview is rendered. */
+ DEG_id_tag_update(&object->id, ID_RECALC_GEOMETRY);
+ DEG_evaluate_on_refresh(preview->depsgraph);
+
+ return pose_backup;
+}
+
+static void action_preview_render_cleanup(IconPreview *preview, struct PoseBackup *pose_backup)
+{
+ if (pose_backup == NULL) {
+ return;
+ }
+ ED_pose_backup_restore(pose_backup);
+ ED_pose_backup_free(pose_backup);
+
+ DEG_id_tag_update(&preview->active_object->id, ID_RECALC_GEOMETRY);
+}
+
/* Render a pose. It is assumed that the pose has already been applied and that the scene camera is
* capturing the pose. In other words, this function just renders from the scene camera without
* evaluating the Action stored in preview->id. */
@@ -827,6 +875,9 @@ static void action_preview_render(IconPreview *preview, IconPreviewSize *preview
BLI_assert(depsgraph != NULL);
BLI_assert(preview->scene == DEG_get_input_scene(depsgraph));
+ /* Apply the pose before getting the evaluated scene, so that the new pose is evaluated. */
+ struct PoseBackup *pose_backup = action_preview_render_prepare(preview);
+
Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
Object *camera_eval = scene_eval->camera;
if (camera_eval == NULL) {
@@ -850,6 +901,8 @@ static void action_preview_render(IconPreview *preview, IconPreviewSize *preview
NULL,
err_out);
+ action_preview_render_cleanup(preview, pose_backup);
+
if (err_out[0] != '\0') {
printf("Error rendering Action %s preview: %s\n", preview->id->name + 2, err_out);
}
@@ -1625,6 +1678,7 @@ void ED_preview_icon_render(
/* Control isn't given back to the caller until the preview is done. So we don't need to copy
* the ID to avoid thread races. */
ip.id_copy = duplicate_ids(id, true);
+ ip.active_object = CTX_data_active_object(C);
icon_preview_add_size(&ip, rect, sizex, sizey);
@@ -1666,6 +1720,7 @@ void ED_preview_icon_job(
ip->bmain = CTX_data_main(C);
ip->depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
ip->scene = DEG_get_input_scene(ip->depsgraph);
+ ip->active_object = CTX_data_active_object(C);
ip->owner = owner;
ip->id = id;
ip->id_copy = duplicate_ids(id, false);