Просмотр исходного кода

Merge pull request #75303 from Calinou/3d-gizmos-only-selected

Show visual-oriented 3D node gizmos only when selected
Yuri Sizov 2 лет назад
Родитель
Сommit
508a758eab

+ 115 - 114
editor/plugins/gizmos/audio_stream_player_3d_gizmo_plugin.cpp

@@ -121,136 +121,137 @@ void AudioStreamPlayer3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gi
 }
 
 void AudioStreamPlayer3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
-	const AudioStreamPlayer3D *player = Object::cast_to<AudioStreamPlayer3D>(p_gizmo->get_node_3d());
-
 	p_gizmo->clear();
 
-	const Ref<Material> icon = get_material("stream_player_3d_icon", p_gizmo);
-
-	if (player->get_attenuation_model() != AudioStreamPlayer3D::ATTENUATION_DISABLED || player->get_max_distance() > CMP_EPSILON) {
-		// Draw a circle to represent sound volume attenuation.
-		// Use only a billboard circle to represent radius.
-		// This helps distinguish AudioStreamPlayer3D gizmos from OmniLight3D gizmos.
-		const Ref<Material> lines_billboard_material = get_material("stream_player_3d_material_billboard", p_gizmo);
-
-		// Soft distance cap varies depending on attenuation model, as some will fade out more aggressively than others.
-		// Multipliers were empirically determined through testing.
-		float soft_multiplier;
-		switch (player->get_attenuation_model()) {
-			case AudioStreamPlayer3D::ATTENUATION_INVERSE_DISTANCE:
-				soft_multiplier = 12.0;
-				break;
-			case AudioStreamPlayer3D::ATTENUATION_INVERSE_SQUARE_DISTANCE:
-				soft_multiplier = 4.0;
-				break;
-			case AudioStreamPlayer3D::ATTENUATION_LOGARITHMIC:
-				soft_multiplier = 3.25;
-				break;
-			default:
-				// Ensures Max Distance's radius visualization is not capped by Unit Size
-				// (when the attenuation mode is Disabled).
-				soft_multiplier = 10000.0;
-				break;
-		}
-
-		// Draw the distance at which the sound can be reasonably heard.
-		// This can be either a hard distance cap with the Max Distance property (if set above 0.0),
-		// or a soft distance cap with the Unit Size property (sound never reaches true zero).
-		// When Max Distance is 0.0, `r` represents the distance above which the
-		// sound can't be heard in *most* (but not all) scenarios.
-		float r;
-		if (player->get_max_distance() > CMP_EPSILON) {
-			r = MIN(player->get_unit_size() * soft_multiplier, player->get_max_distance());
-		} else {
-			r = player->get_unit_size() * soft_multiplier;
-		}
-		Vector<Vector3> points_billboard;
-
-		for (int i = 0; i < 120; i++) {
-			// Create a circle.
-			const float ra = Math::deg_to_rad((float)(i * 3));
-			const float rb = Math::deg_to_rad((float)((i + 1) * 3));
-			const Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * r;
-			const Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * r;
-
-			// Draw a billboarded circle.
-			points_billboard.push_back(Vector3(a.x, a.y, 0));
-			points_billboard.push_back(Vector3(b.x, b.y, 0));
-		}
-
-		Color color;
-		switch (player->get_attenuation_model()) {
-			// Pick cold colors for all attenuation models (except Disabled),
-			// so that soft caps can be easily distinguished from hard caps
-			// (which use warm colors).
-			case AudioStreamPlayer3D::ATTENUATION_INVERSE_DISTANCE:
-				color = Color(0.4, 0.8, 1);
-				break;
-			case AudioStreamPlayer3D::ATTENUATION_INVERSE_SQUARE_DISTANCE:
-				color = Color(0.4, 0.5, 1);
-				break;
-			case AudioStreamPlayer3D::ATTENUATION_LOGARITHMIC:
-				color = Color(0.4, 0.2, 1);
-				break;
-			default:
-				// Disabled attenuation mode.
-				// This is never reached when Max Distance is 0, but the
-				// hue-inverted form of this color will be used if Max Distance is greater than 0.
-				color = Color(1, 1, 1);
-				break;
+	if (p_gizmo->is_selected()) {
+		const AudioStreamPlayer3D *player = Object::cast_to<AudioStreamPlayer3D>(p_gizmo->get_node_3d());
+
+		if (player->get_attenuation_model() != AudioStreamPlayer3D::ATTENUATION_DISABLED || player->get_max_distance() > CMP_EPSILON) {
+			// Draw a circle to represent sound volume attenuation.
+			// Use only a billboard circle to represent radius.
+			// This helps distinguish AudioStreamPlayer3D gizmos from OmniLight3D gizmos.
+			const Ref<Material> lines_billboard_material = get_material("stream_player_3d_material_billboard", p_gizmo);
+
+			// Soft distance cap varies depending on attenuation model, as some will fade out more aggressively than others.
+			// Multipliers were empirically determined through testing.
+			float soft_multiplier;
+			switch (player->get_attenuation_model()) {
+				case AudioStreamPlayer3D::ATTENUATION_INVERSE_DISTANCE:
+					soft_multiplier = 12.0;
+					break;
+				case AudioStreamPlayer3D::ATTENUATION_INVERSE_SQUARE_DISTANCE:
+					soft_multiplier = 4.0;
+					break;
+				case AudioStreamPlayer3D::ATTENUATION_LOGARITHMIC:
+					soft_multiplier = 3.25;
+					break;
+				default:
+					// Ensures Max Distance's radius visualization is not capped by Unit Size
+					// (when the attenuation mode is Disabled).
+					soft_multiplier = 10000.0;
+					break;
+			}
+
+			// Draw the distance at which the sound can be reasonably heard.
+			// This can be either a hard distance cap with the Max Distance property (if set above 0.0),
+			// or a soft distance cap with the Unit Size property (sound never reaches true zero).
+			// When Max Distance is 0.0, `r` represents the distance above which the
+			// sound can't be heard in *most* (but not all) scenarios.
+			float r;
+			if (player->get_max_distance() > CMP_EPSILON) {
+				r = MIN(player->get_unit_size() * soft_multiplier, player->get_max_distance());
+			} else {
+				r = player->get_unit_size() * soft_multiplier;
+			}
+			Vector<Vector3> points_billboard;
+
+			for (int i = 0; i < 120; i++) {
+				// Create a circle.
+				const float ra = Math::deg_to_rad((float)(i * 3));
+				const float rb = Math::deg_to_rad((float)((i + 1) * 3));
+				const Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * r;
+				const Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * r;
+
+				// Draw a billboarded circle.
+				points_billboard.push_back(Vector3(a.x, a.y, 0));
+				points_billboard.push_back(Vector3(b.x, b.y, 0));
+			}
+
+			Color color;
+			switch (player->get_attenuation_model()) {
+				// Pick cold colors for all attenuation models (except Disabled),
+				// so that soft caps can be easily distinguished from hard caps
+				// (which use warm colors).
+				case AudioStreamPlayer3D::ATTENUATION_INVERSE_DISTANCE:
+					color = Color(0.4, 0.8, 1);
+					break;
+				case AudioStreamPlayer3D::ATTENUATION_INVERSE_SQUARE_DISTANCE:
+					color = Color(0.4, 0.5, 1);
+					break;
+				case AudioStreamPlayer3D::ATTENUATION_LOGARITHMIC:
+					color = Color(0.4, 0.2, 1);
+					break;
+				default:
+					// Disabled attenuation mode.
+					// This is never reached when Max Distance is 0, but the
+					// hue-inverted form of this color will be used if Max Distance is greater than 0.
+					color = Color(1, 1, 1);
+					break;
+			}
+
+			if (player->get_max_distance() > CMP_EPSILON) {
+				// Sound is hard-capped by max distance. The attenuation model still matters,
+				// so invert the hue of the color that was chosen above.
+				color.set_h(color.get_h() + 0.5);
+			}
+
+			p_gizmo->add_lines(points_billboard, lines_billboard_material, true, color);
 		}
 
-		if (player->get_max_distance() > CMP_EPSILON) {
-			// Sound is hard-capped by max distance. The attenuation model still matters,
-			// so invert the hue of the color that was chosen above.
-			color.set_h(color.get_h() + 0.5);
-		}
+		if (player->is_emission_angle_enabled()) {
+			const float pc = player->get_emission_angle();
+			const float ofs = -Math::cos(Math::deg_to_rad(pc));
+			const float radius = Math::sin(Math::deg_to_rad(pc));
 
-		p_gizmo->add_lines(points_billboard, lines_billboard_material, true, color);
-	}
+			Vector<Vector3> points_primary;
+			points_primary.resize(200);
 
-	if (player->is_emission_angle_enabled()) {
-		const float pc = player->get_emission_angle();
-		const float ofs = -Math::cos(Math::deg_to_rad(pc));
-		const float radius = Math::sin(Math::deg_to_rad(pc));
+			real_t step = Math_TAU / 100.0;
+			for (int i = 0; i < 100; i++) {
+				const float a = i * step;
+				const float an = (i + 1) * step;
 
-		Vector<Vector3> points_primary;
-		points_primary.resize(200);
+				const Vector3 from(Math::sin(a) * radius, Math::cos(a) * radius, ofs);
+				const Vector3 to(Math::sin(an) * radius, Math::cos(an) * radius, ofs);
 
-		real_t step = Math_TAU / 100.0;
-		for (int i = 0; i < 100; i++) {
-			const float a = i * step;
-			const float an = (i + 1) * step;
+				points_primary.write[i * 2 + 0] = from;
+				points_primary.write[i * 2 + 1] = to;
+			}
 
-			const Vector3 from(Math::sin(a) * radius, Math::cos(a) * radius, ofs);
-			const Vector3 to(Math::sin(an) * radius, Math::cos(an) * radius, ofs);
+			const Ref<Material> material_primary = get_material("stream_player_3d_material_primary", p_gizmo);
+			p_gizmo->add_lines(points_primary, material_primary);
 
-			points_primary.write[i * 2 + 0] = from;
-			points_primary.write[i * 2 + 1] = to;
-		}
+			Vector<Vector3> points_secondary;
+			points_secondary.resize(16);
 
-		const Ref<Material> material_primary = get_material("stream_player_3d_material_primary", p_gizmo);
-		p_gizmo->add_lines(points_primary, material_primary);
+			for (int i = 0; i < 8; i++) {
+				const float a = i * (Math_TAU / 8.0);
+				const Vector3 from(Math::sin(a) * radius, Math::cos(a) * radius, ofs);
 
-		Vector<Vector3> points_secondary;
-		points_secondary.resize(16);
+				points_secondary.write[i * 2 + 0] = from;
+				points_secondary.write[i * 2 + 1] = Vector3();
+			}
 
-		for (int i = 0; i < 8; i++) {
-			const float a = i * (Math_TAU / 8.0);
-			const Vector3 from(Math::sin(a) * radius, Math::cos(a) * radius, ofs);
+			const Ref<Material> material_secondary = get_material("stream_player_3d_material_secondary", p_gizmo);
+			p_gizmo->add_lines(points_secondary, material_secondary);
 
-			points_secondary.write[i * 2 + 0] = from;
-			points_secondary.write[i * 2 + 1] = Vector3();
+			Vector<Vector3> handles;
+			const float ha = Math::deg_to_rad(player->get_emission_angle());
+			handles.push_back(Vector3(Math::sin(ha), 0, -Math::cos(ha)));
+			p_gizmo->add_handles(handles, get_material("handles"));
 		}
-
-		const Ref<Material> material_secondary = get_material("stream_player_3d_material_secondary", p_gizmo);
-		p_gizmo->add_lines(points_secondary, material_secondary);
-
-		Vector<Vector3> handles;
-		const float ha = Math::deg_to_rad(player->get_emission_angle());
-		handles.push_back(Vector3(Math::sin(ha), 0, -Math::cos(ha)));
-		p_gizmo->add_handles(handles, get_material("handles"));
 	}
 
+	const Ref<Material> icon = get_material("stream_player_3d_icon", p_gizmo);
 	p_gizmo->add_unscaled_billboard(icon, 0.05);
 }

+ 32 - 31
editor/plugins/gizmos/gpu_particles_3d_gizmo_plugin.cpp

@@ -151,49 +151,50 @@ void GPUParticles3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo,
 }
 
 void GPUParticles3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
-	GPUParticles3D *particles = Object::cast_to<GPUParticles3D>(p_gizmo->get_node_3d());
-
 	p_gizmo->clear();
 
-	Vector<Vector3> lines;
-	AABB aabb = particles->get_visibility_aabb();
+	if (p_gizmo->is_selected()) {
+		GPUParticles3D *particles = Object::cast_to<GPUParticles3D>(p_gizmo->get_node_3d());
 
-	for (int i = 0; i < 12; i++) {
-		Vector3 a, b;
-		aabb.get_edge(i, a, b);
-		lines.push_back(a);
-		lines.push_back(b);
-	}
+		Vector<Vector3> lines;
+		AABB aabb = particles->get_visibility_aabb();
 
-	Vector<Vector3> handles;
+		for (int i = 0; i < 12; i++) {
+			Vector3 a, b;
+			aabb.get_edge(i, a, b);
+			lines.push_back(a);
+			lines.push_back(b);
+		}
 
-	for (int i = 0; i < 3; i++) {
-		Vector3 ax;
-		ax[i] = aabb.position[i] + aabb.size[i];
-		ax[(i + 1) % 3] = aabb.position[(i + 1) % 3] + aabb.size[(i + 1) % 3] * 0.5;
-		ax[(i + 2) % 3] = aabb.position[(i + 2) % 3] + aabb.size[(i + 2) % 3] * 0.5;
-		handles.push_back(ax);
-	}
+		Vector<Vector3> handles;
 
-	Vector3 center = aabb.get_center();
-	for (int i = 0; i < 3; i++) {
-		Vector3 ax;
-		ax[i] = 1.0;
-		handles.push_back(center + ax);
-		lines.push_back(center);
-		lines.push_back(center + ax);
-	}
+		for (int i = 0; i < 3; i++) {
+			Vector3 ax;
+			ax[i] = aabb.position[i] + aabb.size[i];
+			ax[(i + 1) % 3] = aabb.position[(i + 1) % 3] + aabb.size[(i + 1) % 3] * 0.5;
+			ax[(i + 2) % 3] = aabb.position[(i + 2) % 3] + aabb.size[(i + 2) % 3] * 0.5;
+			handles.push_back(ax);
+		}
 
-	Ref<Material> material = get_material("particles_material", p_gizmo);
-	Ref<Material> icon = get_material("particles_icon", p_gizmo);
+		Vector3 center = aabb.get_center();
+		for (int i = 0; i < 3; i++) {
+			Vector3 ax;
+			ax[i] = 1.0;
+			handles.push_back(center + ax);
+			lines.push_back(center);
+			lines.push_back(center + ax);
+		}
 
-	p_gizmo->add_lines(lines, material);
+		Ref<Material> material = get_material("particles_material", p_gizmo);
+
+		p_gizmo->add_lines(lines, material);
 
-	if (p_gizmo->is_selected()) {
 		Ref<Material> solid_material = get_material("particles_solid_material", p_gizmo);
 		p_gizmo->add_solid_box(solid_material, aabb.get_size(), aabb.get_center());
+
+		p_gizmo->add_handles(handles, get_material("handles"));
 	}
 
-	p_gizmo->add_handles(handles, get_material("handles"));
+	Ref<Material> icon = get_material("particles_icon", p_gizmo);
 	p_gizmo->add_unscaled_billboard(icon, 0.05);
 }

+ 100 - 91
editor/plugins/gizmos/light_3d_gizmo_plugin.cpp

@@ -158,124 +158,133 @@ void Light3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
 	p_gizmo->clear();
 
 	if (Object::cast_to<DirectionalLight3D>(light)) {
-		Ref<Material> material = get_material("lines_primary", p_gizmo);
-		Ref<Material> icon = get_material("light_directional_icon", p_gizmo);
+		if (p_gizmo->is_selected()) {
+			Ref<Material> material = get_material("lines_primary", p_gizmo);
 
-		const int arrow_points = 7;
-		const float arrow_length = 1.5;
+			const int arrow_points = 7;
+			const float arrow_length = 1.5;
 
-		Vector3 arrow[arrow_points] = {
-			Vector3(0, 0, -1),
-			Vector3(0, 0.8, 0),
-			Vector3(0, 0.3, 0),
-			Vector3(0, 0.3, arrow_length),
-			Vector3(0, -0.3, arrow_length),
-			Vector3(0, -0.3, 0),
-			Vector3(0, -0.8, 0)
-		};
+			Vector3 arrow[arrow_points] = {
+				Vector3(0, 0, -1),
+				Vector3(0, 0.8, 0),
+				Vector3(0, 0.3, 0),
+				Vector3(0, 0.3, arrow_length),
+				Vector3(0, -0.3, arrow_length),
+				Vector3(0, -0.3, 0),
+				Vector3(0, -0.8, 0)
+			};
 
-		int arrow_sides = 2;
+			int arrow_sides = 2;
 
-		Vector<Vector3> lines;
+			Vector<Vector3> lines;
 
-		for (int i = 0; i < arrow_sides; i++) {
-			for (int j = 0; j < arrow_points; j++) {
-				Basis ma(Vector3(0, 0, 1), Math_PI * i / arrow_sides);
+			for (int i = 0; i < arrow_sides; i++) {
+				for (int j = 0; j < arrow_points; j++) {
+					Basis ma(Vector3(0, 0, 1), Math_PI * i / arrow_sides);
 
-				Vector3 v1 = arrow[j] - Vector3(0, 0, arrow_length);
-				Vector3 v2 = arrow[(j + 1) % arrow_points] - Vector3(0, 0, arrow_length);
+					Vector3 v1 = arrow[j] - Vector3(0, 0, arrow_length);
+					Vector3 v2 = arrow[(j + 1) % arrow_points] - Vector3(0, 0, arrow_length);
 
-				lines.push_back(ma.xform(v1));
-				lines.push_back(ma.xform(v2));
+					lines.push_back(ma.xform(v1));
+					lines.push_back(ma.xform(v2));
+				}
 			}
+
+			p_gizmo->add_lines(lines, material, false, color);
 		}
 
-		p_gizmo->add_lines(lines, material, false, color);
+		Ref<Material> icon = get_material("light_directional_icon", p_gizmo);
 		p_gizmo->add_unscaled_billboard(icon, 0.05, color);
 	}
 
 	if (Object::cast_to<OmniLight3D>(light)) {
-		// Use both a billboard circle and 3 non-billboard circles for a better sphere-like representation
-		const Ref<Material> lines_material = get_material("lines_secondary", p_gizmo);
-		const Ref<Material> lines_billboard_material = get_material("lines_billboard", p_gizmo);
-		const Ref<Material> icon = get_material("light_omni_icon", p_gizmo);
+		if (p_gizmo->is_selected()) {
+			// Use both a billboard circle and 3 non-billboard circles for a better sphere-like representation
+			const Ref<Material> lines_material = get_material("lines_secondary", p_gizmo);
+			const Ref<Material> lines_billboard_material = get_material("lines_billboard", p_gizmo);
+
+			OmniLight3D *on = Object::cast_to<OmniLight3D>(light);
+			const float r = on->get_param(Light3D::PARAM_RANGE);
+			Vector<Vector3> points;
+			Vector<Vector3> points_billboard;
+
+			for (int i = 0; i < 120; i++) {
+				// Create a circle
+				const float ra = Math::deg_to_rad((float)(i * 3));
+				const float rb = Math::deg_to_rad((float)((i + 1) * 3));
+				const Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * r;
+				const Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * r;
+
+				// Draw axis-aligned circles
+				points.push_back(Vector3(a.x, 0, a.y));
+				points.push_back(Vector3(b.x, 0, b.y));
+				points.push_back(Vector3(0, a.x, a.y));
+				points.push_back(Vector3(0, b.x, b.y));
+				points.push_back(Vector3(a.x, a.y, 0));
+				points.push_back(Vector3(b.x, b.y, 0));
+
+				// Draw a billboarded circle
+				points_billboard.push_back(Vector3(a.x, a.y, 0));
+				points_billboard.push_back(Vector3(b.x, b.y, 0));
+			}
+
+			p_gizmo->add_lines(points, lines_material, true, color);
+			p_gizmo->add_lines(points_billboard, lines_billboard_material, true, color);
 
-		OmniLight3D *on = Object::cast_to<OmniLight3D>(light);
-		const float r = on->get_param(Light3D::PARAM_RANGE);
-		Vector<Vector3> points;
-		Vector<Vector3> points_billboard;
-
-		for (int i = 0; i < 120; i++) {
-			// Create a circle
-			const float ra = Math::deg_to_rad((float)(i * 3));
-			const float rb = Math::deg_to_rad((float)((i + 1) * 3));
-			const Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * r;
-			const Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * r;
-
-			// Draw axis-aligned circles
-			points.push_back(Vector3(a.x, 0, a.y));
-			points.push_back(Vector3(b.x, 0, b.y));
-			points.push_back(Vector3(0, a.x, a.y));
-			points.push_back(Vector3(0, b.x, b.y));
-			points.push_back(Vector3(a.x, a.y, 0));
-			points.push_back(Vector3(b.x, b.y, 0));
-
-			// Draw a billboarded circle
-			points_billboard.push_back(Vector3(a.x, a.y, 0));
-			points_billboard.push_back(Vector3(b.x, b.y, 0));
+			Vector<Vector3> handles;
+			handles.push_back(Vector3(r, 0, 0));
+			p_gizmo->add_handles(handles, get_material("handles_billboard"), Vector<int>(), true);
 		}
 
-		p_gizmo->add_lines(points, lines_material, true, color);
-		p_gizmo->add_lines(points_billboard, lines_billboard_material, true, color);
+		const Ref<Material> icon = get_material("light_omni_icon", p_gizmo);
 		p_gizmo->add_unscaled_billboard(icon, 0.05, color);
-
-		Vector<Vector3> handles;
-		handles.push_back(Vector3(r, 0, 0));
-		p_gizmo->add_handles(handles, get_material("handles_billboard"), Vector<int>(), true);
 	}
 
 	if (Object::cast_to<SpotLight3D>(light)) {
-		const Ref<Material> material_primary = get_material("lines_primary", p_gizmo);
-		const Ref<Material> material_secondary = get_material("lines_secondary", p_gizmo);
-		const Ref<Material> icon = get_material("light_spot_icon", p_gizmo);
-
-		Vector<Vector3> points_primary;
-		Vector<Vector3> points_secondary;
-		SpotLight3D *sl = Object::cast_to<SpotLight3D>(light);
+		if (p_gizmo->is_selected()) {
+			const Ref<Material> material_primary = get_material("lines_primary", p_gizmo);
+			const Ref<Material> material_secondary = get_material("lines_secondary", p_gizmo);
+
+			Vector<Vector3> points_primary;
+			Vector<Vector3> points_secondary;
+			SpotLight3D *sl = Object::cast_to<SpotLight3D>(light);
+
+			float r = sl->get_param(Light3D::PARAM_RANGE);
+			float w = r * Math::sin(Math::deg_to_rad(sl->get_param(Light3D::PARAM_SPOT_ANGLE)));
+			float d = r * Math::cos(Math::deg_to_rad(sl->get_param(Light3D::PARAM_SPOT_ANGLE)));
+
+			for (int i = 0; i < 120; i++) {
+				// Draw a circle
+				const float ra = Math::deg_to_rad((float)(i * 3));
+				const float rb = Math::deg_to_rad((float)((i + 1) * 3));
+				const Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * w;
+				const Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * w;
+
+				points_primary.push_back(Vector3(a.x, a.y, -d));
+				points_primary.push_back(Vector3(b.x, b.y, -d));
+
+				if (i % 15 == 0) {
+					// Draw 8 lines from the cone origin to the sides of the circle
+					points_secondary.push_back(Vector3(a.x, a.y, -d));
+					points_secondary.push_back(Vector3());
+				}
+			}
 
-		float r = sl->get_param(Light3D::PARAM_RANGE);
-		float w = r * Math::sin(Math::deg_to_rad(sl->get_param(Light3D::PARAM_SPOT_ANGLE)));
-		float d = r * Math::cos(Math::deg_to_rad(sl->get_param(Light3D::PARAM_SPOT_ANGLE)));
+			points_primary.push_back(Vector3(0, 0, -r));
+			points_primary.push_back(Vector3());
 
-		for (int i = 0; i < 120; i++) {
-			// Draw a circle
-			const float ra = Math::deg_to_rad((float)(i * 3));
-			const float rb = Math::deg_to_rad((float)((i + 1) * 3));
-			const Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * w;
-			const Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * w;
+			p_gizmo->add_lines(points_primary, material_primary, false, color);
+			p_gizmo->add_lines(points_secondary, material_secondary, false, color);
 
-			points_primary.push_back(Vector3(a.x, a.y, -d));
-			points_primary.push_back(Vector3(b.x, b.y, -d));
+			Vector<Vector3> handles = {
+				Vector3(0, 0, -r),
+				Vector3(w, 0, -d)
+			};
 
-			if (i % 15 == 0) {
-				// Draw 8 lines from the cone origin to the sides of the circle
-				points_secondary.push_back(Vector3(a.x, a.y, -d));
-				points_secondary.push_back(Vector3());
-			}
+			p_gizmo->add_handles(handles, get_material("handles"));
 		}
 
-		points_primary.push_back(Vector3(0, 0, -r));
-		points_primary.push_back(Vector3());
-
-		p_gizmo->add_lines(points_primary, material_primary, false, color);
-		p_gizmo->add_lines(points_secondary, material_secondary, false, color);
-
-		Vector<Vector3> handles = {
-			Vector3(0, 0, -r),
-			Vector3(w, 0, -d)
-		};
-
-		p_gizmo->add_handles(handles, get_material("handles"));
+		const Ref<Material> icon = get_material("light_spot_icon", p_gizmo);
 		p_gizmo->add_unscaled_billboard(icon, 0.05, color);
 	}
 }

+ 3 - 3
editor/plugins/gizmos/lightmap_gi_gizmo_plugin.cpp

@@ -68,17 +68,17 @@ void LightmapGIGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
 	LightmapGI *baker = Object::cast_to<LightmapGI>(p_gizmo->get_node_3d());
 	Ref<LightmapGIData> data = baker->get_light_data();
 
+	p_gizmo->clear();
+
 	p_gizmo->add_unscaled_billboard(icon, 0.05);
 
-	if (data.is_null()) {
+	if (data.is_null() || !p_gizmo->is_selected()) {
 		return;
 	}
 
 	Ref<Material> material_lines = get_material("lightmap_lines", p_gizmo);
 	Ref<Material> material_probes = get_material("lightmap_probe_material", p_gizmo);
 
-	p_gizmo->clear();
-
 	Vector<Vector3> lines;
 	HashSet<Vector2i> lines_found;
 

+ 39 - 37
editor/plugins/gizmos/reflection_probe_gizmo_plugin.cpp

@@ -151,55 +151,57 @@ void ReflectionProbeGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo,
 }
 
 void ReflectionProbeGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
-	ReflectionProbe *probe = Object::cast_to<ReflectionProbe>(p_gizmo->get_node_3d());
-
 	p_gizmo->clear();
 
-	Vector<Vector3> lines;
-	Vector<Vector3> internal_lines;
-	Vector3 size = probe->get_size();
+	if (p_gizmo->is_selected()) {
+		ReflectionProbe *probe = Object::cast_to<ReflectionProbe>(p_gizmo->get_node_3d());
+		Vector<Vector3> lines;
+		Vector<Vector3> internal_lines;
+		Vector3 size = probe->get_size();
 
-	AABB aabb;
-	aabb.position = -size / 2;
-	aabb.size = size;
+		AABB aabb;
+		aabb.position = -size / 2;
+		aabb.size = size;
 
-	for (int i = 0; i < 12; i++) {
-		Vector3 a, b;
-		aabb.get_edge(i, a, b);
-		lines.push_back(a);
-		lines.push_back(b);
-	}
+		for (int i = 0; i < 12; i++) {
+			Vector3 a, b;
+			aabb.get_edge(i, a, b);
+			lines.push_back(a);
+			lines.push_back(b);
+		}
 
-	for (int i = 0; i < 8; i++) {
-		Vector3 ep = aabb.get_endpoint(i);
-		internal_lines.push_back(probe->get_origin_offset());
-		internal_lines.push_back(ep);
-	}
+		for (int i = 0; i < 8; i++) {
+			Vector3 ep = aabb.get_endpoint(i);
+			internal_lines.push_back(probe->get_origin_offset());
+			internal_lines.push_back(ep);
+		}
 
-	Vector<Vector3> handles = helper->box_get_handles(probe->get_size());
+		Vector<Vector3> handles = helper->box_get_handles(probe->get_size());
 
-	for (int i = 0; i < 3; i++) {
-		Vector3 orig_handle = probe->get_origin_offset();
-		orig_handle[i] -= 0.25;
-		lines.push_back(orig_handle);
-		handles.push_back(orig_handle);
+		for (int i = 0; i < 3; i++) {
+			Vector3 orig_handle = probe->get_origin_offset();
+			orig_handle[i] -= 0.25;
+			lines.push_back(orig_handle);
+			handles.push_back(orig_handle);
 
-		orig_handle[i] += 0.5;
-		lines.push_back(orig_handle);
-	}
+			orig_handle[i] += 0.5;
+			lines.push_back(orig_handle);
+		}
 
-	Ref<Material> material = get_material("reflection_probe_material", p_gizmo);
-	Ref<Material> material_internal = get_material("reflection_internal_material", p_gizmo);
-	Ref<Material> icon = get_material("reflection_probe_icon", p_gizmo);
+		Ref<Material> material = get_material("reflection_probe_material", p_gizmo);
+		Ref<Material> material_internal = get_material("reflection_internal_material", p_gizmo);
 
-	p_gizmo->add_lines(lines, material);
-	p_gizmo->add_lines(internal_lines, material_internal);
+		p_gizmo->add_lines(lines, material);
+		p_gizmo->add_lines(internal_lines, material_internal);
 
-	if (p_gizmo->is_selected()) {
-		Ref<Material> solid_material = get_material("reflection_probe_solid_material", p_gizmo);
-		p_gizmo->add_solid_box(solid_material, probe->get_size());
+		if (p_gizmo->is_selected()) {
+			Ref<Material> solid_material = get_material("reflection_probe_solid_material", p_gizmo);
+			p_gizmo->add_solid_box(solid_material, probe->get_size());
+		}
+
+		p_gizmo->add_handles(handles, get_material("handles"));
 	}
 
+	Ref<Material> icon = get_material("reflection_probe_icon", p_gizmo);
 	p_gizmo->add_unscaled_billboard(icon, 0.05);
-	p_gizmo->add_handles(handles, get_material("handles"));
 }

+ 50 - 48
editor/plugins/gizmos/voxel_gi_gizmo_plugin.cpp

@@ -100,74 +100,76 @@ void VoxelGIGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_i
 }
 
 void VoxelGIGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
-	VoxelGI *probe = Object::cast_to<VoxelGI>(p_gizmo->get_node_3d());
+	p_gizmo->clear();
 
-	Ref<Material> material = get_material("voxel_gi_material", p_gizmo);
-	Ref<Material> icon = get_material("voxel_gi_icon", p_gizmo);
-	Ref<Material> material_internal = get_material("voxel_gi_internal_material", p_gizmo);
+	if (p_gizmo->is_selected()) {
+		VoxelGI *probe = Object::cast_to<VoxelGI>(p_gizmo->get_node_3d());
+		Ref<Material> material = get_material("voxel_gi_material", p_gizmo);
+		Ref<Material> material_internal = get_material("voxel_gi_internal_material", p_gizmo);
 
-	p_gizmo->clear();
+		Vector<Vector3> lines;
+		Vector3 size = probe->get_size();
 
-	Vector<Vector3> lines;
-	Vector3 size = probe->get_size();
+		static const int subdivs[VoxelGI::SUBDIV_MAX] = { 64, 128, 256, 512 };
 
-	static const int subdivs[VoxelGI::SUBDIV_MAX] = { 64, 128, 256, 512 };
+		AABB aabb = AABB(-size / 2, size);
+		int subdiv = subdivs[probe->get_subdiv()];
+		float cell_size = aabb.get_longest_axis_size() / subdiv;
 
-	AABB aabb = AABB(-size / 2, size);
-	int subdiv = subdivs[probe->get_subdiv()];
-	float cell_size = aabb.get_longest_axis_size() / subdiv;
+		for (int i = 0; i < 12; i++) {
+			Vector3 a, b;
+			aabb.get_edge(i, a, b);
+			lines.push_back(a);
+			lines.push_back(b);
+		}
 
-	for (int i = 0; i < 12; i++) {
-		Vector3 a, b;
-		aabb.get_edge(i, a, b);
-		lines.push_back(a);
-		lines.push_back(b);
-	}
+		p_gizmo->add_lines(lines, material);
 
-	p_gizmo->add_lines(lines, material);
+		lines.clear();
 
-	lines.clear();
+		for (int i = 1; i < subdiv; i++) {
+			for (int j = 0; j < 3; j++) {
+				if (cell_size * i > aabb.size[j]) {
+					continue;
+				}
 
-	for (int i = 1; i < subdiv; i++) {
-		for (int j = 0; j < 3; j++) {
-			if (cell_size * i > aabb.size[j]) {
-				continue;
-			}
+				int j_n1 = (j + 1) % 3;
+				int j_n2 = (j + 2) % 3;
 
-			int j_n1 = (j + 1) % 3;
-			int j_n2 = (j + 2) % 3;
+				for (int k = 0; k < 4; k++) {
+					Vector3 from = aabb.position, to = aabb.position;
+					from[j] += cell_size * i;
+					to[j] += cell_size * i;
 
-			for (int k = 0; k < 4; k++) {
-				Vector3 from = aabb.position, to = aabb.position;
-				from[j] += cell_size * i;
-				to[j] += cell_size * i;
+					if (k & 1) {
+						to[j_n1] += aabb.size[j_n1];
+					} else {
+						to[j_n2] += aabb.size[j_n2];
+					}
 
-				if (k & 1) {
-					to[j_n1] += aabb.size[j_n1];
-				} else {
-					to[j_n2] += aabb.size[j_n2];
-				}
+					if (k & 2) {
+						from[j_n1] += aabb.size[j_n1];
+						from[j_n2] += aabb.size[j_n2];
+					}
 
-				if (k & 2) {
-					from[j_n1] += aabb.size[j_n1];
-					from[j_n2] += aabb.size[j_n2];
+					lines.push_back(from);
+					lines.push_back(to);
 				}
-
-				lines.push_back(from);
-				lines.push_back(to);
 			}
 		}
-	}
 
-	p_gizmo->add_lines(lines, material_internal);
+		p_gizmo->add_lines(lines, material_internal);
 
-	Vector<Vector3> handles = helper->box_get_handles(probe->get_size());
+		Vector<Vector3> handles = helper->box_get_handles(probe->get_size());
 
-	if (p_gizmo->is_selected()) {
-		Ref<Material> solid_material = get_material("voxel_gi_solid_material", p_gizmo);
-		p_gizmo->add_solid_box(solid_material, aabb.get_size());
+		if (p_gizmo->is_selected()) {
+			Ref<Material> solid_material = get_material("voxel_gi_solid_material", p_gizmo);
+			p_gizmo->add_solid_box(solid_material, aabb.get_size());
+		}
+
+		p_gizmo->add_handles(handles, get_material("handles"));
 	}
 
+	Ref<Material> icon = get_material("voxel_gi_icon", p_gizmo);
 	p_gizmo->add_unscaled_billboard(icon, 0.05);
-	p_gizmo->add_handles(handles, get_material("handles"));
 }