Malen mit Symmetrie: nur wirklich bemalte Punkte spiegeln (harte gerade Kanten weg)
Sly 25.10.: „teilweise sehr harte Kanten in den Übergängen“. Ursache: bei aktiver Symmetrie kopierte jeder Mal-Schritt das GANZE Snapshot-Quadrat um den Pinsel auf die Gegenseite — dort vorhandene weiche Verläufe wurden an den Quadratkanten gerade abgeschnitten. Jetzt werden nur Punkte gespiegelt, die der Schritt verändert hat; überlappen beide Seiten, gewinnt wie bisher der näher am Strichpunkt liegende Wert. Test: test_terrain_mirror 109/109 (neuer Fall schlägt mit altem Code fehl). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
4e973795f6
commit
7f06e28472
2 changed files with 48 additions and 5 deletions
|
|
@ -549,22 +549,30 @@ func _mirror_mats(snap: Dictionary, g: Vector2) -> void:
|
|||
var positions: Array = snap.keys()
|
||||
positions.sort_custom(func(a: Vector2i, b: Vector2i) -> bool:
|
||||
return (a.y * _mres + a.x) < (b.y * _mres + b.x))
|
||||
# Karte 25.10. (Sly: harte gerade Kanten mit Symmetrie): NUR Punkte spiegeln,
|
||||
# die dieser Pinsel-Schritt wirklich verändert hat. Vorher wurde das ganze
|
||||
# Snapshot-Quadrat auf die Gegenseite kopiert — weiche Verläufe drüben
|
||||
# wurden an den Quadratkanten hart abgeschnitten.
|
||||
for pos: Vector2i in positions:
|
||||
if done.has(pos):
|
||||
continue
|
||||
var idx: int = pos.y * _mres + pos.x
|
||||
var mirror: Vector2i = SymmetryCore.mirror_cell(sym, pos.x, pos.y, _mres)
|
||||
done[pos] = true
|
||||
var idx: int = pos.y * _mres + pos.x
|
||||
if _punkt(idx) == int(snap[pos]):
|
||||
continue # nicht bemalt → Gegenseite bleibt unangetastet
|
||||
var mirror: Vector2i = SymmetryCore.mirror_cell(sym, pos.x, pos.y, _mres)
|
||||
if mirror == pos:
|
||||
continue
|
||||
var midx: int = mirror.y * _mres + mirror.x
|
||||
var value: int = _punkt(idx)
|
||||
if snap.has(mirror):
|
||||
if snap.has(mirror) and _punkt(midx) != int(snap[mirror]):
|
||||
# Beide Seiten bemalt (Pinsel überlappt die Achse): der näher am
|
||||
# Strichpunkt liegende Wert gewinnt, beide bekommen ihn.
|
||||
if _cell_dist(mirror, g, cell_x, cell_z) < _cell_dist(pos, g, cell_x, cell_z):
|
||||
value = _punkt(midx)
|
||||
_setze_punkt(idx, value)
|
||||
_setze_punkt(midx, value)
|
||||
done[mirror] = true
|
||||
_setze_punkt(midx, value)
|
||||
|
||||
|
||||
# ----------------------------------------------------------- Ring-Optik -----
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ func _run_tests() -> void:
|
|||
_test_off_mode_unchanged()
|
||||
_test_live_rebuild_inputs()
|
||||
_test_undo_one_step()
|
||||
_test_mirror_nur_bemalte()
|
||||
|
||||
|
||||
# ------------------------------------------------------------- Hilfsbau -----
|
||||
|
|
@ -514,3 +515,37 @@ func _world_to_cell(at: Vector2) -> Vector2i:
|
|||
var fx: int = clampi(int(roundf((at.x / SIZE + 0.5) * float(RES - 1))), 0, RES - 1)
|
||||
var fz: int = clampi(int(roundf((at.y / SIZE + 0.5) * float(RES - 1))), 0, RES - 1)
|
||||
return Vector2i(fx, fz)
|
||||
|
||||
## Karte 25.10.: Mit Symmetrie wird NUR gespiegelt, was der Pinsel wirklich
|
||||
## bemalt hat — die Gegenseite außerhalb des Spiegelkreises bleibt unberührt
|
||||
## (vorher: ganzes Snapshot-Quadrat kopiert → harte gerade Kanten).
|
||||
func _test_mirror_nur_bemalte() -> void:
|
||||
print("Testgruppe: Spiegeln nur bemalter Punkte (Quadrat-Kanten-Bug)")
|
||||
var parts := _make_tool(SymmetryCore.Mode.POINT)
|
||||
var ttool = parts[0]
|
||||
var doc: Dictionary = parts[3]
|
||||
# Gegenseite vorbereiten: Fels-Fleck dort, wo das Spiegel-QUADRAT, aber
|
||||
# nicht der Spiegel-KREIS des Strichs liegt (Ecke des Quadrats).
|
||||
var t: Dictionary = doc["terrain"]
|
||||
var mats := SvmapIO.decode_materials(t)
|
||||
var cell := SIZE / float(RES - 1)
|
||||
var ecke := Vector2(100.0 + RADIUS * 0.9, 60.0 + RADIUS * 0.9) # Spiegelpunkt der Quadratecke
|
||||
var gx := int(roundf((ecke.x / SIZE + 0.5) * float(RES - 1)))
|
||||
var gz := int(roundf((ecke.y / SIZE + 0.5) * float(RES - 1)))
|
||||
mats[gz * RES + gx] = 2
|
||||
t["materials_r8_b64"] = SvmapIO.encode_materials(mats)
|
||||
ttool.call("refresh_from_doc")
|
||||
ttool.call("set_paint_material", 1)
|
||||
ttool.set("brush_weichheit", 0.8)
|
||||
_stroke(ttool, -100.0, -60.0, TerrainField.Mode.PAINT, 0.2)
|
||||
var after := SvmapIO.decode_materials(doc["terrain"])
|
||||
_check(int(after[gz * RES + gx]) == 2,
|
||||
"Fels-Fleck auf der Gegenseite (Quadratecke, außerhalb des Kreises) bleibt (Zelle %d,%d)" % [gx, gz])
|
||||
var mm := SymmetryCore.mirror_cell(SymmetryCore.Mode.POINT,
|
||||
int(roundf((-100.0 / SIZE + 0.5) * float(RES - 1))),
|
||||
int(roundf((-60.0 / SIZE + 0.5) * float(RES - 1))), RES)
|
||||
var mix := SvmapIO.decode_mix(doc["terrain"])
|
||||
var share := func(i: int) -> float:
|
||||
var w := float(mix[1][i]) / 255.0
|
||||
return (1.0 - w if after[i] == 1 else 0.0) + (w if mix[0][i] == 1 else 0.0)
|
||||
_check(share.call(mm.y * RES + mm.x) > 0.99, "Strichmitte auf der Gegenseite gespiegelt (Sand)")
|
||||
|
|
|
|||
Loading…
Reference in a new issue