Gizmo: add undo and name #104888

Open
Weizhen Huang wants to merge 5 commits from weizhen/blender:enable_gizmo_undo into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
6 changed files with 102 additions and 12 deletions
Showing only changes of commit 599cbe0b04 - Show all commits

View File

@ -173,6 +173,8 @@ static void WIDGETGROUP_light_spot_setup(const bContext *C, wmGizmoGroup *gzgrou
RNA_enum_set(gz->ptr, "transform", ED_GIZMO_ARROW_XFORM_FLAG_INVERTED);
ED_gizmo_arrow3d_set_range_fac(gz, 4.0f);
UI_GetThemeColor3fv(TH_GIZMO_SECONDARY, gz->color);
WM_gizmo_enable_undo(gz, "Adjust");
}
/* Spot blend gizmo. */
@ -187,6 +189,10 @@ static void WIDGETGROUP_light_spot_setup(const bContext *C, wmGizmoGroup *gzgrou
UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color);
UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi);
/* FIXME: this should ideally use RNA with a way to intercept the value and transform it based
* on the context (3D scene, viewport... etc), instead of using custom getter/setter and call
* `WM_gizmo_target_property_def_rna()` separately. The same comment applies to spot radius
* gizmo, light point gizmo and possibly light area gizmo. */
WM_gizmo_target_property_def_func(gz,
"matrix",
&(const struct wmGizmoPropertyFnParams){
@ -195,6 +201,8 @@ static void WIDGETGROUP_light_spot_setup(const bContext *C, wmGizmoGroup *gzgrou
.range_get_fn = NULL,
.user_data = (void *)C,
});
WM_gizmo_enable_undo(gz, "Adjust");
}
/* Spot radius gizmo. */
@ -217,6 +225,8 @@ static void WIDGETGROUP_light_spot_setup(const bContext *C, wmGizmoGroup *gzgrou
.range_get_fn = NULL,
.user_data = (void *)C,
});
WM_gizmo_enable_undo(gz, "Adjust");
}
}
@ -229,11 +239,11 @@ static void WIDGETGROUP_light_spot_refresh(const bContext *C, wmGizmoGroup *gzgr
Object *ob = BKE_view_layer_active_object_get(view_layer);
Light *la = ob->data;
PointerRNA lamp_ptr;
RNA_pointer_create(&la->id, &RNA_Light, la, &lamp_ptr);
/* Spot angle gizmo. */
{
PointerRNA lamp_ptr;
RNA_pointer_create(&la->id, &RNA_Light, la, &lamp_ptr);
wmGizmo *gz = ls_gzgroup->spot_angle;
float dir[3];
negate_v3_v3(dir, ob->object_to_world[2]);
@ -255,6 +265,14 @@ static void WIDGETGROUP_light_spot_refresh(const bContext *C, wmGizmoGroup *gzgr
negate_v3_v3(dir, ob->object_to_world[2]);
mul_v3_fl(dir, CONE_SCALE * cosf(0.5f * la->spotsize));
add_v3_v3(gz->matrix_basis[3], dir);
WM_gizmo_target_property_def_rna(gz, "matrix", &lamp_ptr, "spot_blend", -1);
}
/* Spot radius gizmo. */
{
WM_gizmo_target_property_def_rna(
ls_gzgroup->spot_radius, "matrix", &lamp_ptr, "shadow_soft_size", -1);
}
}
@ -343,6 +361,8 @@ static void WIDGETGROUP_light_point_setup(const bContext *C, wmGizmoGroup *gzgro
.range_get_fn = NULL,
.user_data = (void *)C,
});
WM_gizmo_enable_undo(gz, "Adjust");
}
static void WIDGETGROUP_light_point_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
@ -362,6 +382,20 @@ static void WIDGETGROUP_light_point_draw_prepare(const bContext *C, wmGizmoGroup
WM_gizmo_set_matrix_location(gz, ob->object_to_world[3]);
}
static void WIDGETGROUP_light_point_refresh(const bContext *C, wmGizmoGroup *gzgroup)
{
wmGizmoWrapper *wwrapper = gzgroup->customdata;
ViewLayer *view_layer = CTX_data_view_layer(C);
BKE_view_layer_synced_ensure(CTX_data_scene(C), view_layer);
Light *la = BKE_view_layer_active_object_get(view_layer)->data;
PointerRNA lamp_ptr;
RNA_pointer_create(&la->id, &RNA_Light, la, &lamp_ptr);
WM_gizmo_target_property_def_rna(wwrapper->gizmo, "matrix", &lamp_ptr, "shadow_soft_size", -1);
}
void VIEW3D_GGT_light_point(wmGizmoGroupType *gzgt)
{
gzgt->name = "Point Light Widgets";
@ -372,6 +406,7 @@ void VIEW3D_GGT_light_point(wmGizmoGroupType *gzgt)
gzgt->poll = WIDGETGROUP_light_point_poll;
gzgt->setup = WIDGETGROUP_light_point_setup;
gzgt->setup_keymap = WM_gizmogroup_setup_keymap_generic_maybe_drag;
gzgt->refresh = WIDGETGROUP_light_point_refresh;
gzgt->draw_prepare = WIDGETGROUP_light_point_draw_prepare;
}
@ -452,6 +487,8 @@ static void WIDGETGROUP_light_area_setup(const bContext *UNUSED(C), wmGizmoGroup
UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color);
UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi);
WM_gizmo_enable_undo(gz, "Resize");
}
static void WIDGETGROUP_light_area_refresh(const bContext *C, wmGizmoGroup *gzgroup)
@ -472,7 +509,7 @@ static void WIDGETGROUP_light_area_refresh(const bContext *C, wmGizmoGroup *gzgr
}
RNA_enum_set(gz->ptr, "transform", flag);
/* need to set property here for undo. TODO: would prefer to do this in _init. */
/* Need to set property here for `la`. TODO: would prefer to do this in _init. */
WM_gizmo_target_property_def_func(gz,
"matrix",
&(const struct wmGizmoPropertyFnParams){

View File

@ -269,6 +269,7 @@ void WM_gizmo_target_property_clear_rna(struct wmGizmo *gz, const char *idname);
bool WM_gizmo_target_property_is_valid_any(struct wmGizmo *gz);
bool WM_gizmo_target_property_is_valid(const struct wmGizmoProperty *gz_prop);
struct wmGizmoProperty *WM_gizmo_target_property_get_unique(struct wmGizmo *gz);
float WM_gizmo_target_property_float_get(const struct wmGizmo *gz,
struct wmGizmoProperty *gz_prop);
void WM_gizmo_target_property_float_set(struct bContext *C,
@ -508,6 +509,8 @@ void WM_gizmo_group_remove_by_tool(struct bContext *C,
void WM_gizmo_group_tag_remove(struct wmGizmoGroup *gzgroup);
void WM_gizmo_enable_undo(struct wmGizmo *gz, const char *name);
/* Wrap Group Type Callbacks. */
bool WM_gizmo_group_type_poll(const struct bContext *C, const struct wmGizmoGroupType *gzgt);

View File

@ -82,6 +82,9 @@ typedef enum eWM_GizmoFlag {
/** Don't use tool-tips for this gizmo (can be distracting). */
WM_GIZMO_NO_TOOLTIP = (1 << 12),
/** Do an undo push after gizmo tweaking is finished.*/
WM_GIZMO_UNDO = (1 << 13),
} eWM_GizmoFlag;
ENUM_OPERATORS(eWM_GizmoFlag, WM_GIZMO_NO_TOOLTIP);
@ -206,6 +209,9 @@ typedef struct wmGizmoOpElem {
struct wmGizmo {
struct wmGizmo *next, *prev;
/** Text for tooltip, undo. */
const char *name;
/** While we don't have a real type, use this to put type-like vars. */
const struct wmGizmoType *type;

View File

@ -738,4 +738,13 @@ bool WM_gizmo_context_check_drawstep(const struct bContext *C, eWM_GizmoFlagMapD
return true;
}
void WM_gizmo_enable_undo(wmGizmo *gz, const char *name)
{
/* Operators handle undo themselves. */
BLI_assert(gz->op_data == NULL);
WM_gizmo_set_flag(gz, WM_GIZMO_UNDO, true);
gz->name = name;
}
/** \} */

View File

@ -35,6 +35,8 @@
#include "ED_screen.h"
#include "ED_undo.h"
#include "BLT_translation.h"
/* own includes */
#include "wm_gizmo_intern.h"
#include "wm_gizmo_wmapi.h"
@ -451,8 +453,25 @@ static bool gizmo_tweak_start_and_finish(
static void gizmo_tweak_finish(bContext *C, wmOperator *op, const bool cancel, bool clear_modal)
{
GizmoTweakData *mtweak = op->customdata;
if (mtweak->gz_modal->type->exit) {
mtweak->gz_modal->type->exit(C, mtweak->gz_modal, cancel);
wmGizmo *gz = mtweak->gz_modal;
if (gz->type->exit) {
/* Push undo if needed. */
if ((gz->flag & WM_GIZMO_UNDO) && !cancel) {
const wmGizmoProperty *gz_prop = WM_gizmo_target_property_get_unique(gz);
Review

I find this get_unique concept quite strange, it is here because gizmos are allowed to have multiple properties, and if there are multiple I don't know which one just got edited, and could it be that only one of them has undo.

I find this `get_unique` concept quite strange, it is here because gizmos are allowed to have multiple properties, and if there are multiple I don't know which one just got edited, and could it be that only one of them has undo.
if (!gz_prop || RNA_struct_undo_check(gz_prop->ptr.type)) {
/* Use the name of `wmGizmoGroupType` if we don't know which RNA property this gizmo is
* editting. */
const char *prop_name = gz_prop ? RNA_property_ui_name(gz_prop->prop) :
N_(gz->parent_gzgroup->type->name);
char *undo_str = (gz->name && gz->name[0]) ?
BLI_sprintfN("%s: %s", TIP_(gz->name), prop_name) :
BLI_strdup(prop_name);
ED_undo_push(C, undo_str);
MEM_freeN(undo_str);
}
}
gz->type->exit(C, mtweak->gz_modal, cancel);
}
if (clear_modal) {
/* The gizmo may have been removed. */
@ -606,12 +625,6 @@ void GIZMOGROUP_OT_gizmo_tweak(wmOperatorType *ot)
/* api callbacks */
ot->invoke = gizmo_tweak_invoke;
ot->modal = gizmo_tweak_modal;
/* TODO(@ideasman42): This causes problems tweaking settings for operators,
* need to find a way to support this. */
#if 0
ot->flag = OPTYPE_UNDO;
#endif
}
wmKeyMap *wm_gizmogroup_tweak_modal_keymap(wmKeyConfig *keyconf)

View File

@ -156,6 +156,28 @@ bool WM_gizmo_target_property_is_valid_any(wmGizmo *gz)
return false;
}
/* Get the `*wmGizmoProperty` with valid `PropertyRNA`. If there is none or multiple, returns
* `NULL`. */
wmGizmoProperty *WM_gizmo_target_property_get_unique(wmGizmo *gz)
{
int count = 0;
wmGizmoProperty *gz_unique_prop;
wmGizmoProperty *gz_prop_array = wm_gizmo_target_property_array(gz);
for (int i = 0; i < gz->type->target_property_defs_len; i++) {
wmGizmoProperty *gz_prop = &gz_prop_array[i];
if (gz_prop->prop != NULL) {
count++;
gz_unique_prop = gz_prop;
}
}
if (count == 1) {
return gz_unique_prop;
}
return NULL;
}
bool WM_gizmo_target_property_is_valid(const wmGizmoProperty *gz_prop)
{
return ((gz_prop->prop != NULL) ||