Gizmo: add gizmos for spot and point light radius #104410

Merged
Weizhen Huang merged 2 commits from weizhen/blender:spot_point_radius into main 2023-02-13 11:18:30 +01:00
4 changed files with 174 additions and 1 deletions

View File

@ -1022,6 +1022,7 @@ static void view3d_widgets()
WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_xform_gizmo_context);
WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_light_spot);
WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_light_point);
WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_light_area);
WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_light_target);
WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_force_field);

View File

@ -42,6 +42,7 @@
typedef struct LightSpotWidgetGroup {
wmGizmo *spot_angle;
wmGizmo *spot_blend;
wmGizmo *spot_radius;
} LightSpotWidgetGroup;
static void gizmo_spot_blend_prop_matrix_get(const wmGizmo *UNUSED(gz),
@ -94,6 +95,48 @@ static void gizmo_spot_blend_prop_matrix_set(const wmGizmo *UNUSED(gz),
RNA_property_update_main(CTX_data_main(C), scene, &light_ptr, spot_blend_prop);
}
/* Used by spot light and point light. */
static void gizmo_light_radius_prop_matrix_get(const wmGizmo *UNUSED(gz),
wmGizmoProperty *gz_prop,
void *value_p)
{
BLI_assert(gz_prop->type->array_length == 16);
float(*matrix)[4] = value_p;
const bContext *C = gz_prop->custom_func.user_data;
ViewLayer *view_layer = CTX_data_view_layer(C);
BKE_view_layer_synced_ensure(CTX_data_scene(C), view_layer);
const Light *la = BKE_view_layer_active_object_get(view_layer)->data;
weizhen marked this conversation as resolved
Review

Can be const.

Can be const.
/* Draw gizmo even when radius is zero. */
const float diameter = fmaxf(2.0f * la->radius, 1e-2f);
matrix[0][0] = diameter;
matrix[1][1] = diameter;
}
static void gizmo_light_radius_prop_matrix_set(const wmGizmo *UNUSED(gz),
wmGizmoProperty *gz_prop,
const void *value_p)
{
const float(*matrix)[4] = value_p;
BLI_assert(gz_prop->type->array_length == 16);
const bContext *C = gz_prop->custom_func.user_data;
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
BKE_view_layer_synced_ensure(scene, view_layer);
Light *la = BKE_view_layer_active_object_get(view_layer)->data;
const float radius = 0.5f * len_v3(matrix[0]);
PointerRNA light_ptr;
RNA_pointer_create(&la->id, &RNA_Light, la, &light_ptr);
PropertyRNA *radius_prop = RNA_struct_find_property(&light_ptr, "shadow_soft_size");
RNA_property_float_set(&light_ptr, radius_prop, radius);
RNA_property_update_main(CTX_data_main(C), scene, &light_ptr, radius_prop);
}
static bool WIDGETGROUP_light_spot_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt))
{
View3D *v3d = CTX_wm_view3d(C);
@ -154,6 +197,28 @@ static void WIDGETGROUP_light_spot_setup(const bContext *C, wmGizmoGroup *gzgrou
.user_data = (void *)C,
});
}
/* Spot radius gizmo. */
{
ls_gzgroup->spot_radius = WM_gizmo_new("GIZMO_GT_cage_2d", gzgroup, NULL);
wmGizmo *gz = ls_gzgroup->spot_radius;
RNA_enum_set(gz->ptr,
"transform",
ED_GIZMO_CAGE_XFORM_FLAG_SCALE | ED_GIZMO_CAGE_XFORM_FLAG_SCALE_UNIFORM);
RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_CAGE2D_STYLE_CIRCLE);
WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_HOVER, true);
UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color);
UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi);
WM_gizmo_target_property_def_func(gz,
"matrix",
&(const struct wmGizmoPropertyFnParams){
.value_get_fn = gizmo_light_radius_prop_matrix_get,
.value_set_fn = gizmo_light_radius_prop_matrix_set,
.range_get_fn = NULL,
.user_data = (void *)C,
});
}
}
static void WIDGETGROUP_light_spot_refresh(const bContext *C, wmGizmoGroup *gzgroup)
@ -165,6 +230,7 @@ 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;
/* Spot angle gizmo. */
{
PointerRNA lamp_ptr;
RNA_pointer_create(&la->id, &RNA_Light, la, &lamp_ptr);
@ -179,6 +245,7 @@ static void WIDGETGROUP_light_spot_refresh(const bContext *C, wmGizmoGroup *gzgr
WM_gizmo_target_property_def_rna(gz, "offset", &lamp_ptr, propname, -1);
}
/* Spot blend gizmo. */
{
wmGizmo *gz = ls_gzgroup->spot_blend;
@ -192,6 +259,23 @@ static void WIDGETGROUP_light_spot_refresh(const bContext *C, wmGizmoGroup *gzgr
}
}
static void WIDGETGROUP_light_spot_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
{
LightSpotWidgetGroup *ls_gzgroup = gzgroup->customdata;
ViewLayer *view_layer = CTX_data_view_layer(C);
BKE_view_layer_synced_ensure(CTX_data_scene(C), view_layer);
Object *ob = BKE_view_layer_active_object_get(view_layer);
/* Spot radius gizmo. */
wmGizmo *gz = ls_gzgroup->spot_radius;
/* Draw circle in the screen space. */
RegionView3D *rv3d = CTX_wm_region(C)->regiondata;
WM_gizmo_set_matrix_rotation_from_z_axis(gz, rv3d->viewinv[2]);
WM_gizmo_set_matrix_location(gz, ob->object_to_world[3]);
}
void VIEW3D_GGT_light_spot(wmGizmoGroupType *gzgt)
{
gzgt->name = "Spot Light Widgets";
@ -203,6 +287,93 @@ void VIEW3D_GGT_light_spot(wmGizmoGroupType *gzgt)
gzgt->setup = WIDGETGROUP_light_spot_setup;
gzgt->setup_keymap = WM_gizmogroup_setup_keymap_generic_maybe_drag;
gzgt->refresh = WIDGETGROUP_light_spot_refresh;
gzgt->draw_prepare = WIDGETGROUP_light_spot_draw_prepare;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Point Light Gizmo
* \{ */
static bool WIDGETGROUP_light_point_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt))
{
const View3D *v3d = CTX_wm_view3d(C);
if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_CONTEXT)) {
return false;
}
if ((v3d->gizmo_show_light & V3D_GIZMO_SHOW_LIGHT_SIZE) == 0) {
return false;
}
const Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
BKE_view_layer_synced_ensure(scene, view_layer);
const Base *base = BKE_view_layer_active_base_get(view_layer);
if (base && BASE_SELECTABLE(v3d, base)) {
const Object *ob = base->object;
if (ob->type == OB_LAMP) {
const Light *la = ob->data;
return (la->type == LA_LOCAL);
}
}
return false;
}
static void WIDGETGROUP_light_point_setup(const bContext *C, wmGizmoGroup *gzgroup)
{
wmGizmoWrapper *wwrapper = MEM_mallocN(sizeof(wmGizmoWrapper), __func__);
wwrapper->gizmo = WM_gizmo_new("GIZMO_GT_cage_2d", gzgroup, NULL);
/* Point radius gizmo. */
wmGizmo *gz = wwrapper->gizmo;
gzgroup->customdata = wwrapper;
RNA_enum_set(gz->ptr,
"transform",
ED_GIZMO_CAGE_XFORM_FLAG_SCALE | ED_GIZMO_CAGE_XFORM_FLAG_SCALE_UNIFORM);
RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_CAGE2D_STYLE_CIRCLE);
WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_HOVER, true);
UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color);
UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi);
WM_gizmo_target_property_def_func(gz,
"matrix",
&(const struct wmGizmoPropertyFnParams){
.value_get_fn = gizmo_light_radius_prop_matrix_get,
.value_set_fn = gizmo_light_radius_prop_matrix_set,
.range_get_fn = NULL,
.user_data = (void *)C,
});
}
static void WIDGETGROUP_light_point_draw_prepare(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);
const Object *ob = BKE_view_layer_active_object_get(view_layer);
/* Point radius gizmo. */
wmGizmo *gz = wwrapper->gizmo;
/* Draw circle in the screen space. */
const RegionView3D *rv3d = CTX_wm_region(C)->regiondata;
WM_gizmo_set_matrix_rotation_from_z_axis(gz, rv3d->viewinv[2]);
WM_gizmo_set_matrix_location(gz, ob->object_to_world[3]);
}
void VIEW3D_GGT_light_point(wmGizmoGroupType *gzgt)
{
gzgt->name = "Point Light Widgets";
gzgt->idname = "VIEW3D_GGT_light_point";
gzgt->flag |= (WM_GIZMOGROUPTYPE_PERSISTENT | WM_GIZMOGROUPTYPE_3D | WM_GIZMOGROUPTYPE_DEPTH_3D);
gzgt->poll = WIDGETGROUP_light_point_poll;
gzgt->setup = WIDGETGROUP_light_point_setup;
gzgt->setup_keymap = WM_gizmogroup_setup_keymap_generic_maybe_drag;
gzgt->draw_prepare = WIDGETGROUP_light_point_draw_prepare;
}
/** \} */

View File

@ -212,6 +212,7 @@ extern const char *view3d_context_dir[]; /* doc access */
/* view3d_widgets.c */
void VIEW3D_GGT_light_spot(struct wmGizmoGroupType *gzgt);
void VIEW3D_GGT_light_point(struct wmGizmoGroupType *gzgt);
void VIEW3D_GGT_light_area(struct wmGizmoGroupType *gzgt);
void VIEW3D_GGT_light_target(struct wmGizmoGroupType *gzgt);
void VIEW3D_GGT_camera(struct wmGizmoGroupType *gzgt);

View File

@ -341,7 +341,7 @@ static void rna_def_light_shadow(StructRNA *srna, bool sun)
RNA_def_property_ui_range(prop, 0, 100, 0.1, 3);
RNA_def_property_ui_text(
prop, "Shadow Soft Size", "Light size for ray shadow sampling (Raytraced shadows)");
RNA_def_property_update(prop, 0, "rna_Light_update");
RNA_def_property_update(prop, 0, "rna_Light_draw_update");
/* Eevee */
prop = RNA_def_property(srna, "use_contact_shadow", PROP_BOOLEAN, PROP_NONE);