Implement playable Mac client and rendering validation

This commit is contained in:
shen
2026-09-11 14:58:22 +08:00
parent 1ab68bd06e
commit 374d4165d8
233 changed files with 6546 additions and 284 deletions
+83
View File
@@ -0,0 +1,83 @@
extends SceneTree
const EffectPlayer = preload("res://fx/effect_player.gd")
var failures := 0
func check(ok: bool, label: String) -> void:
if not ok:
failures += 1
printerr("FAIL: " + label)
func effective(pm: ParticleProcessMaterial, age: float) -> Color:
return pm.color * pm.color_ramp.gradient.sample(age) if pm.color_ramp else pm.color
func _init() -> void:
var fx := EffectPlayer.new()
fx.build({"particles": [{"particle": {
"TimeEventColorRed": [[0.0, 0.2], [0.5, 0.8], [1.0, 0.4]],
"TimeEventColorGreen": [[0.25, 0.4], [0.75, 0.8]],
"TimeEventColorBlue": [[0.0, 0.5]],
"TimeEventAlpha": [[0.0, 1.0], [1.0, 0.0]]}},
{"particle": {"TimeEventColorRed": [[0.0, 0.5]], "TimeEventAlpha": [[0.0, 1.0]]}},
{"particle": {"TimeEventColorBlue": [[0.0, 0.2], [1.0, 0.8]]}},
{"particle": {}}]})
var pm: ParticleProcessMaterial = fx._emitters[0].process_material
check(pm.color == Color.WHITE, "neutral base prevents double tint")
check(effective(pm, 0.0).is_equal_approx(Color(0.2, 0.4, 0.5, 1.0)), "birth RGBA")
check(effective(pm, 0.25).is_equal_approx(Color(0.5, 0.4, 0.5, 0.75)), "independent green knot")
check(effective(pm, 0.5).is_equal_approx(Color(0.8, 0.6, 0.5, 0.5)), "middle RGBA")
check(effective(pm, 0.75).is_equal_approx(Color(0.6, 0.8, 0.5, 0.25)), "late RGBA")
check(effective(pm, 1.0).is_equal_approx(Color(0.4, 0.8, 0.5, 0.0)), "end RGBA")
check(effective(fx._emitters[1].process_material, 0.5).is_equal_approx(Color(0.5, 1.0, 1.0)),
"constant 0.5 tint remains 0.5, not 0.25")
check(effective(fx._emitters[2].process_material, 0.5).is_equal_approx(Color(1.0, 1.0, 0.5)),
"RGB animates without alpha track")
check(effective(fx._emitters[3].process_material, 0.5) == Color.WHITE, "missing tracks default white")
fx.free()
var malformed := EffectPlayer.new()
var cleaned: GradientTexture1D = malformed._color_ramp({"TimeEventColorRed": [
[1.0, 0.8], [], [0.0, 0.1], [0.0, 0.2], [NAN, 0.5], [0.5, INF], ["bad", 0.4]]})
check(cleaned.gradient.sample(0.5).is_equal_approx(Color(0.5, 1, 1)),
"unordered/duplicate keys normalized and invalid values ignored")
malformed.free()
real_resources()
print("effect_color_test: failures=%d" % failures)
quit(1 if failures else 0)
# Independent scalar interpolation oracle for the sorted, valid asset tracks.
func reference(rows: Array, age: float) -> float:
if rows.is_empty():
return 1.0
if age <= float(rows[0][0]):
return float(rows[0][1])
for i in range(1, rows.size()):
if age <= float(rows[i][0]):
var fraction := (age - float(rows[i - 1][0])) / (float(rows[i][0]) - float(rows[i - 1][0]))
return float(rows[i - 1][1]) * (1.0 - fraction) + float(rows[i][1]) * fraction
return float(rows[-1][1])
func real_resources() -> void:
var count := 0
for name in ["warrior/effect/palbang_4_sword.mse", "assassin/effect/beam_blow.mse",
"sura/effect/pabeopsul_4_blow.mse", "shaman/effect/noejeon_making_1.mse"]:
var path := AssetRoot.path().path_join("PC/ymir work/pc/" + name)
var parsed: Dictionary = preload("res://fx/mse.gd").new().parse_file(path)
check(not parsed.get("particles", []).is_empty(), "real resource loaded: " + name)
for particle in parsed.get("particles", []):
# Exercise real RGBA through material construction; texture loading and
# emission geometry are deliberately outside this color-only regression.
var prop: Dictionary = {}
for key in ["TimeEventColorRed", "TimeEventColorGreen", "TimeEventColorBlue", "TimeEventAlpha"]:
prop[key] = particle.particle.get(key, [])
var fx := EffectPlayer.new()
fx.build({"particles": [{"particle": prop}]})
var pm: ParticleProcessMaterial = fx._emitters[0].process_material
for step in range(41):
var age := float(step) / 40.0
var expected := Color(reference(prop.TimeEventColorRed, age),
reference(prop.TimeEventColorGreen, age), reference(prop.TimeEventColorBlue, age),
reference(prop.TimeEventAlpha, age))
check(effective(pm, age).is_equal_approx(expected), "real RGBA %s particle %d t=%f" % [name, count, age])
count += 1
fx.free()
print("real color tracks: particles=%d samples=%d" % [count, count * 41])