Did you forget to add the details? Also no need to clutter up the feed by closing a question just update it
Seems there might be a bug or I missed something. Could post before without problem
Your post is empty, it just says “Godot Version” and “Question”, did you put something else in?
Im writing feedback in Reply cause of a posting bug:
edit: Adding some additional comments
My question: In my script, the shader is never loaded while is_selected is set to true!
extends Node3D
var outline_material: ShaderMaterial = load("res://shaders/OutlineShader.tres")
func _ready():
print("OutlineApplier ready")
# Connect to the selection_changed signals emitted by child nodes
for child in get_children():
if child.has_method("connect_selection_signal"):
child.connect_selection_signal(Callable(self, "_on_selection_changed"))
# Called when the selection changes
func _on_selection_changed(node, is_selected: bool):
if is_selected:
print(node.name + " selected")
apply_outline_shader(node)
else:
print(node.name + " deselected")
remove_outline_shader(node)
func apply_outline_shader(node):
print("Applying outline shader to ", node.name)
# Apply the outline shader to the node itself if it's a MeshInstance or StaticBody3D
if node.is_class("MeshInstance") or node.is_class("StaticBody3D"):
var material = node.get_surface_material(0)
# Check if the node already has a material applied
if not material:
# If no material is applied, apply the outline shader material
node.set_surface_material(0, outline_material.instance())
else:
# Apply the outline shader to all MeshInstance children of the node
for child in node.get_children():
if child.is_class("MeshInstance"):
var material = child.get_surface_material(0)
# Check if the child already has a material applied
if not material:
# If no material is applied, apply the outline shader material
child.set_surface_material(0, outline_material.instance())
func remove_outline_shader(node):
print("Removing outline shader from ", node.name)
# Remove the outline shader from all MeshInstance children of the node
for child in node.get_children():
if child.is_class("MeshInstance"):
if child.get_surface_material(0) == outline_material:
child.set_surface_material(0, null)
I just wrote a functioning reply to myself. Give it a try
So now Ive chose to go with material override instead. This works by changing the materials when units are selected. But the my shader overrides everything, so the objects are simply seen as outlines… Anyone got a clue?
extends Node3D
var outline_material: ShaderMaterial = load("res://shaders/OutlineShader.tres")
func _ready():
print("OutlineApplier ready")
# Connect to the selection_changed signals emitted by child nodes
for child in get_children():
if child.has_method("connect_selection_signal"):
child.connect_selection_signal(Callable(self, "_on_selection_changed"))
# Called when the selection changes
func _on_selection_changed(node, is_selected: bool):
if is_selected:
print(node.name + " selected")
apply_outline_shader(node)
else:
print(node.name + " deselected")
remove_outline_shader(node)
func apply_outline_shader(node):
print("Applying outline shader to ", node.name)
# Check if the node is a MeshInstance
if node.is_class("MeshInstance3D"):
# Apply the outline shader material override if it's not already set
if not node.material_override:
node.material_override = outline_material
else:
# Iterate over all children and apply the outline shader recursively
for child in node.get_children():
apply_outline_shader(child)
func remove_outline_shader(node):
print("Removing outline shader from ", node.name)
# Remove the outline shader override from all MeshInstance children of the node
for child in node.get_children():
if child.is_class("MeshInstance3D"):
if child.material_override == outline_material:
child.material_override = null
else:
# Recursively remove the outline shader override from child nodes
remove_outline_shader(child)
shader_type spatial;
render_mode unshaded, cull_front;
uniform float outline_thickness : hint_range(0.0, 0.2) = 0.1;
uniform vec4 outline_color : source_color = vec4(1.0, 1.0, 0.0, 1.0); // Yellow by default
uniform sampler2D texture_albedo : hint_screen_texture; // Texture uniform
void vertex() {
VERTEX += NORMAL * outline_thickness;
}
void fragment() {
ALBEDO = outline_color.rgb;
}
So I finnaly found my solution. Feel free to use for selected outlines!
extends Node3D
var outline_material: ShaderMaterial = preload("res://shaders/OutlineShader.tres")
func _ready():
print("OutlineApplier ready")
# Connect to the selection_changed signals emitted by child nodes
for child in get_children():
if child.has_method("connect_selection_signal"):
child.connect_selection_signal(Callable(self, "_on_selection_changed"))
# Called when the selection changes
func _on_selection_changed(node, is_selected: bool):
if is_selected:
print(node.name + " selected")
apply_outline_shader(node)
else:
print(node.name + " deselected")
remove_outline_shader(node)
func apply_outline_shader(node):
print("Applying outline shader to ", node.name)
# Check if the node is a MeshInstance
if node.is_class("MeshInstance3D"):
# Apply the outline shader material override if it's not already set
if not node.get_surface_override_material(0):
var original_material = node.mesh.surface_get_material(0)
if original_material:
# Create a new material that uses the outline as a next pass
var material_with_outline = original_material.duplicate()
material_with_outline.next_pass = outline_material
node.set_surface_override_material(0, material_with_outline)
else:
# Iterate over all children and apply the outline shader recursively
for child in node.get_children():
apply_outline_shader(child)
func remove_outline_shader(node):
print("Removing outline shader from ", node.name)
# Check if the node is a MeshInstance
if node.is_class("MeshInstance3D"):
# Remove the outline shader override if it's set to the outline material
if node.get_surface_override_material(0) and node.get_surface_override_material(0).next_pass == outline_material:
node.set_surface_override_material(0, null)
else:
# Iterate over all children and remove the outline shader override recursively
for child in node.get_children():
remove_outline_shader(child)
shader_type spatial;
render_mode unshaded, cull_front;
uniform float outline_thickness : hint_range(0.0, 0.2) = 0.1;
uniform vec4 outline_color : source_color = vec4(0.0, 0.0, 1.0, 1.0); // Blue outline color
void vertex() {
VERTEX += NORMAL * outline_thickness;
}
void fragment() {
ALBEDO = outline_color.rgb;
}
If anyone wonders it seems like there was no bug at godot forums, only me forgetting to remove the arrow signs before version and question! LOL
This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.