WIP: Onion Skinning Prototype #107641

Closed
Christoph Lendenfeld wants to merge 22 commits from ChrisLend/blender:onion_skin_test into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
20 changed files with 543 additions and 3 deletions

View File

@ -1056,6 +1056,7 @@ def km_time_scrub(_params):
items.extend([
("anim.change_frame", {"type": 'LEFTMOUSE', "value": 'PRESS'}, None),
("anim.change_onion_skin_range", {"type": 'LEFTMOUSE', "value": 'PRESS', "alt": True}, None),
])
return keymap

View File

@ -715,6 +715,33 @@ class RENDER_PT_gpencil(RenderButtonsPanel, Panel):
col.prop(props, "antialias_threshold")
class RENDER_PT_onion_skins(RenderButtonsPanel, Panel):
bl_label = "Onion Skins"
bl_options = {'DEFAULT_CLOSED'}
bl_order = 10
COMPAT_ENGINES = {
'BLENDER_RENDER',
'BLENDER_EEVEE',
'BLENDER_EEVEE_NEXT',
'BLENDER_WORKBENCH',
'BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
# layout.use_property_split = True
# layout.use_property_decorate = False # No animation.
scene = context.scene
col = layout.column()
col.prop(scene, "onion_skin_color_left")
col.prop(scene, "onion_skin_color_right")
col.prop(scene, "os_relative_left")
col.prop(scene, "os_relative_right")
col.prop(scene, "onion_skin_alpha")
col.prop(scene, "onion_skin_draw_modes")
class RENDER_PT_opengl_sampling(RenderButtonsPanel, Panel):
bl_label = "Sampling"
COMPAT_ENGINES = {'BLENDER_WORKBENCH', 'BLENDER_WORKBENCH_NEXT'}
@ -921,6 +948,8 @@ classes = (
RENDER_PT_simplify_viewport,
RENDER_PT_simplify_render,
RENDER_PT_simplify_greasepencil,
RENDER_PT_onion_skins,
)
if __name__ == "__main__": # only for live edit.

View File

@ -6532,7 +6532,7 @@ class VIEW3D_PT_overlay_geometry(Panel):
col.prop(overlay, "show_face_orientation")
# sub.prop(overlay, "show_onion_skins")
sub.prop(overlay, "show_onion_skins")
class VIEW3D_PT_overlay_motion_tracking(Panel):

View File

@ -225,6 +225,7 @@ set(SRC
engines/overlay/overlay_viewer_attribute.cc
engines/overlay/overlay_volume.cc
engines/overlay/overlay_wireframe.cc
engines/overlay/overlay_onion_skin.cc
DRW_engine.h
DRW_pbvh.hh
@ -698,6 +699,8 @@ set(GLSL_SRC
engines/overlay/shaders/overlay_motion_path_line_vert.glsl
engines/overlay/shaders/overlay_motion_path_line_vert_no_geom.glsl
engines/overlay/shaders/overlay_motion_path_point_vert.glsl
engines/overlay/shaders/overlay_onion_skin_mesh_frag.glsl
engines/overlay/shaders/overlay_onion_skin_mesh_vert.glsl
engines/overlay/shaders/overlay_outline_detect_frag.glsl
engines/overlay/shaders/overlay_outline_prepass_curves_vert.glsl
engines/overlay/shaders/overlay_outline_prepass_frag.glsl

View File

@ -137,6 +137,7 @@ static void OVERLAY_engine_init(void *vedata)
OVERLAY_outline_init(data);
OVERLAY_wireframe_init(data);
OVERLAY_paint_init(data);
OVERLAY_onion_skin_init(data);
}
static void OVERLAY_cache_init(void *vedata)
@ -365,6 +366,8 @@ static void OVERLAY_cache_populate(void *vedata, Object *ob)
const bool draw_motion_paths = (pd->overlay.flag & V3D_OVERLAY_HIDE_MOTION_PATHS) == 0;
const bool draw_onion_skins = pd->overlay.flag & V3D_OVERLAY_ONION_SKINS;
bool do_init;
OVERLAY_DupliData *dupli = OVERLAY_duplidata_get(ob, vedata, &do_init);
@ -386,6 +389,9 @@ static void OVERLAY_cache_populate(void *vedata, Object *ob)
if (draw_bone_selection) {
OVERLAY_pose_cache_populate(data, ob);
}
if (draw_onion_skins) {
OVERLAY_onion_skin_populate(data, ob);
}
if (pd->overlay.flag & V3D_OVERLAY_VIEWER_ATTRIBUTE) {
if (is_preview) {
@ -686,6 +692,7 @@ static void OVERLAY_draw_scene(void *vedata)
OVERLAY_image_in_front_draw(data);
OVERLAY_motion_path_draw(data);
OVERLAY_onion_skin_draw(data);
OVERLAY_extra_centers_draw(data);
if (DRW_state_is_select() || DRW_state_is_depth()) {

View File

@ -0,0 +1,88 @@
#include "BKE_mesh.h"
#include "DRW_render.h"
#include "draw_cache_impl.h"
#include "overlay_private.hh"
void OVERLAY_onion_skin_init(OVERLAY_Data *vedata)
{
OVERLAY_PassList *psl = vedata->psl;
OVERLAY_PrivateData *pd = vedata->stl->pd;
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA;
DRW_PASS_CREATE(psl->onion_skin_ps, state | pd->clipping_state);
DRWShadingGroup *grp;
GPUShader *shader = OVERLAY_shader_onion_skin_mesh();
pd->onion_skin_grp = grp = DRW_shgroup_create(shader, psl->onion_skin_ps);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
GPUShader *shader_outline = OVERLAY_shader_onion_skin_outline();
pd->onion_skin_outline_grp = grp = DRW_shgroup_create(shader_outline, psl->onion_skin_ps);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
}
static bool str_equals(const char *__restrict str, const char *__restrict start)
{
for (; *str && *start; str++, start++) {
if (*str != *start) {
return false;
}
}
return (*start == *str);
}
void OVERLAY_onion_skin_populate(OVERLAY_Data *vedata, Object *ob)
{
OVERLAY_PrivateData *pd = vedata->stl->pd;
const DRWContextState *draw_ctx = DRW_context_state_get();
Scene *scene = draw_ctx->scene;
const float current_frame = BKE_scene_ctime_get(scene);
DRWShadingGroup *grp = nullptr;
if (scene->onion_skin_cache.draw_method == ONION_SKIN_DRAW_SOLID) {
grp = pd->onion_skin_grp;
}
else {
grp = pd->onion_skin_outline_grp;
}
DRW_shgroup_uniform_float_copy(grp, "alpha", scene->onion_skin_cache.alpha);
LISTBASE_FOREACH (OnionSkinMeshLink *, mesh_link, &scene->onion_skin_cache.objects) {
if (!str_equals(ob->id.name, mesh_link->object->id.name)) {
continue;
}
if (compare_ff(mesh_link->frame, current_frame, FLT_EPSILON)) {
continue;
}
if (mesh_link->frame < current_frame - scene->onion_skin_cache.relative_left) {
continue;
}
if (mesh_link->frame > current_frame + scene->onion_skin_cache.relative_right) {
continue;
}
if (mesh_link->frame < current_frame) {
DRW_shgroup_uniform_vec3_copy(grp, "color", draw_ctx->scene->onion_skin_cache.color_left);
}
else {
DRW_shgroup_uniform_vec3_copy(grp, "color", draw_ctx->scene->onion_skin_cache.color_right);
}
struct GPUBatch *geom = DRW_cache_object_surface_get(ob);
if (geom) {
DRW_shgroup_call(grp, geom, ob);
}
}
}
void OVERLAY_onion_skin_draw(OVERLAY_Data *vedata)
{
OVERLAY_PassList *psl = vedata->psl;
DRW_draw_pass(psl->onion_skin_ps);
}

View File

@ -113,6 +113,7 @@ typedef struct OVERLAY_PassList {
DRWPass *image_foreground_scene_ps;
DRWPass *metaball_ps[2];
DRWPass *motion_paths_ps;
DRWPass *onion_skin_ps;
DRWPass *outlines_prepass_ps;
DRWPass *outlines_detect_ps;
DRWPass *outlines_resolve_ps;
@ -279,6 +280,8 @@ typedef struct OVERLAY_PrivateData {
DRWShadingGroup *flash_grp[2];
DRWShadingGroup *motion_path_lines_grp;
DRWShadingGroup *motion_path_points_grp;
DRWShadingGroup *onion_skin_grp;
DRWShadingGroup *onion_skin_outline_grp;
DRWShadingGroup *outlines_grp;
DRWShadingGroup *outlines_curves_grp;
DRWShadingGroup *outlines_ptcloud_grp;
@ -653,6 +656,7 @@ void OVERLAY_image_empty_cache_populate(OVERLAY_Data *vedata, Object *ob);
void OVERLAY_image_cache_finish(OVERLAY_Data *vedata);
void OVERLAY_image_draw(OVERLAY_Data *vedata);
void OVERLAY_image_background_draw(OVERLAY_Data *vedata);
/**
* This function draws images that needs the view transform applied.
* It draws these images directly into the scene color buffer.
@ -670,6 +674,10 @@ void OVERLAY_motion_path_cache_init(OVERLAY_Data *vedata);
void OVERLAY_motion_path_cache_populate(OVERLAY_Data *vedata, Object *ob);
void OVERLAY_motion_path_draw(OVERLAY_Data *vedata);
void OVERLAY_onion_skin_init(OVERLAY_Data *vedata);
void OVERLAY_onion_skin_populate(OVERLAY_Data *vedata, Object *ob);
void OVERLAY_onion_skin_draw(OVERLAY_Data *vedata);
void OVERLAY_outline_init(OVERLAY_Data *vedata);
void OVERLAY_outline_cache_init(OVERLAY_Data *vedata);
void OVERLAY_outline_cache_populate(OVERLAY_Data *vedata,
@ -769,6 +777,8 @@ GPUShader *OVERLAY_shader_grid_image(void);
GPUShader *OVERLAY_shader_image(void);
GPUShader *OVERLAY_shader_motion_path_line(void);
GPUShader *OVERLAY_shader_motion_path_vert(void);
GPUShader *OVERLAY_shader_onion_skin_mesh(void);
GPUShader *OVERLAY_shader_onion_skin_outline(void);
GPUShader *OVERLAY_shader_uniform_color(void);
GPUShader *OVERLAY_shader_uniform_color_pointcloud(void);
GPUShader *OVERLAY_shader_outline_prepass(bool use_wire);

View File

@ -78,6 +78,8 @@ struct OVERLAY_Shaders {
GPUShader *image;
GPUShader *motion_path_line;
GPUShader *motion_path_vert;
GPUShader *onion_skin_mesh;
GPUShader *onion_skin_outline;
GPUShader *outline_prepass;
GPUShader *outline_prepass_curves;
GPUShader *outline_prepass_gpencil;
@ -685,6 +687,26 @@ GPUShader *OVERLAY_shader_motion_path_vert(void)
return sh_data->motion_path_vert;
}
GPUShader *OVERLAY_shader_onion_skin_mesh(void)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
if (!sh_data->onion_skin_mesh) {
sh_data->onion_skin_mesh = GPU_shader_create_from_info_name("overlay_onion_skin_mesh");
}
return sh_data->onion_skin_mesh;
}
GPUShader *OVERLAY_shader_onion_skin_outline(void)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
if (!sh_data->onion_skin_outline) {
sh_data->onion_skin_outline = GPU_shader_create_from_info_name("overlay_outline_detect");
}
return sh_data->onion_skin_outline;
}
GPUShader *OVERLAY_shader_outline_prepass(bool use_wire)
{
const DRWContextState *draw_ctx = DRW_context_state_get();

View File

@ -248,6 +248,26 @@ GPU_SHADER_CREATE_INFO(overlay_motion_path_point_clipped)
/** \} */
/* -------------------------------------------------------------------- */
/** \name Onion Skin
* \{ */
GPU_SHADER_INTERFACE_INFO(onion_skin_iface, "interp").smooth(Type::VEC4, "color");
GPU_SHADER_CREATE_INFO(overlay_onion_skin_mesh)
.do_static_compilation(true)
.vertex_in(0, Type::VEC3, "pos")
.vertex_out(onion_skin_iface)
.push_constant(Type::VEC3, "color")
.push_constant(Type::FLOAT, "alpha")
.push_constant(Type::INT, "draw_method")
.fragment_out(0, Type::VEC4, "fragColor")
.fragment_source("overlay_onion_skin_mesh_frag.glsl")
.vertex_source("overlay_onion_skin_mesh_vert.glsl")
.additional_info("draw_mesh", "draw_globals");
/** \} */
/* -------------------------------------------------------------------- */
/** \name Image Empty
* \{ */

View File

@ -0,0 +1,4 @@
void main()
{
fragColor = interp.color;
}

View File

@ -0,0 +1,11 @@
#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl)
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
void main()
{
interp.color.rgb = color;
interp.color.a = alpha;
vec3 world_pos = point_object_to_world(pos);
gl_Position = point_world_to_ndc(world_pos);
/* view_clipping_distances(world_pos); */
}

View File

@ -29,6 +29,7 @@ set(SRC
anim_ipo_utils.c
anim_markers.c
anim_motion_paths.c
anim_onion_skin.c
anim_ops.c
drivers.c
fmodifier_ui.c

View File

@ -0,0 +1,99 @@
#include "BKE_context.h"
#include "BKE_layer.h"
#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_object.h"
#include "BKE_scene.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
#include "DNA_scene_types.h"
#include "DNA_windowmanager_types.h"
#include "ED_onion_skin.h"
#include "ED_outliner.h"
#include "MEM_guardedalloc.h"
#include "WM_api.h"
#include "WM_types.h"
static void graveyard()
{
ListBase selected = {NULL, NULL};
LISTBASE_FOREACH (CollectionPointerLink *, object_ptr_link, &selected) {
/* Mesh *mesh = BKE_mesh_from_object(ob);
if (!mesh) {
continue;
} */
/* Mesh *copy = BKE_mesh_copy_for_eval(mesh); */
/* Mesh *mesh_result = (Mesh *)BKE_id_copy_ex(
NULL, &mesh->id, NULL, LIB_ID_CREATE_NO_MAIN | LIB_ID_CREATE_NO_USER_REFCOUNT); */
/*
OnionSkinMeshLink *link = MEM_callocN(sizeof(OnionSkinMeshLink), "onion skin mesh link");
link->mesh = copy;
BLI_addtail(&scene->onion_skin_cache.meshes, link); */
}
BLI_freelistN(&selected);
}
static int onion_skin_add_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
Main *bmain = CTX_data_main(C);
BKE_main_id_newptr_and_tag_clear(bmain);
ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob = CTX_data_active_object(C);
if (!ob) {
return OPERATOR_CANCELLED;
}
Mesh *mesh = BKE_mesh_from_object(ob);
if (!mesh) {
return OPERATOR_CANCELLED;
}
/* Mesh *copy = BKE_mesh_copy_for_eval(mesh); */
/* Mesh *copy = (Mesh *)BKE_id_copy_ex(bmain, &mesh->id, NULL, LIB_ID_COPY_DEFAULT); */
Object *ob_new = BKE_object_duplicate(bmain,
ob,
(eDupli_ID_Flags)U.dupflag,
LIB_ID_DUPLICATE_IS_SUBPROCESS |
LIB_ID_DUPLICATE_IS_ROOT_ID);
LayerCollection *layer_collection = BKE_layer_collection_from_index(view_layer, 2);
BKE_collection_object_add(bmain, layer_collection->collection, ob_new);
OnionSkinMeshLink *link = MEM_callocN(sizeof(OnionSkinMeshLink), "onion skin mesh link");
link->object = ob_new;
ob_new->adt = NULL;
link->frame = BKE_scene_ctime_get(scene);
BLI_addtail(&scene->onion_skin_cache.objects, link);
ED_outliner_select_sync_from_object_tag(C);
DEG_relations_tag_update(bmain);
DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT | ND_LAYER_CONTENT, scene);
return OPERATOR_FINISHED;
}
static void ANIM_OT_onion_skin_add(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Add Onion Skin";
ot->description = "foobar";
ot->idname = "ANIM_OT_onion_skin_add";
/* api callbacks */
ot->exec = onion_skin_add_exec;
/* ot->cancel = WM_gesture_box_cancel; */
/* ot->poll = ed_markers_poll_markers_exist; */
/* flags */
ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER;
/* properties */
}
void ED_operatortypes_onion_skin(void)
{
WM_operatortype_append(ANIM_OT_onion_skin_add);
}

View File

@ -395,6 +395,138 @@ static void ANIM_OT_change_frame(wmOperatorType *ot)
/** \} */
/* Set the new frame number */
static void change_onion_skin_range_apply(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
const int left = RNA_int_get(op->ptr, "left");
const int right = RNA_int_get(op->ptr, "right");
scene->onion_skin_cache.relative_left = left;
scene->onion_skin_cache.relative_right = right;
DEG_id_tag_update(&scene->id, ID_RECALC_FRAME_CHANGE);
WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
}
static void onion_skin_range_foo(bContext *C, wmOperator *op, const wmEvent *event)
{
Scene *scene = CTX_data_scene(C);
const int clicked_frame = roundf(frame_from_event(C, event));
const int current_scene_frame = BKE_scene_ctime_get(scene);
if (clicked_frame > current_scene_frame) {
RNA_int_set(op->ptr, "right", clicked_frame - current_scene_frame);
}
else if (clicked_frame < current_scene_frame) {
RNA_int_set(op->ptr, "left", current_scene_frame - clicked_frame);
}
}
static void change_onion_skin_range_cancel(bContext *C, wmOperator *UNUSED(op))
{
bScreen *screen = CTX_wm_screen(C);
screen->scrubbing = false;
SpaceSeq *sseq = CTX_wm_space_seq(C);
if (sseq != NULL) {
change_frame_seq_preview_end(sseq);
}
if (need_extra_redraw_after_scrubbing_ends(C)) {
Scene *scene = CTX_data_scene(C);
WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
}
}
/* Modal event handling of frame changing */
static int change_onion_skin_range_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
int ret = OPERATOR_RUNNING_MODAL;
/* execute the events */
switch (event->type) {
case EVT_ESCKEY:
ret = OPERATOR_FINISHED;
break;
case MOUSEMOVE:
onion_skin_range_foo(C, op, event);
change_onion_skin_range_apply(C, op);
break;
case LEFTMOUSE:
case RIGHTMOUSE:
case MIDDLEMOUSE:
/* We check for either mouse-button to end, to work with all user keymaps. */
if (event->val == KM_RELEASE) {
ret = OPERATOR_FINISHED;
}
break;
}
if (ret != OPERATOR_RUNNING_MODAL) {
bScreen *screen = CTX_wm_screen(C);
screen->scrubbing = false;
if (need_extra_redraw_after_scrubbing_ends(C)) {
Scene *scene = CTX_data_scene(C);
WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
}
}
return ret;
}
/* Modal Operator init */
static int change_onion_skin_range_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
ARegion *region = CTX_wm_region(C);
bScreen *screen = CTX_wm_screen(C);
if (CTX_wm_space_seq(C) != NULL && region->regiontype == RGN_TYPE_PREVIEW) {
return OPERATOR_CANCELLED;
}
Scene *scene = CTX_data_scene(C);
RNA_int_set(op->ptr, "right", scene->onion_skin_cache.relative_right);
RNA_int_set(op->ptr, "left", scene->onion_skin_cache.relative_left);
onion_skin_range_foo(C, op, event);
screen->scrubbing = true;
change_onion_skin_range_apply(C, op);
/* add temp handler */
WM_event_add_modal_handler(C, op);
return OPERATOR_RUNNING_MODAL;
}
static int change_onion_skin_range_exec(bContext *C, wmOperator *op)
{
change_onion_skin_range_apply(C, op);
return OPERATOR_FINISHED;
}
static void ANIM_OT_change_onion_skin_range(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Change Onion Skin Range";
ot->idname = "ANIM_OT_change_onion_skin_range";
ot->description = "Interactively change the amount of onion skins shown";
ot->exec = change_onion_skin_range_exec;
ot->poll = change_frame_poll;
ot->invoke = change_onion_skin_range_invoke;
ot->modal = change_onion_skin_range_modal;
ot->cancel = change_onion_skin_range_cancel;
/* rna */
ot->prop = RNA_def_int(
ot->srna, "left", 0, MINAFRAME, MAXFRAME, "Left", "", MINAFRAME, MAXFRAME);
ot->prop = RNA_def_int(
ot->srna, "right", 0, MINAFRAME, MAXFRAME, "Right", "", MINAFRAME, MAXFRAME);
}
/* -------------------------------------------------------------------- */
/** \name Start/End Frame Operators
* \{ */
@ -652,6 +784,7 @@ void ED_operatortypes_anim(void)
{
/* Animation Editors only -------------------------- */
WM_operatortype_append(ANIM_OT_change_frame);
WM_operatortype_append(ANIM_OT_change_onion_skin_range);
WM_operatortype_append(ANIM_OT_start_frame_set);
WM_operatortype_append(ANIM_OT_end_frame_set);

View File

@ -122,6 +122,41 @@ static void draw_current_frame(const Scene *scene,
float outline_color[4];
UI_GetThemeColorShade4fv(TH_CFRAME, 5, outline_color);
if (scene->onion_skin_cache.relative_left != 0) {
const int frame_relative_left = UI_view2d_view_to_region_x(
v2d, current_frame - scene->onion_skin_cache.relative_left);
UI_draw_roundbox_4fv_ex(
&(const rctf){
.xmin = frame_relative_left - box_width / 4 + U.pixelsize / 2,
.xmax = frame_relative_left + box_width / 4 + U.pixelsize / 2,
.ymin = scrub_region_rect->ymin + box_padding,
.ymax = scrub_region_rect->ymax - box_padding,
},
bg_color,
NULL,
1.0f,
outline_color,
U.pixelsize,
4 * UI_SCALE_FAC);
}
if (scene->onion_skin_cache.relative_right != 0) {
const int frame_relative_right = UI_view2d_view_to_region_x(
v2d, current_frame + scene->onion_skin_cache.relative_right);
UI_draw_roundbox_4fv_ex(
&(const rctf){
.xmin = frame_relative_right - box_width / 4 + U.pixelsize / 2,
.xmax = frame_relative_right + box_width / 4 + U.pixelsize / 2,
.ymin = scrub_region_rect->ymin + box_padding,
.ymax = scrub_region_rect->ymax - box_padding,
},
bg_color,
NULL,
1.0f,
outline_color,
U.pixelsize,
4 * UI_SCALE_FAC);
}
UI_draw_roundbox_4fv_ex(
&(const rctf){
.xmin = frame_x - box_width / 2 + U.pixelsize / 2,

View File

@ -0,0 +1,2 @@
void ED_operatortypes_onion_skin(void);

View File

@ -41,6 +41,7 @@
#include "ED_mesh.h"
#include "ED_node.h"
#include "ED_object.h"
#include "ED_onion_skin.h"
#include "ED_paint.h"
#include "ED_physics.h"
#include "ED_render.h"
@ -105,6 +106,7 @@ void ED_spacetypes_init(void)
ED_operatortypes_curves();
ED_operatortypes_armature();
ED_operatortypes_marker();
ED_operatortypes_onion_skin();
ED_operatortypes_metaball();
ED_operatortypes_sound();
ED_operatortypes_render();

View File

@ -1857,6 +1857,28 @@ typedef struct SceneGpencil {
char _pad[4];
} SceneGpencil;
typedef struct OnionSkinMeshLink {
struct OnionSkinMeshLink *prev, *next;
/* Having a Mesh pointer here breaks compilation. Complains about "extern C" issues. */
struct Object *object;
float frame;
char _pad[4];
} OnionSkinMeshLink;
enum {
ONION_SKIN_DRAW_SOLID = 0,
ONION_SKIN_DRAW_OUTLINE = 1,
};
typedef struct SceneOnionSkin {
float color_left[3];
float color_right[3];
float alpha;
int relative_left, relative_right;
int draw_method;
ListBase objects /* OnionSkinMeshLink */;
} SceneOnionSkin;
/** \} */
/* -------------------------------------------------------------------- */
@ -2003,6 +2025,7 @@ typedef struct Scene {
struct SceneDisplay display;
struct SceneEEVEE eevee;
struct SceneGpencil grease_pencil_settings;
struct SceneOnionSkin onion_skin_cache;
} Scene;
/** \} */

View File

@ -671,6 +671,12 @@ static const EnumPropertyItem plane_orientation_items[] = {
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem onion_skin_draw_modes[] = {
{ONION_SKIN_DRAW_SOLID, "SOLID", 0, "Solid", "Draw solid shape"},
{ONION_SKIN_DRAW_OUTLINE, "OUTLINE", 0, "Outline", "Draw outline"},
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem snap_to_items[] = {
{SCE_SNAP_MODE_GEOM, "GEOMETRY", 0, "Geometry", "Snap to all geometry"},
{SCE_SNAP_MODE_NONE, "DEFAULT", 0, "Default", "Use the current snap settings"},
@ -8442,6 +8448,48 @@ void RNA_def_scene(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "SceneGpencil");
RNA_def_property_ui_text(prop, "Grease Pencil", "Grease Pencil settings for the scene");
prop = RNA_def_property(srna, "onion_skin_color_left", PROP_FLOAT, PROP_COLOR);
RNA_def_property_float_sdna(prop, NULL, "onion_skin_cache.color_left");
RNA_def_property_array(prop, 3);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(prop, "Onion Skin Color Left", "Define the color of onion skins");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D | NS_VIEW3D_SHADING, NULL);
prop = RNA_def_property(srna, "onion_skin_color_right", PROP_FLOAT, PROP_COLOR);
RNA_def_property_float_sdna(prop, NULL, "onion_skin_cache.color_right");
RNA_def_property_array(prop, 3);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(prop, "Onion Skin Color Right", "Define the color of onion skins");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D | NS_VIEW3D_SHADING, NULL);
prop = RNA_def_property(srna, "os_relative_left", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_sdna(prop, NULL, "onion_skin_cache.relative_left");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(
prop, "Onion Skin Range Left", "how far to the lef to draw onion skins");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D | NS_VIEW3D_SHADING, NULL);
prop = RNA_def_property(srna, "os_relative_right", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_sdna(prop, NULL, "onion_skin_cache.relative_right");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(
prop, "Onion Skin Range Right", "how far to the lef to draw onion skins");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D | NS_VIEW3D_SHADING, NULL);
prop = RNA_def_property(srna, "onion_skin_alpha", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "onion_skin_cache.alpha");
RNA_def_property_ui_text(prop, "Onion Skin Alpha", "Alpha of drawn onion skins");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_range(prop, 0.0f, 1.0f, 1, 2);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D | NS_VIEW3D_SHADING, NULL);
prop = RNA_def_property(srna, "onion_skin_draw_modes", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "onion_skin_cache.draw_method");
RNA_def_property_enum_items(prop, onion_skin_draw_modes);
RNA_def_property_enum_default(prop, ONION_SKIN_DRAW_SOLID);
RNA_def_property_ui_text(prop, "Onion Skin Draw Modes", "How to draw os's");
/* Nestled Data. */
/* *** Non-Animated *** */
RNA_define_animate_sdna(false);

View File

@ -1542,7 +1542,8 @@ static void rna_3DViewShading_render_pass_set(PointerRNA *ptr, int value)
STRNCPY(shading->aov_name, aov->name);
}
else if (value == EEVEE_RENDER_PASS_BLOOM &&
((scene->eevee.flag & SCE_EEVEE_BLOOM_ENABLED) == 0)) {
((scene->eevee.flag & SCE_EEVEE_BLOOM_ENABLED) == 0))
{
shading->render_pass = EEVEE_RENDER_PASS_COMBINED;
}
else {
@ -3299,7 +3300,8 @@ const EnumPropertyItem *rna_SpaceSpreadsheet_attribute_domain_itemf(bContext *UN
ATTR_DOMAIN_CORNER,
ATTR_DOMAIN_EDGE,
ATTR_DOMAIN_POINT,
ATTR_DOMAIN_FACE)) {
ATTR_DOMAIN_FACE))
{
continue;
}
}