## A compile failure must be VISIBLE and ANSWERABLE, not silent.
##
## hyper-games #64 NEXT 4. Every early return in _recompile_glsl leaves
## cached_glsl_ empty; the terrain then meshes from the CPU wrapper, or from
## dc-terrain's BUILT-IN noise generator, and renders a plausible landscape that
## is not the graph's. This asserts each state reports itself.
extends SceneTree
var _fail := 0
func _ck(name: String, ok: bool, detail: String) -> void:
print(" %-34s %s %s" % [name, "PASS" if ok else "FAIL", detail])
if not ok: _fail += 1
func _init() -> void:
# A. no graph -- a legitimate state, recorded, not screamed about
var g0 := DCTerrainGeneratorProcNodes.new()
_ck("no graph: not compiled", not g0.has_compiled_shader(), "has_compiled_shader() false")
# "" here would be indistinguishable from "compiled cleanly" -- a fresh
# generator has never ATTEMPTED a compile, because _recompile_glsl only runs
# from set_graph()/_set(). That ambiguity is what this asserts is gone.
_ck("fresh: says never compiled",
g0.get_last_compile_error().begins_with("never compiled"),
'"%s"' % g0.get_last_compile_error())
# B. a graph that compiles
var good := ProcNodeGraph.new()
var n1 := good.add_node(GradientNoiseNode.new())
var e1 := good.add_node(ErosionNoiseNode.new())
good.connect_sockets(n1, 0, e1, 7)
good.connect_sockets(n1, 1, e1, 8)
var g1 := DCTerrainGeneratorProcNodes.new()
g1.set_graph(good)
_ck("good graph: compiled", g1.has_compiled_shader(), "has_compiled_shader() true")
_ck("good graph: no error", g1.get_last_compile_error() == "",
'"%s"' % g1.get_last_compile_error())
# C. a graph proc-nodes REFUSES to emit.
#
# ⛔ THIS USED VolumeToMesh AND WENT RED WHEN THAT NODE BECAME LEGITIMATE.
# proc-nodes made it gpu_transparent() -- it NAMES a density rather than
# failing to compute one -- so a graph containing it now compiles, and this
# case silently stopped testing refusal. proc-nodes' own glsl_golden_gate.gd
# had the identical dependency and was updated in the same commit; THIS gate
# was not, and nothing re-ran it, so it sat at 7/9.
#
# Join Geometry instead: a density function is a float of a position, there
# is no geometry in it to join, so this subject cannot be finished into
# legitimacy by anybody.
var bad := ProcNodeGraph.new()
var n2 := bad.add_node(GradientNoiseNode.new())
var e2 := bad.add_node(ErosionNoiseNode.new())
bad.connect_sockets(n2, 0, e2, 7)
bad.connect_sockets(n2, 1, e2, 8)
bad.add_node(JoinGeometryNode.new())
var g2 := DCTerrainGeneratorProcNodes.new()
g2.set_graph(bad)
_ck("refused graph: not compiled", not g2.has_compiled_shader(),
"has_compiled_shader() false")
_ck("refused graph: says REFUSED",
g2.get_last_compile_error().contains("REFUSED"),
'"%s"' % g2.get_last_compile_error())
# D. THE BUILT-IN SUBSTITUTION. A DCTerrainGenerator that does not override
# get_native_generator() returns null, and DCTerrain quietly swaps in its
# own noise generator -- which renders a plausible landscape, so the
# symptom is "the terrain is wrong somehow" and never points here.
var t := DCTerrain.new()
_ck("no generator: builtin, honestly", t.is_using_builtin_generator(),
"is_using_builtin_generator() true")
t.set_generator(g1)
_ck("real generator: not builtin", not t.is_using_builtin_generator(),
"is_using_builtin_generator() false")
var plain := DCTerrainGenerator.new()
t.set_generator(plain)
_ck("generator with no native: builtin", t.is_using_builtin_generator(),
"is_using_builtin_generator() true, and an error was pushed")
print("\n%d/%d passed" % [9 - _fail, 9])
quit(1 if _fail > 0 else 0)