Godot 3 to 4 rename

VisualShaderNodeScalarSwitch in Godot 4: it is VisualShaderNodeSwitch now

VisualShaderNodeScalarSwitch is VisualShaderNodeSwitch in Godot 4.7.2: one switch node, whose op_type picks float, int, uint, a 2D, 3D or 4D vector, a boolean or a transform. Set to floats, Godot generated no branch for it: the choice became a mix() with the condition as a float.

What Godot prints

A Godot 3 script that builds a float switch node for a visual shader in code.

repro.gd
extends Node

func _ready():
	var shader = VisualShader.new()
	var pick = VisualShaderNodeScalarSwitch.new()
	shader.add_node(VisualShader.TYPE_FRAGMENT, pick, Vector2(0, 0), 2)
	print(shader.get_code())
Output, Godot 4.7.2
Godot Engine v4.7.2.stable.mono.official.ed1daf0bf - https://godotengine.org

SCRIPT ERROR: Parse Error: Identifier "VisualShaderNodeScalarSwitch" not declared in the current scope. Did you mean to use "VisualShaderNodeSwitch"?
   at: GDScript::reload (res://answers/visualshadernodescalarswitch-in-godot-4/repro.gd:5)
ERROR: Failed to load script "res://answers/visualshadernodescalarswitch-in-godot-4/repro.gd" with error "Parse error".
   at: load (modules/gdscript/gdscript_resource_format.cpp:46)

The fix

One VisualShaderNodeSwitch, set to floats with op_type, its condition taken from a boolean parameter and its result sent to the fragment output. The fix prints the lines of generated shader code that make the choice.

fix.gd
extends Node

func _ready() -> void:
	var shader := VisualShader.new()
	var lit := VisualShaderNodeBooleanParameter.new()
	lit.parameter_name = "lit"
	shader.add_node(VisualShader.TYPE_FRAGMENT, lit, Vector2(0, 0), 2)
	var pick := VisualShaderNodeSwitch.new()
	pick.op_type = VisualShaderNodeSwitch.OP_TYPE_FLOAT
	shader.add_node(VisualShader.TYPE_FRAGMENT, pick, Vector2(200, 0), 3)
	shader.connect_nodes(VisualShader.TYPE_FRAGMENT, 2, 0, 3, 0)
	shader.connect_nodes(VisualShader.TYPE_FRAGMENT, 3, 0, 0, 0)
	var code := shader.get_code()
	var start := code.find("// Switch:3")
	print(code.substr(start, code.find("\n\n", start) - start) if start >= 0 else code)
Output, Godot 4.7.2
Godot Engine v4.7.2.stable.mono.official.ed1daf0bf - https://godotengine.org

// Switch:3
	float n_in3p1 = 1.00000;
	float n_in3p2 = 0.00000;
	n_out3p0 = mix(n_in3p2, n_in3p1, float(n_out2p0));

Why it happens

GDScript's analyzer resolves every identifier when the script loads. VisualShaderNodeScalarSwitch is not a class in Godot 4.7.2, so the script fails to parse and Godot does not load it. The editor build adds the new name from Godot's 3 to 4 rename table: Did you mean to use "VisualShaderNodeSwitch"?

VisualShaderNodeSwitch returns one of two values of its op_type, depending on whether its boolean input is true or false. op_type is one of OP_TYPE_FLOAT, OP_TYPE_INT, OP_TYPE_UINT, OP_TYPE_VECTOR_2D, OP_TYPE_VECTOR_3D, OP_TYPE_VECTOR_4D, OP_TYPE_BOOLEAN and OP_TYPE_TRANSFORM.

In the code Godot generated, the two value inputs left unconnected kept their defaults, 1.0 for true and 0.0 for false, and the result is mix(false_value, true_value, float(condition)), with no if statement.

Sources

Run on Godot 4.7.2, .

Related