diff --git a/source/blender/editors/space_view3d/space_view3d.cc b/source/blender/editors/space_view3d/space_view3d.cc index 5825b5466f6..25708ee7a67 100644 --- a/source/blender/editors/space_view3d/space_view3d.cc +++ b/source/blender/editors/space_view3d/space_view3d.cc @@ -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); diff --git a/source/blender/editors/space_view3d/view3d_gizmo_light.c b/source/blender/editors/space_view3d/view3d_gizmo_light.c index d967b950bc5..f3db63b9a20 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_light.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_light.c @@ -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; + + /* 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; } /** \} */ diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index 4e768078fe5..b94833dd276 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -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); diff --git a/source/blender/makesrna/intern/rna_light.c b/source/blender/makesrna/intern/rna_light.c index f429fd73cdb..0ff0787de50 100644 --- a/source/blender/makesrna/intern/rna_light.c +++ b/source/blender/makesrna/intern/rna_light.c @@ -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);