Compare commits
9 commits
server-tab
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
313500b988 | ||
|
|
8f01775a92 | ||
|
|
295f79011f | ||
|
|
949d73dfdd | ||
|
|
e8ab954876 | ||
|
|
ff1c0e345e | ||
|
|
91c66a0b98 | ||
|
|
330365e59b | ||
|
|
9589703f7c |
5
.gitmodules
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
[submodule "core"]
|
||||
path = core
|
||||
url = ../scopedvr-map-core.git
|
||||
branch = main
|
||||
ignore = untracked
|
||||
26
README.md
|
|
@ -48,14 +48,14 @@ UX-Fundament auf dem App-Skelett (t_5badf371), nach dem Chef-Grundsatz gebaut:
|
|||
Neue-Map-Dialog mit 4 Pflicht-Spawns pro Team, Orbit-Viewport mit Gitter/
|
||||
Boden/Wetter-Stimmung — siehe Commit 84bc081 und `svmap_io.gd`.)*
|
||||
|
||||
- **Undo/Redo (`src/editor/action_history.gd`):** zentrale ActionHistory über
|
||||
- **Undo/Redo (`core/editor/action_history.gd`):** zentrale ActionHistory über
|
||||
die svmap-Ober-Blöcke (`objects`/`terrain`/`spawn_zones` — tiefe Kopien vor
|
||||
und nach jeder Änderung, merge_tags gegen Mausrad-Tick-Fluten, Max-Stufe 100).
|
||||
Strg+Z / Strg+Y UND große Buttons „↩ Rückgängig / ↪ Wiederholen" oben.
|
||||
Spätere Werkzeuge melden sich mit `snapshot(keys)` vor und
|
||||
`commit(desc, before, after)` nach der Änderung an — Terrain-Strokes und
|
||||
Spawn-Zonen landen damit automatisch in derselben History.
|
||||
- **Objekt-Platzierung mit Ghost-Preview (`src/editor/interaction.gd`):**
|
||||
- **Objekt-Platzierung mit Ghost-Preview (`core/editor/interaction.gd`):**
|
||||
Bibliothek links (deutsche Namen + Poly-Zahl), Klick startet den
|
||||
Platzier-Modus — eine transparente Vorschau schwebt am Cursor auf dem Boden
|
||||
(Höhe kommt aus dem Terrain), Klick setzt, ESC bricht ab (Rechte
|
||||
|
|
@ -94,7 +94,7 @@ synchron ziehen (IDs sind der Vertrag, Entscheidung 20).
|
|||
|
||||
Auf dem Terrain-Werkzeug (t_9aba04f1) aufgebaut, nach dem Chef-Grundsatz:
|
||||
|
||||
- **Bibliothek-Browser mit Gruppen (`src/editor/library_browser.gd`):**
|
||||
- **Bibliothek-Browser mit Gruppen (`core/editor/library_browser.gd`):**
|
||||
*(Stand 25.10.2026, Military-Pack-Umstellung)* Die Bibliothek ist das
|
||||
komplette Military-Desert-Pack (418 Modelle + 5 Kombis = 423 Objekte aus
|
||||
`library/objects.json`), sortiert in 19 deutsche Kategorien aus dem
|
||||
|
|
@ -106,14 +106,14 @@ Auf dem Terrain-Werkzeug (t_9aba04f1) aufgebaut, nach dem Chef-Grundsatz:
|
|||
(Panzer mit Turm und Kanone, Hummer mit Rädern, Hubschrauber mit Rotoren);
|
||||
die Einzelteile stehen zusätzlich unter „Fahrzeugteile“. Unbekannte
|
||||
Kategorien (z. B. spätere Bauteil-Module) bekommen automatisch eine eigene
|
||||
Gruppe. Jeder Button zeigt ein 128-px-Thumbnail (`library/thumbs/*.png` —
|
||||
Gruppe. Jeder Button zeigt ein 128-px-Thumbnail (`core/thumbs/*.png` —
|
||||
erzeugt von `tools/sync_objects.sh`/`tools/gen_thumbs.gd` und committed;
|
||||
fehlt ein PNG, fällt der Button aufs Text-Layout zurück). Deutsche Namen
|
||||
kommen aus `name_de` im Manifest (ohne UI → headless testbar). Kollision:
|
||||
Gebäude/Zelte/Türme exakter Trimesh (betretbar), Fahrzeuge Verbund aus
|
||||
Boxen, Bäume nur Stamm, Dekor ohne Kollision — erzeugt vom Match-Server-Repo
|
||||
(`tools/pack_registry.py`).
|
||||
- **Snap to Ground (`src/editor/object_ops.gd`):** Ein Klick auf
|
||||
- **Snap to Ground (`core/editor/object_ops.gd`):** Ein Klick auf
|
||||
„⚡ Alles auf den Boden setzen" holt ALLE schwebenden Objekte auf die
|
||||
Terrain-Höhe (z. B. nach dem Terrain-Formen) — EIN Undo-Eintrag für die
|
||||
ganze Aktion. Objekte, die schon auf dem Boden stehen, bleiben unangetastet.
|
||||
|
|
@ -138,14 +138,14 @@ Export-Workflow.
|
|||
|
||||
Auf der Objekt-Bibliothek (t_3a998ae4) aufgebaut, nach dem Chef-Grundsatz:
|
||||
|
||||
- **Spawn-Zonen malen (`src/editor/spawn_tool.gd`):** Werkzeug
|
||||
- **Spawn-Zonen malen (`core/editor/spawn_tool.gd`):** Werkzeug
|
||||
„🚩 Spawn-Zonen malen“ — Team Blau 🔵 / Team Rot 🔴 (TDM-Konvention:
|
||||
IDs A…/B…, mapformat § spawn_zones), Klick setzt eine farbige flache
|
||||
Kreis-Zone auf dem Terrain (Vorschau-Kreis folgt der Maus), Radius
|
||||
2–30 m per Regler. Zone anklicken → auswählen + ziehen (Terrain-Höhe
|
||||
bleibt), Entf löscht, Strg+Z nimmt JEDE Operation zurück (jede Zone =
|
||||
EIN History-Eintrag, Radius-Slider-Ticks sind merge-gekoppelt).
|
||||
- **Live-Validierung (`src/editor/spawn_ops.gd`):** Block „Spawn-Check“
|
||||
- **Live-Validierung (`core/editor/spawn_ops.gd`):** Block „Spawn-Check“
|
||||
rechts bleibt STÄNDIG sichtbar und spiegelt exakt die Loader-Regeln
|
||||
(V11: ≥ 4 Spawn-Punkte pro Team · V7: Objekt-IDs in der Bibliothek) —
|
||||
z. B. „✅ Spawns Team Blau: 4 · ❌ Spawns Team Rot: 2 (mindestens 4
|
||||
|
|
@ -238,13 +238,13 @@ Undo für alles):
|
|||
Mehrfachauswahl + Gruppieren + Gruppen-Verschieben, auf dem UX-Fundament
|
||||
(t_40d855d0) aufgebaut, nach dem Chef-Grundsatz:
|
||||
|
||||
- **Mehrfachauswahl (`src/editor/interaction.gd`):** Umschalt+Klick fügt
|
||||
- **Mehrfachauswahl (`core/editor/interaction.gd`):** Umschalt+Klick fügt
|
||||
ein Objekt hinzu/entfernt es, Rahmen-Aufziehen (Rubberband) über leeren
|
||||
Boden wählt ALLE Objekte im Rahmen (Umschalt + Rahmen = zusätzliche zur
|
||||
Auswahl). Loser Klick auf leere Fläche hebt die Auswahl auf. ALLE
|
||||
markierten Objekte färben sich orange, das Auswahl-Panel rechts listet
|
||||
sie namentlich auf (ab 9: „… und N weitere“). Projektions-Mathe liegt
|
||||
in `src/editor/selection_math.gd` (headless getestet).
|
||||
in `core/editor/selection_math.gd` (headless getestet).
|
||||
- **Gruppieren:** Buttons „🔗 Gruppieren / ⛓ Gruppe lösen“ im Auswahl-Panel
|
||||
+ Kürzel Strg+G / Strg+Umschalt+G. Eine Gruppe braucht ≥ 2 Objekte.
|
||||
Gruppen-Mitglieder ziehen und drehen GEMEINSAM — ein Griff an ein
|
||||
|
|
@ -287,7 +287,7 @@ auch ungespeicherte! — sofort als Spiel in einem EIGENEN Fenster. Der Editor
|
|||
bleibt offen. Im Spiel: WASD laufen, Maus umsehen, Shift sprinten, Leertaste
|
||||
springen, ESC beendet das Test-Fenster sauber (kein Prozess-Kill nötig).
|
||||
|
||||
- **Temp-Export (`src/editor/test_run.gd`):** Die Map wird nach
|
||||
- **Temp-Export (`core/editor/test_run.gd`):** Die Map wird nach
|
||||
`user://testrun/<name>.svmap` exportiert (deterministischer Name aus dem
|
||||
Map-Namen, erneuter Testlauf überschreibt) — über dieselbe
|
||||
`SvmapIO.save_to_file`-Validierung wie das echte Speichern. Ist die Map
|
||||
|
|
@ -317,7 +317,7 @@ Tastenkürzel-Karte 1 von 3 (Sly-Freigabe 16.10., finale Belegung).
|
|||
Shortcut-Karten — Karten 2/3 ergänzen dort.
|
||||
|
||||
- **Konventionen (alle Karten):** Tastaturcode-basiert — InputMap-Actions mit
|
||||
PHYSISCHEN `KEY_*`-Konstanten (`src/editor/shortcut_keys.gd`, registriert in
|
||||
PHYSISCHEN `KEY_*`-Konstanten (`core/editor/shortcut_keys.gd`, registriert in
|
||||
`main._ready`, idempotent). Physische Codes = deutsche (QWERTZ) und
|
||||
Windows-Layouts identisch, keine OS-Hardcodes. Jede Objekt-Operation =
|
||||
EIN ActionHistory-Eintrag (Ausnahme: reine Kamera-Aktionen).
|
||||
|
|
@ -327,7 +327,7 @@ Shortcut-Karten — Karten 2/3 ergänzen dort.
|
|||
Orbit bleibt Default —
|
||||
beim Flug-Exit werden Ziel/Winkel/Abstand aus Flugposition/Blickrichtung
|
||||
zurückgerechnet (kein Kamera-Sprung, getestet). Mathe pur in
|
||||
`src/editor/fly_math.gd`, Kamera dünn (`src/viewport/orbit_camera.gd`).
|
||||
`core/editor/fly_math.gd`, Kamera dünn (`core/viewport/orbit_camera.gd`).
|
||||
Konflikt-Auflösung: RMB hat ABSOLUTEN Vorrang für den Flug — in JEDEM
|
||||
Werkzeugzustand (Terrain, Bauen, Spawn, Platzieren; Karte t_2470de89,
|
||||
kein `rmb_filter` mehr), Mausrad im Flug gehört dem Tempo (interaction
|
||||
|
|
@ -337,7 +337,7 @@ Shortcut-Karten — Karten 2/3 ergänzen dort.
|
|||
Flug dreht sich nur die Blickrichtung.
|
||||
- **Esc** = Prioritätskette Werkzeug verlassen → Ghost-Preview abbrechen →
|
||||
Auswahl aufheben, als pure, headless-getestete Funktion
|
||||
(`src/editor/shortcut_policy.gd`).
|
||||
(`core/editor/shortcut_policy.gd`).
|
||||
- **Entf (DELETE)** = Auswahl SOFORT löschen ohne Rückfrage (Sly-Yolo) —
|
||||
wirkt auf Szene-Auswahl UND Objektbaum-Markierung (Baum und Szene sind
|
||||
synchron), Strg+Z deckt es ab. War schon mehrfach-fähig, jetzt
|
||||
|
|
|
|||
|
|
@ -80,6 +80,6 @@ Roh-Modelle und Texturen weiterzugeben. Das heißt konkret:
|
|||
|
||||
---
|
||||
*Technischer Hintergrund: die Modelle werden zur Laufzeit per GLTFDocument
|
||||
aus dem `models/`-Ordner geladen (siehe `src/viewport/glb_mesh_store.gd`,
|
||||
aus dem `models/`-Ordner geladen (siehe `core/viewport/glb_mesh_store.gd`,
|
||||
Quellen-Reihenfolge: Einstellungen → Nachbar-Ordner `../scopedvr-client` →
|
||||
`models/`). Erster Treffer gewinnt.*
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
extends EditorPlugin
|
||||
|
||||
const PIECE_SCRIPT = preload("res://addons/modular_builder/modular_piece.gd")
|
||||
const DETAIL_SCRIPT = preload("res://addons/modular_builder/modular_building_detail.gd")
|
||||
const DETAIL_SCRIPT = preload("res://core/vendor/modular_builder/modular_building_detail.gd")
|
||||
const MESH_BAKER = preload("res://addons/modular_builder/modular_mesh_baker.gd")
|
||||
const TOOL_NONE := ""
|
||||
const TOOL_FOUNDATION := "foundation"
|
||||
|
|
|
|||
|
|
@ -1,284 +0,0 @@
|
|||
@tool
|
||||
class_name ModularBuilderDetail
|
||||
extends Node3D
|
||||
|
||||
enum DetailType { WINDOW, DOOR, HATCH, PILLAR, FENCE, PARAPET }
|
||||
enum DetailMode { OPENING, SEPARATE_OBJECT }
|
||||
enum WindowStyle { SINGLE_PANE, CROSS_PANE }
|
||||
enum DoorStyle { FLAT, PANELED }
|
||||
|
||||
@export var detail_type: DetailType = DetailType.WINDOW:
|
||||
set(value):
|
||||
detail_type = value
|
||||
notify_property_list_changed()
|
||||
_rebuild()
|
||||
@export var detail_mode: DetailMode = DetailMode.OPENING:
|
||||
set(value):
|
||||
detail_mode = value
|
||||
notify_property_list_changed()
|
||||
_rebuild()
|
||||
@export var center_align: bool = false:
|
||||
set(value):
|
||||
center_align = value
|
||||
_apply_pillar_alignment()
|
||||
notify_property_list_changed()
|
||||
@export_storage var pillar_direction: Vector3 = Vector3.UP
|
||||
@export_storage var pillar_alignment_basis: Basis = Basis.IDENTITY
|
||||
@export var window_style: WindowStyle = WindowStyle.SINGLE_PANE:
|
||||
set(value):
|
||||
window_style = value
|
||||
_rebuild()
|
||||
@export var door_style: DoorStyle = DoorStyle.FLAT:
|
||||
set(value):
|
||||
door_style = value
|
||||
_rebuild()
|
||||
@export_range(0.01, 5.0, 0.001, "suffix:m") var width: float = 1.0:
|
||||
set(value):
|
||||
width = value
|
||||
_rebuild()
|
||||
@export_range(0.2, 5.0, 0.001, "suffix:m") var height: float = 1.0:
|
||||
set(value):
|
||||
height = value
|
||||
_rebuild()
|
||||
@export_range(0.02, 0.5, 0.001, "suffix:m") var frame_depth: float = 0.08:
|
||||
set(value):
|
||||
frame_depth = value
|
||||
_rebuild()
|
||||
@export_range(0.1, 8.0, 0.001, "suffix:m") var fence_height: float = 0.7:
|
||||
set(value):
|
||||
fence_height = value
|
||||
_rebuild()
|
||||
@export_range(0, 100, 1, "suffix: posts") var fence_divisions: int = 1:
|
||||
set(value):
|
||||
fence_divisions = value
|
||||
_rebuild()
|
||||
@export_storage var path_points: PackedVector3Array = PackedVector3Array()
|
||||
@export_range(0.01, 0.5, 0.001, "suffix:m") var frame_width: float = 0.08:
|
||||
set(value):
|
||||
frame_width = value
|
||||
_rebuild()
|
||||
@export var follow_host_thickness: bool = true:
|
||||
set(value):
|
||||
follow_host_thickness = value
|
||||
_rebuild()
|
||||
@export var surface_material: Material:
|
||||
set(value):
|
||||
surface_material = value
|
||||
_rebuild()
|
||||
@export var frame_material: Material:
|
||||
set(value):
|
||||
frame_material = value
|
||||
_rebuild()
|
||||
@export var panel_material: Material:
|
||||
set(value):
|
||||
panel_material = value
|
||||
_rebuild()
|
||||
|
||||
func _validate_property(property: Dictionary) -> void:
|
||||
var separate_object := detail_mode == DetailMode.SEPARATE_OBJECT
|
||||
var is_window := detail_type == DetailType.WINDOW
|
||||
var is_door := detail_type == DetailType.DOOR
|
||||
var has_frame_and_panel := separate_object and detail_type != DetailType.PILLAR and detail_type != DetailType.FENCE and detail_type != DetailType.PARAPET
|
||||
var show_property := true
|
||||
match StringName(property.name):
|
||||
&"detail_mode":
|
||||
show_property = detail_type != DetailType.PILLAR and detail_type != DetailType.FENCE and detail_type != DetailType.PARAPET
|
||||
&"center_align":
|
||||
show_property = detail_type == DetailType.PILLAR
|
||||
&"fence_height", &"fence_divisions":
|
||||
show_property = detail_type == DetailType.FENCE or detail_type == DetailType.PARAPET
|
||||
&"path_points":
|
||||
show_property = false
|
||||
&"width":
|
||||
show_property = detail_type != DetailType.FENCE and detail_type != DetailType.PARAPET
|
||||
if detail_type == DetailType.PILLAR:
|
||||
property.hint = PROPERTY_HINT_RANGE
|
||||
property.hint_string = "0.01,5.0,0.001,suffix:m"
|
||||
&"height":
|
||||
show_property = detail_type != DetailType.FENCE and detail_type != DetailType.PARAPET
|
||||
&"window_style":
|
||||
show_property = is_window and separate_object
|
||||
&"door_style":
|
||||
show_property = is_door and separate_object
|
||||
&"frame_width", &"frame_material", &"panel_material":
|
||||
show_property = has_frame_and_panel
|
||||
&"follow_host_thickness":
|
||||
show_property = has_frame_and_panel
|
||||
&"frame_depth":
|
||||
show_property = has_frame_and_panel and not follow_host_thickness
|
||||
&"surface_material":
|
||||
show_property = separate_object
|
||||
if not show_property:
|
||||
property.usage = PROPERTY_USAGE_NO_EDITOR
|
||||
|
||||
func _ready() -> void:
|
||||
set_notify_transform(true)
|
||||
_rebuild()
|
||||
|
||||
func _notification(what: int) -> void:
|
||||
if what == NOTIFICATION_TRANSFORM_CHANGED and is_inside_tree():
|
||||
var host := get_parent()
|
||||
if host != null and host.has_method("_rebuild"):
|
||||
host.call("_rebuild")
|
||||
|
||||
func _on_host_thickness_changed() -> void:
|
||||
_rebuild(false)
|
||||
|
||||
func _apply_pillar_alignment() -> void:
|
||||
if detail_type != DetailType.PILLAR:
|
||||
return
|
||||
var direction := pillar_direction.normalized()
|
||||
if direction.is_zero_approx():
|
||||
direction = Vector3.UP
|
||||
if center_align:
|
||||
var object_axes := pillar_alignment_basis.orthonormalized()
|
||||
var best_axis := direction
|
||||
var best_dot := -1.0
|
||||
for axis in [object_axes.x, object_axes.y, object_axes.z]:
|
||||
var normalized_axis: Vector3 = axis.normalized()
|
||||
var alignment := absf(direction.dot(normalized_axis))
|
||||
if alignment > best_dot:
|
||||
best_dot = alignment
|
||||
best_axis = normalized_axis if direction.dot(normalized_axis) >= 0.0 else -normalized_axis
|
||||
direction = best_axis
|
||||
var reference_axis := Vector3.FORWARD if absf(direction.dot(Vector3.UP)) > 0.99 else Vector3.UP
|
||||
var x_axis := reference_axis.cross(direction).normalized()
|
||||
var z_axis := x_axis.cross(direction).normalized()
|
||||
transform.basis = Basis(x_axis, direction, z_axis).orthonormalized()
|
||||
if center_align and pillar_direction.length() > 0.0:
|
||||
height = pillar_direction.length()
|
||||
|
||||
func _rebuild(notify_host: bool = true) -> void:
|
||||
if not is_inside_tree():
|
||||
return
|
||||
for child in get_children():
|
||||
if child.name == "DetailGeometry":
|
||||
remove_child(child)
|
||||
child.queue_free()
|
||||
var host := get_parent()
|
||||
if notify_host and host != null and host.has_method("_rebuild"):
|
||||
host.call("_rebuild")
|
||||
if detail_mode == DetailMode.OPENING and detail_type != DetailType.FENCE and detail_type != DetailType.PARAPET:
|
||||
return
|
||||
var holder := Node3D.new()
|
||||
holder.name = "DetailGeometry"
|
||||
add_child(holder)
|
||||
var scene_root: Node = null
|
||||
if Engine.is_editor_hint() and not has_meta("modular_builder_preview"):
|
||||
scene_root = get_tree().edited_scene_root
|
||||
if scene_root:
|
||||
holder.owner = scene_root
|
||||
var effective_depth := _effective_frame_depth()
|
||||
var frame := minf(maxf(frame_width, 0.01), minf(width, height) * 0.45)
|
||||
if detail_type == DetailType.FENCE or detail_type == DetailType.PARAPET:
|
||||
_build_fence_geometry(holder)
|
||||
return
|
||||
if detail_type == DetailType.PILLAR:
|
||||
_add_box(holder, "PillarBody", Vector3(width, height, width), Vector3.ZERO, surface_material)
|
||||
return
|
||||
if detail_type == DetailType.HATCH:
|
||||
_add_box(holder, "LeftFrame", Vector3(frame, effective_depth, height), Vector3(-width * 0.5 + frame * 0.5, 0.0, 0.0), _frame_material())
|
||||
_add_box(holder, "RightFrame", Vector3(frame, effective_depth, height), Vector3(width * 0.5 - frame * 0.5, 0.0, 0.0), _frame_material())
|
||||
_add_box(holder, "NearFrame", Vector3(width, effective_depth, frame), Vector3(0.0, 0.0, -height * 0.5 + frame * 0.5), _frame_material())
|
||||
_add_box(holder, "FarFrame", Vector3(width, effective_depth, frame), Vector3(0.0, 0.0, height * 0.5 - frame * 0.5), _frame_material())
|
||||
_add_box(holder, "HatchPanel", Vector3(width - frame * 2.0, effective_depth * 0.35, height - frame * 2.0), Vector3(0.0, effective_depth * 0.4, 0.0), _panel_material())
|
||||
return
|
||||
_add_box(holder, "LeftFrame", Vector3(frame, height, effective_depth), Vector3(-width * 0.5 + frame * 0.5, 0.0, 0.0), _frame_material())
|
||||
_add_box(holder, "RightFrame", Vector3(frame, height, effective_depth), Vector3(width * 0.5 - frame * 0.5, 0.0, 0.0), _frame_material())
|
||||
_add_box(holder, "TopFrame", Vector3(width, frame, effective_depth), Vector3(0.0, height * 0.5 - frame * 0.5, 0.0), _frame_material())
|
||||
if detail_type != DetailType.DOOR:
|
||||
_add_box(holder, "BottomFrame", Vector3(width, frame, effective_depth), Vector3(0.0, -height * 0.5 + frame * 0.5, 0.0), _frame_material())
|
||||
if detail_type == DetailType.WINDOW:
|
||||
_add_box(holder, "WindowPanel", Vector3(maxf(width - frame * 2.0, 0.001), maxf(height - frame * 2.0, 0.001), effective_depth * 0.35), Vector3.ZERO, _panel_material())
|
||||
if window_style == WindowStyle.CROSS_PANE:
|
||||
_add_box(holder, "VerticalMullion", Vector3(frame * 0.55, height - frame * 2.0, effective_depth * 0.4), Vector3.ZERO, _frame_material())
|
||||
_add_box(holder, "HorizontalMullion", Vector3(width - frame * 2.0, frame * 0.55, effective_depth * 0.4), Vector3.ZERO, _frame_material())
|
||||
elif detail_type == DetailType.DOOR:
|
||||
_add_box(holder, "DoorPanel", Vector3(width - frame * 2.0, height - frame, effective_depth * 0.45), Vector3(0.0, -frame * 0.5, 0.0), _panel_material())
|
||||
if door_style == DoorStyle.PANELED:
|
||||
var inset_depth := maxf(effective_depth * 0.04, 0.005)
|
||||
var panel_width := (width - frame * 2.0) * 0.82
|
||||
var panel_height := maxf((height - frame) * 0.28, 0.05)
|
||||
for panel_index in range(2):
|
||||
var panel_y := -frame * 0.5 + (panel_index - 0.5) * (panel_height + frame * 0.25)
|
||||
_add_box(holder, "DoorInset_%d" % panel_index, Vector3(panel_width, panel_height, inset_depth), Vector3(0.0, panel_y, effective_depth * 0.24), _frame_material())
|
||||
|
||||
func _effective_frame_depth() -> float:
|
||||
if follow_host_thickness:
|
||||
var host := get_parent()
|
||||
if host != null:
|
||||
var host_thickness = host.get("thickness")
|
||||
if host_thickness is float or host_thickness is int:
|
||||
var depth := float(host_thickness)
|
||||
if detail_type == DetailType.WINDOW or detail_type == DetailType.DOOR:
|
||||
depth *= 1.25
|
||||
return maxf(depth, 0.02)
|
||||
return frame_depth
|
||||
|
||||
func _build_fence_geometry(holder: Node3D) -> void:
|
||||
if path_points.size() < 2 or fence_height <= 0.0:
|
||||
return
|
||||
var start := path_points[0]
|
||||
var finish := path_points[1]
|
||||
var path := finish - start
|
||||
var path_length := path.length()
|
||||
if path_length < 0.05:
|
||||
return
|
||||
var path_axis := path / path_length
|
||||
var up_axis := Vector3.UP - path_axis * path_axis.dot(Vector3.UP)
|
||||
if up_axis.length_squared() < 0.001:
|
||||
up_axis = Vector3.FORWARD - path_axis * path_axis.dot(Vector3.FORWARD)
|
||||
up_axis = up_axis.normalized()
|
||||
var side_axis := path_axis.cross(up_axis).normalized()
|
||||
var post_width := 0.16 if detail_type == DetailType.PARAPET else 0.08
|
||||
var post_count := fence_divisions + 2
|
||||
var posts: Array[Vector3] = []
|
||||
for i in range(post_count):
|
||||
var base := start.lerp(finish, float(i) / float(post_count - 1))
|
||||
posts.append(base)
|
||||
_add_oriented_box(holder, "Post_%d" % i, base + up_axis * fence_height * 0.5, path_axis, up_axis, side_axis, Vector3(post_width, fence_height, post_width))
|
||||
for i in range(posts.size() - 1):
|
||||
var a := posts[i]
|
||||
var b := posts[i + 1]
|
||||
var segment := b - a
|
||||
var segment_length := segment.length()
|
||||
if detail_type == DetailType.PARAPET:
|
||||
_add_oriented_box(holder, "Rail_%d" % i, (a + b) * 0.5 + up_axis * fence_height * 0.78, segment.normalized(), up_axis, side_axis, Vector3(segment_length, post_width * 0.8, post_width * 0.8))
|
||||
else:
|
||||
for height_ratio in [0.28, 0.78]:
|
||||
_add_oriented_box(holder, "Rail_%d_%d" % [i, int(height_ratio * 100.0)], (a + b) * 0.5 + up_axis * fence_height * height_ratio, segment.normalized(), up_axis, side_axis, Vector3(segment_length, post_width, post_width))
|
||||
|
||||
func _add_oriented_box(holder: Node3D, node_name: String, center: Vector3, axis_x: Vector3, axis_y: Vector3, axis_z: Vector3, dimensions: Vector3) -> void:
|
||||
var mesh_instance := MeshInstance3D.new()
|
||||
mesh_instance.name = node_name
|
||||
var box := BoxMesh.new()
|
||||
box.size = dimensions
|
||||
mesh_instance.mesh = box
|
||||
var basis := Basis(axis_x.normalized(), axis_y.normalized(), axis_z.normalized()).orthonormalized()
|
||||
mesh_instance.transform = Transform3D(basis, center)
|
||||
mesh_instance.material_override = surface_material
|
||||
holder.add_child(mesh_instance)
|
||||
if Engine.is_editor_hint() and not has_meta("modular_builder_preview"):
|
||||
var scene_root := get_tree().edited_scene_root
|
||||
if scene_root:
|
||||
mesh_instance.owner = scene_root
|
||||
|
||||
func _frame_material() -> Material:
|
||||
return frame_material if frame_material != null else surface_material
|
||||
|
||||
func _panel_material() -> Material:
|
||||
return panel_material if panel_material != null else surface_material
|
||||
|
||||
func _add_box(holder: Node3D, node_name: String, box_size: Vector3, box_position: Vector3, material: Material = null) -> void:
|
||||
var mesh_instance := MeshInstance3D.new()
|
||||
mesh_instance.name = node_name
|
||||
var box := BoxMesh.new()
|
||||
box.size = box_size
|
||||
mesh_instance.mesh = box
|
||||
mesh_instance.position = box_position
|
||||
mesh_instance.material_override = material if material != null else surface_material
|
||||
holder.add_child(mesh_instance)
|
||||
if Engine.is_editor_hint() and not has_meta("modular_builder_preview"):
|
||||
var scene_root := get_tree().edited_scene_root
|
||||
if scene_root:
|
||||
mesh_instance.owner = scene_root
|
||||
|
|
@ -1 +0,0 @@
|
|||
uid://dsttda167kuhi
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
@tool
|
||||
class_name ModularBuilderPiece
|
||||
extends "res://addons/modular_builder/modular_piece_geometry.gd"
|
||||
extends "res://core/vendor/modular_builder/modular_piece_geometry.gd"
|
||||
|
||||
func _ready() -> void:
|
||||
_rebuild()
|
||||
|
|
|
|||
|
|
@ -1,748 +0,0 @@
|
|||
@tool
|
||||
class_name ModularBuilderPieceGeometry
|
||||
extends Node3D
|
||||
|
||||
const DETAIL_SCRIPT_PATH := "res://addons/modular_builder/modular_building_detail.gd"
|
||||
const DETAIL_TYPE_HATCH := 2
|
||||
const DETAIL_TYPE_PILLAR := 3
|
||||
|
||||
enum PieceType { FOUNDATION_SQUARE, FOUNDATION_TRIANGLE, FLOOR, WALL, BUILDING, GABLE_WALL, ROOF_GABLE, ROOF_SHED, GABLE_WALL_RIGHT, ROOF_PYRAMID, STAIRS, FENCE }
|
||||
|
||||
@export var piece_type: PieceType = PieceType.FOUNDATION_SQUARE:
|
||||
set(value):
|
||||
piece_type = value
|
||||
notify_property_list_changed()
|
||||
_rebuild()
|
||||
@export_range(0.5, 8.0, 0.001, "suffix:m") var unit_size: float = 2.0:
|
||||
set(value):
|
||||
unit_size = value
|
||||
_rebuild()
|
||||
@export_range(0.01, 1.0, 0.001, "suffix:m") var thickness: float = 0.2:
|
||||
set(value):
|
||||
thickness = value
|
||||
_rebuild()
|
||||
for child in get_children():
|
||||
if child.has_method("_on_host_thickness_changed"):
|
||||
child.call("_on_host_thickness_changed")
|
||||
@export_range(0.1, 8.0, 0.001, "suffix:m") var rise: float = 1.0:
|
||||
set(value):
|
||||
rise = value
|
||||
_rebuild()
|
||||
@export_range(0.01, 32.0, 0.001, "suffix:m") var roof_width: float = 2.0:
|
||||
set(value):
|
||||
roof_width = value
|
||||
_rebuild()
|
||||
@export_range(1, 100, 1, "suffix: steps") var stair_count: int = 10:
|
||||
set(value):
|
||||
stair_count = value
|
||||
_rebuild()
|
||||
@export_range(0.01, 8.0, 0.001, "suffix:m") var stair_width: float = 1.0:
|
||||
set(value):
|
||||
stair_width = value
|
||||
_rebuild()
|
||||
@export_range(0, 100, 1, "suffix: posts") var fence_divisions: int = 1:
|
||||
set(value):
|
||||
fence_divisions = value
|
||||
_rebuild()
|
||||
@export_range(0.1, 8.0, 0.001, "suffix:m") var fence_height: float = 1.0:
|
||||
set(value):
|
||||
fence_height = value
|
||||
_rebuild()
|
||||
@export var symmetric_dimensions: bool = true:
|
||||
set(value):
|
||||
if symmetric_dimensions == value:
|
||||
return
|
||||
if not value:
|
||||
_capture_mesh_dimensions()
|
||||
symmetric_dimensions = value
|
||||
notify_property_list_changed()
|
||||
if value:
|
||||
scale = Vector3.ONE
|
||||
else:
|
||||
_apply_dimension_scale()
|
||||
@export_range(0.01, 100.0, 0.001, "suffix:m") var dimension_width: float = 2.0:
|
||||
set(value):
|
||||
dimension_width = value
|
||||
_apply_dimension_scale()
|
||||
@export_range(0.01, 100.0, 0.001, "suffix:m") var dimension_height: float = 2.0:
|
||||
set(value):
|
||||
dimension_height = value
|
||||
_apply_dimension_scale()
|
||||
@export_range(0.01, 100.0, 0.001, "suffix:m") var dimension_depth: float = 2.0:
|
||||
set(value):
|
||||
dimension_depth = value
|
||||
_apply_dimension_scale()
|
||||
@export_storage var _dimension_reference: Vector3 = Vector3.ZERO
|
||||
@export var center_align: bool = false:
|
||||
set(value):
|
||||
center_align = value
|
||||
_rebuild()
|
||||
@export var surface_material: Material:
|
||||
set(value):
|
||||
surface_material = value
|
||||
_rebuild()
|
||||
@export var custom_points: PackedVector3Array = PackedVector3Array():
|
||||
set(value):
|
||||
custom_points = value
|
||||
_rebuild()
|
||||
@export var centered_origin: bool = false:
|
||||
set(value):
|
||||
centered_origin = value
|
||||
_rebuild()
|
||||
|
||||
func _rebuild() -> void:
|
||||
pass
|
||||
|
||||
func _capture_mesh_dimensions() -> void:
|
||||
var geometry := get_node_or_null("Geometry") as MeshInstance3D
|
||||
if geometry == null or geometry.mesh == null:
|
||||
return
|
||||
var dimensions := geometry.mesh.get_aabb().size
|
||||
if dimensions.x > 0.001:
|
||||
dimension_width = dimensions.x
|
||||
if dimensions.y > 0.001:
|
||||
dimension_height = dimensions.y
|
||||
if dimensions.z > 0.001:
|
||||
dimension_depth = dimensions.z
|
||||
_dimension_reference = dimensions
|
||||
|
||||
func _apply_dimension_scale() -> void:
|
||||
if symmetric_dimensions or _dimension_reference.x <= 0.001 or _dimension_reference.y <= 0.001 or _dimension_reference.z <= 0.001:
|
||||
return
|
||||
var target := Vector3(dimension_width, dimension_height, dimension_depth)
|
||||
if piece_type == PieceType.FOUNDATION_SQUARE or piece_type == PieceType.FOUNDATION_TRIANGLE or piece_type == PieceType.FLOOR:
|
||||
target.y = _dimension_reference.y
|
||||
if piece_type == PieceType.WALL:
|
||||
target.z = _dimension_reference.z
|
||||
scale = Vector3(target.x / _dimension_reference.x, target.y / _dimension_reference.y, target.z / _dimension_reference.z)
|
||||
|
||||
func _make_mesh() -> ArrayMesh:
|
||||
if piece_type == PieceType.GABLE_WALL and custom_points.size() >= 2:
|
||||
return _make_gable_wall_mesh()
|
||||
if piece_type == PieceType.GABLE_WALL_RIGHT and custom_points.size() >= 2:
|
||||
return _make_right_gable_wall_mesh()
|
||||
if (piece_type == PieceType.ROOF_GABLE or piece_type == PieceType.ROOF_SHED or piece_type == PieceType.ROOF_PYRAMID) and custom_points.size() >= 2:
|
||||
return _make_roof_mesh()
|
||||
if piece_type == PieceType.STAIRS and custom_points.size() >= 2:
|
||||
return _make_stair_mesh()
|
||||
if piece_type == PieceType.FENCE and custom_points.size() >= 2:
|
||||
return _make_fence_mesh()
|
||||
if custom_points.size() >= 2 and piece_type == PieceType.WALL:
|
||||
return _make_custom_wall_mesh()
|
||||
if custom_points.size() >= 3 and piece_type == PieceType.FLOOR:
|
||||
return _make_custom_floor_mesh()
|
||||
if custom_points.size() >= 3 and (piece_type == PieceType.FOUNDATION_SQUARE or piece_type == PieceType.FOUNDATION_TRIANGLE):
|
||||
return _make_custom_foundation_mesh()
|
||||
var vertices := PackedVector3Array()
|
||||
var normals := PackedVector3Array()
|
||||
var s := unit_size
|
||||
var polygon: Array[Vector2]
|
||||
match piece_type:
|
||||
PieceType.FOUNDATION_TRIANGLE:
|
||||
polygon = [Vector2(-s * 0.5, -s * 0.5), Vector2(s * 0.5, -s * 0.5), Vector2(-s * 0.5, s * 0.5)]
|
||||
_:
|
||||
polygon = [Vector2(-s * 0.5, -s * 0.5), Vector2(s * 0.5, -s * 0.5), Vector2(s * 0.5, s * 0.5), Vector2(-s * 0.5, s * 0.5)]
|
||||
var y0 := -thickness * 0.5 if centered_origin else 0.0
|
||||
var y1 := thickness * 0.5 if centered_origin else thickness
|
||||
if piece_type == PieceType.WALL:
|
||||
polygon = [Vector2(-s * 0.5, -thickness * 0.5), Vector2(s * 0.5, -thickness * 0.5), Vector2(s * 0.5, thickness * 0.5), Vector2(-s * 0.5, thickness * 0.5)]
|
||||
y0 = -s * 0.5 if centered_origin else 0.0
|
||||
y1 = s * 0.5 if centered_origin else s
|
||||
if piece_type == PieceType.FOUNDATION_SQUARE or piece_type == PieceType.FOUNDATION_TRIANGLE:
|
||||
var hatch_mesh := _make_hatch_surface_mesh(polygon, y1, y0)
|
||||
if hatch_mesh != null:
|
||||
return hatch_mesh
|
||||
for i in range(1, polygon.size() - 1):
|
||||
_add_tri(vertices, normals, Vector3(polygon[0].x, y1, polygon[0].y), Vector3(polygon[i + 1].x, y1, polygon[i + 1].y), Vector3(polygon[i].x, y1, polygon[i].y))
|
||||
_add_tri(vertices, normals, Vector3(polygon[0].x, y0, polygon[0].y), Vector3(polygon[i].x, y0, polygon[i].y), Vector3(polygon[i + 1].x, y0, polygon[i + 1].y))
|
||||
for i in range(polygon.size()):
|
||||
var j := (i + 1) % polygon.size()
|
||||
var a := polygon[i]
|
||||
var b := polygon[j]
|
||||
_add_tri(vertices, normals, Vector3(a.x, y0, a.y), Vector3(b.x, y0, b.y), Vector3(b.x, y1, b.y))
|
||||
_add_tri(vertices, normals, Vector3(a.x, y0, a.y), Vector3(b.x, y1, b.y), Vector3(a.x, y1, a.y))
|
||||
var arrays: Array = []
|
||||
arrays.resize(Mesh.ARRAY_MAX)
|
||||
arrays[Mesh.ARRAY_VERTEX] = vertices
|
||||
arrays[Mesh.ARRAY_NORMAL] = normals
|
||||
var result := ArrayMesh.new()
|
||||
result.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, arrays)
|
||||
return result
|
||||
|
||||
func _make_gable_wall_mesh() -> ArrayMesh:
|
||||
var vertices := PackedVector3Array()
|
||||
var normals := PackedVector3Array()
|
||||
var base_points := _get_centered_gable_base() if center_align else PackedVector3Array([custom_points[0], custom_points[1]])
|
||||
var a: Vector3 = base_points[0]
|
||||
var b: Vector3 = base_points[1]
|
||||
var direction := (b - a).normalized()
|
||||
var side := Vector3(-direction.z, 0.0, direction.x).normalized() * thickness * 0.5
|
||||
var peak := (a + b) * 0.5 + Vector3.UP * rise
|
||||
var front_a := a + side
|
||||
var front_b := b + side
|
||||
var front_peak := peak + side
|
||||
var back_a := a - side
|
||||
var back_b := b - side
|
||||
var back_peak := peak - side
|
||||
_add_tri(vertices, normals, front_a, front_b, front_peak)
|
||||
_add_tri(vertices, normals, back_b, back_a, back_peak)
|
||||
_add_quad(vertices, normals, front_a, back_a, back_b, front_b)
|
||||
_add_quad(vertices, normals, front_b, back_b, back_peak, front_peak)
|
||||
_add_quad(vertices, normals, front_peak, back_peak, back_a, front_a)
|
||||
return _array_mesh(vertices, normals)
|
||||
|
||||
func _make_right_gable_wall_mesh() -> ArrayMesh:
|
||||
var vertices := PackedVector3Array()
|
||||
var normals := PackedVector3Array()
|
||||
var base_points := _get_centered_gable_base() if center_align else PackedVector3Array([custom_points[0], custom_points[1]])
|
||||
var a: Vector3 = base_points[0]
|
||||
var b: Vector3 = base_points[1]
|
||||
var direction := (b - a).normalized()
|
||||
var side := Vector3(-direction.z, 0.0, direction.x).normalized() * thickness * 0.5
|
||||
var peak := b + Vector3.UP * rise
|
||||
var front_a := a + side
|
||||
var front_b := b + side
|
||||
var front_peak := peak + side
|
||||
var back_a := a - side
|
||||
var back_b := b - side
|
||||
var back_peak := peak - side
|
||||
_add_tri(vertices, normals, front_a, front_b, front_peak)
|
||||
_add_tri(vertices, normals, back_peak, back_b, back_a)
|
||||
_add_quad(vertices, normals, front_a, back_a, back_b, front_b)
|
||||
_add_quad(vertices, normals, front_b, back_b, back_peak, front_peak)
|
||||
_add_quad(vertices, normals, front_peak, back_peak, back_a, front_a)
|
||||
return _array_mesh(vertices, normals)
|
||||
|
||||
func _make_roof_mesh() -> ArrayMesh:
|
||||
if piece_type == PieceType.ROOF_SHED and custom_points.size() == 2:
|
||||
return _make_shed_roof_mesh()
|
||||
if custom_points.size() >= 4:
|
||||
return _make_oriented_roof_mesh()
|
||||
var vertices := PackedVector3Array()
|
||||
var normals := PackedVector3Array()
|
||||
var first: Vector3 = custom_points[0]
|
||||
var second: Vector3 = custom_points[1]
|
||||
var min_x := minf(first.x, second.x)
|
||||
var max_x := maxf(first.x, second.x)
|
||||
var min_z := minf(first.z, second.z)
|
||||
var max_z := maxf(first.z, second.z)
|
||||
var span_x := max_x - min_x
|
||||
var span_z := max_z - min_z
|
||||
if span_x < 0.02 or span_z < 0.02:
|
||||
return _array_mesh(vertices, normals)
|
||||
var panels: Array = []
|
||||
if piece_type == PieceType.ROOF_GABLE:
|
||||
if span_x <= span_z:
|
||||
var ridge_x := (min_x + max_x) * 0.5
|
||||
panels.append([Vector3(min_x, 0.0, min_z), Vector3(min_x, 0.0, max_z), Vector3(ridge_x, rise, max_z), Vector3(ridge_x, rise, min_z)])
|
||||
panels.append([Vector3(ridge_x, rise, min_z), Vector3(ridge_x, rise, max_z), Vector3(max_x, 0.0, max_z), Vector3(max_x, 0.0, min_z)])
|
||||
else:
|
||||
var ridge_z := (min_z + max_z) * 0.5
|
||||
panels.append([Vector3(min_x, 0.0, min_z), Vector3(max_x, 0.0, min_z), Vector3(max_x, rise, ridge_z), Vector3(min_x, rise, ridge_z)])
|
||||
panels.append([Vector3(min_x, rise, ridge_z), Vector3(max_x, rise, ridge_z), Vector3(max_x, 0.0, max_z), Vector3(min_x, 0.0, max_z)])
|
||||
else:
|
||||
if span_x <= span_z:
|
||||
var low_x := first.x
|
||||
var high_x := second.x
|
||||
panels.append([Vector3(low_x, 0.0, min_z), Vector3(low_x, 0.0, max_z), Vector3(high_x, rise, max_z), Vector3(high_x, rise, min_z)])
|
||||
else:
|
||||
var low_z := first.z
|
||||
var high_z := second.z
|
||||
panels.append([Vector3(min_x, 0.0, low_z), Vector3(max_x, 0.0, low_z), Vector3(max_x, rise, high_z), Vector3(min_x, rise, high_z)])
|
||||
for panel in panels:
|
||||
_append_solid_panel(vertices, normals, panel)
|
||||
return _array_mesh(vertices, normals)
|
||||
|
||||
func _make_shed_roof_mesh() -> ArrayMesh:
|
||||
var vertices := PackedVector3Array()
|
||||
var normals := PackedVector3Array()
|
||||
var low: Vector3 = custom_points[0]
|
||||
var high: Vector3 = custom_points[1]
|
||||
var slope := high - low
|
||||
var horizontal := Vector3(slope.x, 0.0, slope.z)
|
||||
if horizontal.length_squared() < 0.0001 or roof_width <= 0.0:
|
||||
return _array_mesh(vertices, normals)
|
||||
var across := Vector3(horizontal.z, 0.0, -horizontal.x).normalized() * roof_width * 0.5
|
||||
var panel := [low - across, low + across, high + across, high - across]
|
||||
_append_solid_panel(vertices, normals, panel)
|
||||
return _array_mesh(vertices, normals)
|
||||
|
||||
func _make_oriented_roof_mesh() -> ArrayMesh:
|
||||
var vertices := PackedVector3Array()
|
||||
var normals := PackedVector3Array()
|
||||
var p0: Vector3 = custom_points[0]
|
||||
var p1: Vector3 = custom_points[1]
|
||||
var p2: Vector3 = custom_points[2]
|
||||
var p3: Vector3 = custom_points[3]
|
||||
var edge_01 := Vector2(p1.x - p0.x, p1.z - p0.z).length()
|
||||
var edge_12 := Vector2(p2.x - p1.x, p2.z - p1.z).length()
|
||||
var panels: Array = []
|
||||
if piece_type == PieceType.ROOF_GABLE:
|
||||
if edge_01 <= edge_12:
|
||||
var ridge_01 := (p0 + p1) * 0.5 + Vector3.UP * rise
|
||||
var ridge_23 := (p2 + p3) * 0.5 + Vector3.UP * rise
|
||||
panels.append([p0, p3, ridge_23, ridge_01])
|
||||
panels.append([ridge_01, ridge_23, p2, p1])
|
||||
else:
|
||||
var ridge_12 := (p1 + p2) * 0.5 + Vector3.UP * rise
|
||||
var ridge_30 := (p3 + p0) * 0.5 + Vector3.UP * rise
|
||||
panels.append([p0, p1, ridge_12, ridge_30])
|
||||
panels.append([ridge_30, ridge_12, p2, p3])
|
||||
elif piece_type == PieceType.ROOF_PYRAMID:
|
||||
var peak := (p0 + p1 + p2 + p3) * 0.25 + Vector3.UP * rise
|
||||
panels.append([p0, p1, peak])
|
||||
panels.append([p1, p2, peak])
|
||||
panels.append([p2, p3, peak])
|
||||
panels.append([p3, p0, peak])
|
||||
else:
|
||||
# The four points define the low and high edges. Keep their centers
|
||||
# fixed when adjusting both edge widths in the Inspector.
|
||||
var base_width := Vector2(p1.x - p0.x, p1.z - p0.z).length()
|
||||
if base_width > 0.001 and roof_width > 0.0:
|
||||
var direction := Vector3(p1.x - p0.x, 0.0, p1.z - p0.z).normalized()
|
||||
var low_center := (p0 + p1) * 0.5
|
||||
var high_center := (p2 + p3) * 0.5
|
||||
var half_width := roof_width * 0.5
|
||||
panels.append([
|
||||
low_center - direction * half_width,
|
||||
low_center + direction * half_width,
|
||||
high_center + direction * half_width,
|
||||
high_center - direction * half_width,
|
||||
])
|
||||
else:
|
||||
panels.append([p0, p1, p2, p3])
|
||||
for panel in panels:
|
||||
_append_solid_panel(vertices, normals, panel)
|
||||
return _array_mesh(vertices, normals)
|
||||
|
||||
func _make_stair_mesh() -> ArrayMesh:
|
||||
var vertices := PackedVector3Array()
|
||||
var normals := PackedVector3Array()
|
||||
var start: Vector3 = custom_points[0]
|
||||
var finish: Vector3 = custom_points[1]
|
||||
var horizontal := Vector3(finish.x - start.x, 0.0, finish.z - start.z)
|
||||
var run := horizontal.length()
|
||||
var rise_amount := finish.y - start.y
|
||||
if run < 0.05 or rise_amount <= 0.05 or stair_count < 1 or stair_width <= 0.0:
|
||||
return _array_mesh(vertices, normals)
|
||||
var forward := horizontal / run
|
||||
var width_axis := Vector3(-forward.z, 0.0, forward.x) * stair_width * 0.5
|
||||
var profile := PackedVector2Array([Vector2(0.0, 0.0), Vector2(run, 0.0), Vector2(run, rise_amount)])
|
||||
for step_index in range(stair_count - 1, -1, -1):
|
||||
var tread_start := run * float(step_index) / stair_count
|
||||
var tread_end := run * float(step_index + 1) / stair_count
|
||||
var tread_height := rise_amount * float(step_index + 1) / stair_count
|
||||
profile.append(Vector2(tread_start, tread_height))
|
||||
if step_index > 0:
|
||||
profile.append(Vector2(tread_start, rise_amount * float(step_index) / stair_count))
|
||||
var triangulation := Geometry2D.triangulate_polygon(profile)
|
||||
for side_sign in [-1.0, 1.0]:
|
||||
for triangle_index in range(0, triangulation.size(), 3):
|
||||
var a := profile[triangulation[triangle_index]]
|
||||
var b := profile[triangulation[triangle_index + 1]]
|
||||
var c := profile[triangulation[triangle_index + 2]]
|
||||
var point_a: Vector3 = start + forward * a.x + Vector3.UP * a.y + width_axis * side_sign
|
||||
var point_b: Vector3 = start + forward * b.x + Vector3.UP * b.y + width_axis * side_sign
|
||||
var point_c: Vector3 = start + forward * c.x + Vector3.UP * c.y + width_axis * side_sign
|
||||
if side_sign > 0.0:
|
||||
_add_tri(vertices, normals, point_a, point_b, point_c)
|
||||
else:
|
||||
_add_tri(vertices, normals, point_c, point_b, point_a)
|
||||
for profile_index in range(profile.size()):
|
||||
var next_index := (profile_index + 1) % profile.size()
|
||||
var a := profile[profile_index]
|
||||
var b := profile[next_index]
|
||||
var point_a_left := start + forward * a.x + Vector3.UP * a.y - width_axis
|
||||
var point_b_left := start + forward * b.x + Vector3.UP * b.y - width_axis
|
||||
var point_b_right := start + forward * b.x + Vector3.UP * b.y + width_axis
|
||||
var point_a_right := start + forward * a.x + Vector3.UP * a.y + width_axis
|
||||
_add_quad(vertices, normals, point_a_left, point_b_left, point_b_right, point_a_right)
|
||||
return _array_mesh(vertices, normals)
|
||||
|
||||
func _make_fence_mesh() -> ArrayMesh:
|
||||
var vertices := PackedVector3Array()
|
||||
var normals := PackedVector3Array()
|
||||
var start: Vector3 = custom_points[0]
|
||||
var finish: Vector3 = custom_points[1]
|
||||
var path := finish - start
|
||||
var path_length := path.length()
|
||||
if path_length < 0.05 or fence_height <= 0.0:
|
||||
return _array_mesh(vertices, normals)
|
||||
var path_axis := path / path_length
|
||||
var post_count := fence_divisions + 2
|
||||
var post_positions: Array[Vector3] = []
|
||||
for post_index in range(post_count):
|
||||
var base_position := start.lerp(finish, float(post_index) / float(post_count - 1))
|
||||
post_positions.append(base_position)
|
||||
var side_axis := path_axis.cross(Vector3.UP).normalized()
|
||||
if side_axis.length_squared() < 0.001:
|
||||
side_axis = Vector3.FORWARD
|
||||
_append_oriented_box(vertices, normals, base_position + Vector3.UP * fence_height * 0.5, path_axis, Vector3.UP, side_axis, Vector3(thickness, fence_height, thickness))
|
||||
for section_index in range(post_positions.size() - 1):
|
||||
var section_start := post_positions[section_index]
|
||||
var section_end := post_positions[section_index + 1]
|
||||
var section_axis := (section_end - section_start).normalized()
|
||||
var rail_up := Vector3.UP - section_axis * section_axis.dot(Vector3.UP)
|
||||
if rail_up.length_squared() < 0.001:
|
||||
rail_up = Vector3.FORWARD - section_axis * section_axis.dot(Vector3.FORWARD)
|
||||
rail_up = rail_up.normalized()
|
||||
var rail_side := section_axis.cross(rail_up).normalized()
|
||||
var section_length := section_start.distance_to(section_end)
|
||||
for height_ratio in [0.28, 0.78]:
|
||||
var rail_center: Vector3 = (section_start + section_end) * 0.5 + Vector3.UP * fence_height * height_ratio
|
||||
_append_oriented_box(vertices, normals, rail_center, section_axis, rail_up, rail_side, Vector3(section_length, thickness, thickness))
|
||||
return _array_mesh(vertices, normals)
|
||||
|
||||
func _append_oriented_box(vertices: PackedVector3Array, normals: PackedVector3Array, center: Vector3, axis_x: Vector3, axis_y: Vector3, axis_z: Vector3, dimensions: Vector3) -> void:
|
||||
var x := axis_x.normalized() * dimensions.x * 0.5
|
||||
var y := axis_y.normalized() * dimensions.y * 0.5
|
||||
var z := axis_z.normalized() * dimensions.z * 0.5
|
||||
var nnn := center - x - y - z
|
||||
var pnn := center + x - y - z
|
||||
var ppn := center + x + y - z
|
||||
var npn := center - x + y - z
|
||||
var nnp := center - x - y + z
|
||||
var pnp := center + x - y + z
|
||||
var ppp := center + x + y + z
|
||||
var npp := center - x + y + z
|
||||
_add_quad(vertices, normals, nnp, pnp, ppp, npp)
|
||||
_add_quad(vertices, normals, pnn, nnn, npn, ppn)
|
||||
_add_quad(vertices, normals, npp, ppp, ppn, npn)
|
||||
_add_quad(vertices, normals, nnn, pnn, pnp, nnp)
|
||||
_add_quad(vertices, normals, nnn, nnp, npp, npn)
|
||||
_add_quad(vertices, normals, pnp, pnn, ppn, ppp)
|
||||
|
||||
func _get_centered_gable_base() -> PackedVector3Array:
|
||||
var selected_a := to_global(custom_points[0])
|
||||
var selected_b := to_global(custom_points[1])
|
||||
var search_root: Node = get_parent()
|
||||
while search_root != null and not search_root is ModularBuilderPieceGeometry:
|
||||
search_root = search_root.get_parent()
|
||||
if search_root == null:
|
||||
return PackedVector3Array([custom_points[0], custom_points[1]])
|
||||
var walls: Array[ModularBuilderPieceGeometry] = []
|
||||
_collect_centering_walls(search_root, walls)
|
||||
var centered_a := selected_a
|
||||
var centered_b := selected_b
|
||||
var nearest_a := INF
|
||||
var nearest_b := INF
|
||||
for wall in walls:
|
||||
if wall.custom_points.size() < 2:
|
||||
continue
|
||||
var wall_a := wall.to_global(wall.custom_points[0] + Vector3.UP * wall.unit_size)
|
||||
var wall_b := wall.to_global(wall.custom_points[1] + Vector3.UP * wall.unit_size)
|
||||
var tolerance: float = wall.thickness + 0.04
|
||||
for endpoint in [wall_a, wall_b]:
|
||||
var distance_a := selected_a.distance_to(endpoint)
|
||||
if distance_a < nearest_a and distance_a <= tolerance:
|
||||
nearest_a = distance_a
|
||||
centered_a = endpoint
|
||||
var distance_b := selected_b.distance_to(endpoint)
|
||||
if distance_b < nearest_b and distance_b <= tolerance:
|
||||
nearest_b = distance_b
|
||||
centered_b = endpoint
|
||||
if nearest_a < INF and nearest_b < INF and centered_a.distance_to(centered_b) >= 0.02:
|
||||
return PackedVector3Array([to_local(centered_a), to_local(centered_b)])
|
||||
return PackedVector3Array([custom_points[0], custom_points[1]])
|
||||
|
||||
func _collect_centering_walls(node: Node, walls: Array[ModularBuilderPieceGeometry]) -> void:
|
||||
if node is ModularBuilderPieceGeometry and node.piece_type == PieceType.WALL:
|
||||
walls.append(node)
|
||||
for child in node.get_children():
|
||||
_collect_centering_walls(child, walls)
|
||||
|
||||
func _append_solid_panel(vertices: PackedVector3Array, normals: PackedVector3Array, panel: Array) -> void:
|
||||
if panel.size() < 3:
|
||||
return
|
||||
var p0: Vector3 = panel[0]
|
||||
var p1: Vector3 = panel[1]
|
||||
var p2: Vector3 = panel[2]
|
||||
var normal: Vector3 = (p1 - p0).cross(p2 - p0).normalized()
|
||||
if normal.is_zero_approx():
|
||||
return
|
||||
var half_depth: Vector3 = normal * thickness * 0.5
|
||||
var front: Array[Vector3] = []
|
||||
var back: Array[Vector3] = []
|
||||
for point in panel:
|
||||
front.append(point + half_depth)
|
||||
back.append(point - half_depth)
|
||||
for i in range(1, panel.size() - 1):
|
||||
_add_tri(vertices, normals, front[0], front[i], front[i + 1])
|
||||
_add_tri(vertices, normals, back[i + 1], back[i], back[0])
|
||||
for i in range(panel.size()):
|
||||
var next := (i + 1) % panel.size()
|
||||
_add_quad(vertices, normals, front[i], back[i], back[next], front[next])
|
||||
|
||||
func _make_custom_wall_mesh() -> ArrayMesh:
|
||||
var vertices := PackedVector3Array()
|
||||
var normals := PackedVector3Array()
|
||||
var wall_points: PackedVector3Array = _get_centered_wall_points() if center_align else custom_points
|
||||
var a: Vector3 = wall_points[0]
|
||||
var b: Vector3 = wall_points[1]
|
||||
var direction := (b - a).normalized()
|
||||
var length := a.distance_to(b)
|
||||
var side := Vector3(-direction.z, 0.0, direction.x).normalized() * thickness * 0.5
|
||||
var height := Vector3.UP * unit_size
|
||||
var openings: Array[PackedVector2Array] = []
|
||||
for child in get_children():
|
||||
if _is_detail_node(child) and int(child.get("detail_type")) != DETAIL_TYPE_HATCH and int(child.get("detail_type")) != DETAIL_TYPE_PILLAR:
|
||||
var detail := child as Node3D
|
||||
var center := Vector2((detail.position - a).dot(direction), detail.position.y - a.y)
|
||||
var axis_x := Vector2(detail.transform.basis.x.dot(direction), detail.transform.basis.x.y).normalized()
|
||||
var axis_y := Vector2(detail.transform.basis.y.dot(direction), detail.transform.basis.y.y).normalized()
|
||||
var opening := PackedVector2Array([
|
||||
center - axis_x * float(detail.get("width")) * 0.5 - axis_y * float(detail.get("height")) * 0.5,
|
||||
center + axis_x * float(detail.get("width")) * 0.5 - axis_y * float(detail.get("height")) * 0.5,
|
||||
center + axis_x * float(detail.get("width")) * 0.5 + axis_y * float(detail.get("height")) * 0.5,
|
||||
center - axis_x * float(detail.get("width")) * 0.5 + axis_y * float(detail.get("height")) * 0.5
|
||||
])
|
||||
var wall_rect := PackedVector2Array([Vector2(0.0, 0.0), Vector2(length, 0.0), Vector2(length, unit_size), Vector2(0.0, unit_size)])
|
||||
for clipped_opening in Geometry2D.intersect_polygons(opening, wall_rect):
|
||||
if clipped_opening.size() >= 3:
|
||||
openings.append(clipped_opening)
|
||||
var xs: Array[float] = [0.0, length]
|
||||
var ys: Array[float] = [0.0, unit_size]
|
||||
for opening in openings:
|
||||
for point in opening:
|
||||
xs.append(clampf(point.x, 0.0, length))
|
||||
ys.append(clampf(point.y, 0.0, unit_size))
|
||||
xs.sort()
|
||||
ys.sort()
|
||||
for xi in range(xs.size() - 1):
|
||||
for yi in range(ys.size() - 1):
|
||||
var u0: float = xs[xi]
|
||||
var u1: float = xs[xi + 1]
|
||||
var v0: float = ys[yi]
|
||||
var v1: float = ys[yi + 1]
|
||||
var mid := Vector2((u0 + u1) * 0.5, (v0 + v1) * 0.5)
|
||||
var cell := PackedVector2Array([Vector2(u0, v0), Vector2(u1, v0), Vector2(u1, v1), Vector2(u0, v1)])
|
||||
var remaining: Array[PackedVector2Array] = [cell]
|
||||
for opening in openings:
|
||||
var next_remaining: Array[PackedVector2Array] = []
|
||||
for polygon in remaining:
|
||||
for clipped in Geometry2D.clip_polygons(polygon, opening):
|
||||
if clipped.size() >= 3:
|
||||
next_remaining.append(clipped)
|
||||
remaining = next_remaining
|
||||
for polygon in remaining:
|
||||
var indices := Geometry2D.triangulate_polygon(polygon)
|
||||
for ti in range(0, indices.size(), 3):
|
||||
var p0: Vector2 = polygon[indices[ti]]
|
||||
var p1: Vector2 = polygon[indices[ti + 1]]
|
||||
var p2: Vector2 = polygon[indices[ti + 2]]
|
||||
var f0 := a + direction * p0.x + Vector3.UP * p0.y
|
||||
var f1 := a + direction * p1.x + Vector3.UP * p1.y
|
||||
var f2 := a + direction * p2.x + Vector3.UP * p2.y
|
||||
_add_tri(vertices, normals, f0 + side, f1 + side, f2 + side)
|
||||
_add_tri(vertices, normals, f2 - side, f1 - side, f0 - side)
|
||||
# Close the wall body at its ends, top, and base.
|
||||
_add_quad(vertices, normals, a - side, a + side, a + side + height, a - side + height)
|
||||
_add_quad(vertices, normals, b + side, b - side, b - side + height, b + side + height)
|
||||
_add_quad(vertices, normals, a + side + height, b + side + height, b - side + height, a - side + height)
|
||||
_add_quad(vertices, normals, a - side, b - side, b + side, a + side)
|
||||
for opening in openings:
|
||||
for edge_index in range(opening.size()):
|
||||
var p0 := opening[edge_index]
|
||||
var p1 := opening[(edge_index + 1) % opening.size()]
|
||||
var a0 := a + direction * p0.x + Vector3.UP * p0.y
|
||||
var a1 := a + direction * p1.x + Vector3.UP * p1.y
|
||||
_add_quad(vertices, normals, a0 + side, a0 - side, a1 - side, a1 + side)
|
||||
return _array_mesh(vertices, normals)
|
||||
|
||||
func _get_centered_wall_points() -> PackedVector3Array:
|
||||
if custom_points.size() < 2:
|
||||
return custom_points
|
||||
var selected_a := to_global(custom_points[0])
|
||||
var selected_b := to_global(custom_points[1])
|
||||
var search_root: Node = get_parent()
|
||||
while search_root != null and not search_root is ModularBuilderPieceGeometry:
|
||||
search_root = search_root.get_parent()
|
||||
if search_root == null:
|
||||
return custom_points
|
||||
var walls: Array[ModularBuilderPieceGeometry] = []
|
||||
_collect_centering_walls(search_root, walls)
|
||||
var centered_a := selected_a
|
||||
var centered_b := selected_b
|
||||
var nearest_a := INF
|
||||
var nearest_b := INF
|
||||
for wall in walls:
|
||||
if wall == self or wall.custom_points.size() < 2:
|
||||
continue
|
||||
var direction := (wall.custom_points[1] - wall.custom_points[0]).normalized()
|
||||
var side := Vector3(-direction.z, 0.0, direction.x).normalized() * wall.thickness * 0.5
|
||||
for endpoint in wall.custom_points:
|
||||
var center := wall.to_global(endpoint + Vector3.UP * wall.unit_size)
|
||||
for surface_corner in [center + side, center - side]:
|
||||
var distance_a := selected_a.distance_to(surface_corner)
|
||||
if distance_a < nearest_a and distance_a <= wall.thickness + 0.04:
|
||||
nearest_a = distance_a
|
||||
centered_a = center
|
||||
var distance_b := selected_b.distance_to(surface_corner)
|
||||
if distance_b < nearest_b and distance_b <= wall.thickness + 0.04:
|
||||
nearest_b = distance_b
|
||||
centered_b = center
|
||||
if nearest_a < INF and nearest_b < INF and centered_a.distance_to(centered_b) >= 0.02:
|
||||
return PackedVector3Array([to_local(centered_a), to_local(centered_b)])
|
||||
return custom_points
|
||||
|
||||
func _make_custom_floor_mesh() -> ArrayMesh:
|
||||
var polygon: Array[Vector2] = []
|
||||
for point in custom_points:
|
||||
polygon.append(Vector2(point.x, point.z))
|
||||
var hatch_mesh := _make_hatch_surface_mesh(polygon, custom_points[0].y, custom_points[0].y - thickness)
|
||||
if hatch_mesh != null:
|
||||
return hatch_mesh
|
||||
var vertices := PackedVector3Array()
|
||||
var normals := PackedVector3Array()
|
||||
var points := custom_points
|
||||
var bottom: Array[Vector3] = []
|
||||
for point in points:
|
||||
bottom.append(point - Vector3.UP * thickness)
|
||||
for i in range(1, points.size() - 1):
|
||||
_add_tri(vertices, normals, points[0], points[i + 1], points[i])
|
||||
_add_tri(vertices, normals, bottom[0], bottom[i], bottom[i + 1])
|
||||
for i in range(points.size()):
|
||||
var j := (i + 1) % points.size()
|
||||
_add_quad(vertices, normals, bottom[i], bottom[j], points[j], points[i])
|
||||
return _array_mesh(vertices, normals)
|
||||
|
||||
func _make_hatch_surface_mesh(polygon: Array[Vector2], top_y: float, bottom_y: float) -> ArrayMesh:
|
||||
var openings: Array[PackedVector2Array] = []
|
||||
for child in get_children():
|
||||
if _is_detail_node(child) and int(child.get("detail_type")) == DETAIL_TYPE_HATCH:
|
||||
var detail := child as Node3D
|
||||
var center := Vector2(detail.position.x, detail.position.z)
|
||||
var axis_x := Vector2(detail.transform.basis.x.x, detail.transform.basis.x.z).normalized()
|
||||
var axis_y := Vector2(detail.transform.basis.z.x, detail.transform.basis.z.z).normalized()
|
||||
var opening := PackedVector2Array([
|
||||
center - axis_x * float(detail.get("width")) * 0.5 - axis_y * float(detail.get("height")) * 0.5,
|
||||
center + axis_x * float(detail.get("width")) * 0.5 - axis_y * float(detail.get("height")) * 0.5,
|
||||
center + axis_x * float(detail.get("width")) * 0.5 + axis_y * float(detail.get("height")) * 0.5,
|
||||
center - axis_x * float(detail.get("width")) * 0.5 + axis_y * float(detail.get("height")) * 0.5
|
||||
])
|
||||
openings.append(opening)
|
||||
if openings.is_empty() or polygon.size() < 3:
|
||||
return null
|
||||
var min_x := polygon[0].x
|
||||
var max_x := polygon[0].x
|
||||
var min_z := polygon[0].y
|
||||
var max_z := polygon[0].y
|
||||
var xs: Array[float] = []
|
||||
var zs: Array[float] = []
|
||||
for point in polygon:
|
||||
min_x = minf(min_x, point.x)
|
||||
max_x = maxf(max_x, point.x)
|
||||
min_z = minf(min_z, point.y)
|
||||
max_z = maxf(max_z, point.y)
|
||||
xs.append(point.x)
|
||||
zs.append(point.y)
|
||||
for opening in openings:
|
||||
for point in opening:
|
||||
xs.append(clampf(point.x, min_x, max_x))
|
||||
zs.append(clampf(point.y, min_z, max_z))
|
||||
xs.sort()
|
||||
zs.sort()
|
||||
var vertices := PackedVector3Array()
|
||||
var normals := PackedVector3Array()
|
||||
var source_polygon := PackedVector2Array()
|
||||
for point in polygon:
|
||||
source_polygon.append(point)
|
||||
for xi in range(xs.size() - 1):
|
||||
for zi in range(zs.size() - 1):
|
||||
var x0: float = xs[xi]
|
||||
var x1: float = xs[xi + 1]
|
||||
var z0: float = zs[zi]
|
||||
var z1: float = zs[zi + 1]
|
||||
if x1 - x0 < 0.0001 or z1 - z0 < 0.0001:
|
||||
continue
|
||||
var cell := PackedVector2Array([Vector2(x0, z0), Vector2(x1, z0), Vector2(x1, z1), Vector2(x0, z1)])
|
||||
var remaining: Array[PackedVector2Array] = []
|
||||
for clipped_surface in Geometry2D.intersect_polygons(source_polygon, cell):
|
||||
remaining.append(clipped_surface)
|
||||
for opening in openings:
|
||||
var next_remaining: Array[PackedVector2Array] = []
|
||||
for surface_polygon in remaining:
|
||||
for clipped_surface in Geometry2D.clip_polygons(surface_polygon, opening):
|
||||
if clipped_surface.size() >= 3:
|
||||
next_remaining.append(clipped_surface)
|
||||
remaining = next_remaining
|
||||
for clipped_surface in remaining:
|
||||
var triangulated := Geometry2D.triangulate_polygon(clipped_surface)
|
||||
for ti in range(0, triangulated.size(), 3):
|
||||
var a: Vector2 = clipped_surface[triangulated[ti]]
|
||||
var b: Vector2 = clipped_surface[triangulated[ti + 1]]
|
||||
var c: Vector2 = clipped_surface[triangulated[ti + 2]]
|
||||
_add_tri(vertices, normals, Vector3(a.x, top_y, a.y), Vector3(c.x, top_y, c.y), Vector3(b.x, top_y, b.y))
|
||||
_add_tri(vertices, normals, Vector3(a.x, bottom_y, a.y), Vector3(b.x, bottom_y, b.y), Vector3(c.x, bottom_y, c.y))
|
||||
for i in range(polygon.size()):
|
||||
var j := (i + 1) % polygon.size()
|
||||
var a := polygon[i]
|
||||
var b := polygon[j]
|
||||
_add_quad(vertices, normals, Vector3(a.x, bottom_y, a.y), Vector3(b.x, bottom_y, b.y), Vector3(b.x, top_y, b.y), Vector3(a.x, top_y, a.y))
|
||||
for opening in openings:
|
||||
var visible_edges := Geometry2D.intersect_polygons(opening, source_polygon)
|
||||
for visible_opening in visible_edges:
|
||||
for edge_index in range(visible_opening.size()):
|
||||
var p0 := visible_opening[edge_index]
|
||||
var p1 := visible_opening[(edge_index + 1) % visible_opening.size()]
|
||||
_add_quad(vertices, normals, Vector3(p0.x, bottom_y, p0.y), Vector3(p0.x, top_y, p0.y), Vector3(p1.x, top_y, p1.y), Vector3(p1.x, bottom_y, p1.y))
|
||||
return _array_mesh(vertices, normals)
|
||||
|
||||
func _is_detail_node(node: Node) -> bool:
|
||||
if not node is Node3D or node.get_script() == null:
|
||||
return false
|
||||
return node.get_script().resource_path == DETAIL_SCRIPT_PATH
|
||||
|
||||
func _make_custom_foundation_mesh() -> ArrayMesh:
|
||||
var polygon: Array[Vector2] = []
|
||||
for point in custom_points:
|
||||
polygon.append(Vector2(point.x, point.z))
|
||||
var bottom_y := -thickness * 0.5 if centered_origin else 0.0
|
||||
var top_y := thickness * 0.5 if centered_origin else thickness
|
||||
var hatch_mesh := _make_hatch_surface_mesh(polygon, top_y, bottom_y)
|
||||
if hatch_mesh != null:
|
||||
return hatch_mesh
|
||||
var vertices := PackedVector3Array()
|
||||
var normals := PackedVector3Array()
|
||||
for i in range(1, custom_points.size() - 1):
|
||||
var a := custom_points[0]
|
||||
var b := custom_points[i]
|
||||
var c := custom_points[i + 1]
|
||||
_add_tri(vertices, normals, Vector3(a.x, top_y, a.z), Vector3(c.x, top_y, c.z), Vector3(b.x, top_y, b.z))
|
||||
_add_tri(vertices, normals, Vector3(a.x, bottom_y, a.z), Vector3(b.x, bottom_y, b.z), Vector3(c.x, bottom_y, c.z))
|
||||
for i in range(custom_points.size()):
|
||||
var j := (i + 1) % custom_points.size()
|
||||
var a := custom_points[i]
|
||||
var b := custom_points[j]
|
||||
_add_quad(vertices, normals, Vector3(a.x, bottom_y, a.z), Vector3(b.x, bottom_y, b.z), Vector3(b.x, top_y, b.z), Vector3(a.x, top_y, a.z))
|
||||
return _array_mesh(vertices, normals)
|
||||
|
||||
func _add_quad(v: PackedVector3Array, n: PackedVector3Array, a: Vector3, b: Vector3, c: Vector3, d: Vector3) -> void:
|
||||
_add_tri(v, n, a, b, c)
|
||||
_add_tri(v, n, a, c, d)
|
||||
|
||||
func _array_mesh(v: PackedVector3Array, n: PackedVector3Array) -> ArrayMesh:
|
||||
var arrays: Array = []
|
||||
arrays.resize(Mesh.ARRAY_MAX)
|
||||
arrays[Mesh.ARRAY_VERTEX] = v
|
||||
arrays[Mesh.ARRAY_NORMAL] = n
|
||||
var result := ArrayMesh.new()
|
||||
result.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, arrays)
|
||||
return result
|
||||
|
||||
func _add_tri(v: PackedVector3Array, n: PackedVector3Array, a: Vector3, b: Vector3, c: Vector3) -> void:
|
||||
var normal := (b - a).cross(c - a).normalized()
|
||||
v.append(a)
|
||||
v.append(b)
|
||||
v.append(c)
|
||||
n.append(normal)
|
||||
n.append(normal)
|
||||
n.append(normal)
|
||||
# Also generate reversed faces to show both sides.
|
||||
# This keeps floors and foundations visible from below with any material.
|
||||
v.append(c)
|
||||
v.append(b)
|
||||
v.append(a)
|
||||
n.append(-normal)
|
||||
n.append(-normal)
|
||||
n.append(-normal)
|
||||
|
|
@ -1 +0,0 @@
|
|||
uid://dp1333xlylabf
|
||||
|
|
@ -133,8 +133,8 @@ func _export(oid: String, name_roh: String) -> void:
|
|||
if not editor_dir.is_empty():
|
||||
var img := await _thumbnail_bilden(mesh)
|
||||
if img != null:
|
||||
DirAccess.make_dir_recursive_absolute(editor_dir + "/library/thumbs")
|
||||
img.save_png(editor_dir + "/library/thumbs/" + oid + ".png")
|
||||
DirAccess.make_dir_recursive_absolute(editor_dir + "/core/thumbs")
|
||||
img.save_png(editor_dir + "/core/thumbs/" + oid + ".png")
|
||||
|
||||
# 6) Editor-Sync (Registry-Kopie; vorhandene Thumbnails bleiben stehen).
|
||||
var schritt4 := _lauf(objekt_tool, ["editor", oid])
|
||||
|
|
|
|||
1
core
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 5e98535a0afc83af4e4017806686a76af4913afd
|
||||
|
|
@ -19,7 +19,7 @@ Ein Bauteil ist ein **ganz normales Bibliotheks-Objekt** (`bau_*`, Kategorie
|
|||
und Server lesen dieselbe Datei.
|
||||
* Poly-Budget zählt wie bei jedem Objekt (`poly` = Dreiecke des Teils).
|
||||
|
||||
## Teile (Katalog: `src/editor/bau_katalog.gd`)
|
||||
## Teile (Katalog: `core/editor/bau_katalog.gd`)
|
||||
|
||||
| Gruppe | Teile |
|
||||
| --- | --- |
|
||||
|
|
@ -34,7 +34,7 @@ Ein Bauteil ist ein **ganz normales Bibliotheks-Objekt** (`bau_*`, Kategorie
|
|||
Fertige Pack-Objekte (Container, Hangar-Tore, Betonsperren) stehen NICHT im Bauen-Tab,
|
||||
sondern wie alle Objekte in der Objekt-Bibliothek unten.
|
||||
|
||||
## Snap (`src/editor/build_snap.gd`)
|
||||
## Snap (`core/editor/build_snap.gd`)
|
||||
|
||||
* **XZ:** Wände auf die nächste Zellkante — und zwar GANZ in die Zelle, in der die
|
||||
Maus ist (Außenseite bündig mit der Kante, kein Überhang, Ecken schließen ohne
|
||||
|
|
|
|||
|
|
@ -41,8 +41,8 @@ im Editor dann Adresse `127.0.0.1`) oder ein Reverse-Proxy mit https (Haken
|
|||
- **Server-Log** mit Filter.
|
||||
|
||||
## Code
|
||||
`src/server/` (AdminClient, ServerStore, AdminTexte, MapPush),
|
||||
`src/ui/panels/server_panel.gd`, `SvmapIO.to_signed_text`.
|
||||
`core/server/` (AdminClient, ServerStore, AdminTexte, MapPush),
|
||||
`core/ui/panels/server_panel.gd`, `SvmapIO.to_signed_text`.
|
||||
|
||||
## Tests
|
||||
`tests/test_server_sektion.gd` (Unit), `tests/run_server_sektion_e2e.sh`
|
||||
|
|
|
|||
|
|
@ -5,12 +5,12 @@ of truth** für alle Shortcut-Karten — FINALE Version nach allen drei Karten:
|
|||
Karte 1/3 (t_c46d31c2): Navigation, Auswahl, Löschen · Karte 2/3 (t_55257792):
|
||||
Objektmanipulation + Terrain · Karte 3/3 (t_11b5c25b): Datei & Undo,
|
||||
Werkzeugwechsel, Hilfe, Test. Das Kurzhilfe-Overlay im Editor (Taste **H**)
|
||||
zeigt dieselbe Tabelle (Quelle: `src/ui/help_text.gd`).
|
||||
zeigt dieselbe Tabelle (Quelle: `core/ui/help_text.gd`).
|
||||
|
||||
Konventionen (alle Karten):
|
||||
|
||||
- Tastaturcode-basiert: InputMap-Actions mit physischen `KEY_*`-Konstanten
|
||||
(`src/editor/shortcut_keys.gd`). Die physische Taste liegt unabhängig vom
|
||||
(`core/editor/shortcut_keys.gd`). Die physische Taste liegt unabhängig vom
|
||||
Tastaturlayout gleich — deutsches (QWERTZ) und Windows-Layout verhalten sich
|
||||
identisch, keine OS-Hardcodes (PLAN.md Plattform-Regel).
|
||||
- Jede Objekt-Operation = **EIN** ActionHistory-Eintrag (Strg+Z nimmt die
|
||||
|
|
|
|||
|
|
@ -1,240 +0,0 @@
|
|||
class_name SvmapWasser
|
||||
extends RefCounted
|
||||
## Wasser pro Map (Karte t_28fdef03) — SPIEGELGLEICHES Modul in Client UND
|
||||
## Map-Editor (Muster: library/terrain_arrays.gd, t_ab408127 — identischer
|
||||
## Pfad in beiden Repos, identischer Code; Repos bleiben entkoppelt).
|
||||
##
|
||||
## Sly-Entscheidungen 20.10.: Wasserlevel-Ansatz (EINE Höhe pro Map — Senken
|
||||
## unter der Höhe füllen sich automatisch), Wat-Trägheit (knietief, kein
|
||||
## Schwimmen), Ufer-Automatik (schlammiges Overlay knapp unter Wasserhöhe).
|
||||
##
|
||||
## Verantwortung dieses Moduls (Dictionary rein, Node out — wie SvmapTerrain):
|
||||
## - hat()/level(): optionales svmap-Feld `water_level` (float, y-Höhe in m).
|
||||
## Abwesenheit oder Fehltyp = KEIN Wasser (Legacy-Maps unverändert).
|
||||
## - baue(): EINE transparente Fläche auf Wasserhöhe über der ganzen Map
|
||||
## (1 Draw-Call, keine Geometrie-Wogen — Wellen NUR im Fragment-Shader).
|
||||
## - ufer_bild(): Tiefe-Feld (R8, depth = wasser − Terrainhöhe, geklemmt auf
|
||||
## tiefe_max) als Textur — der Shader liest daraus Ufer-Schaum + Flach-
|
||||
## Wasser-Transparenz, OHNE Screen-Space-Tricks.
|
||||
## - ufer_faktor()/matsch_anwenden(): Ufer-Automatik — Zellen knapp unter
|
||||
## Wasserhöhe bekommen den Matsch-Ton. BEWUSST nur eine abgeleitete Tönung
|
||||
## (kein gespeichertes Feld): die Material-Schicht bleibt malbar, der
|
||||
## Matsch liegt als Höhen-Regel drüber — Client UND Editor-Vorschau
|
||||
## rechnen IDENTISCH (dieselbe Datei).
|
||||
## - make_material(): dasselbe Material wie der Client (Identitäts-Vertrag
|
||||
## der Vorschau) — Shader-Pfad je Repo über SHADER_KANDIDATEN.
|
||||
##
|
||||
## KEINE echte Spiegelung/Brechung/SSR (bewusste Absage, Performance):
|
||||
## Spiegel-Impression = Skybox-Farbreflex (uniform) + Fresnel-Glanz.
|
||||
##
|
||||
## Wasserdistanz-Regel (Perf-Beweis-Plan): ferne Fragmente vereinfachen im
|
||||
## Shader selbst (kein Wellen-/Schaum-Aufwand) — keine Per-Frame-Logik nötig.
|
||||
|
||||
## Shader-Pfade je Repo (erster vorhandener gewinnt — Spiegel-Dateien sind
|
||||
## byteidentisch, siehe tools/sync_wasser.sh im Map-Editor).
|
||||
const SHADER_KANDIDATEN: Array[String] = [
|
||||
"res://shaders/wasser.gdshader", # scopedvr-client
|
||||
"res://src/viewport/wasser.gdshader", # scopedvr-map-editor (Spiegel)
|
||||
]
|
||||
|
||||
## Plausibilitätsbereich des svmap-Feldes `water_level` (Meter, y-Höhe).
|
||||
## GLEICHE Werte wie V18 im Match-Server (svmap_loader) und im Editor
|
||||
## (svmap_io) — nur Dokumentations-Konstante hier.
|
||||
const LEVEL_MIN := -5.0
|
||||
const LEVEL_MAX := 500.0
|
||||
|
||||
## Ufer-Bild: Tiefe in 0..tiefe_max m → 0..255 (R8). Mehr Tiefe braucht kein
|
||||
## Detail — Schaum lebt in den ersten Dezimetern, Transparenz in den ersten Metern.
|
||||
const TIEFE_MAX := 4.0
|
||||
|
||||
## Schaum-Band am Ufer (Meter Wassertiefe, in denen Schaum sichtbar ist).
|
||||
const SCHAUM_BAND := 0.35
|
||||
|
||||
## Matsch-Ring (Ufer-Automatik): Zellen, deren Terrainhöhe weniger als
|
||||
## MATSCH_HOEHE unter dem Wasserlevel liegt (bis MATSCH_UEBER leicht darüber,
|
||||
## damit die Wasserlinie selbst matschig ist), werden zum Matsch-Ton überblendet.
|
||||
const MATSCH_HOEHE := 0.55
|
||||
const MATSCH_UEBER := 0.06
|
||||
const MATSCH_FARBE := Color(0.34, 0.26, 0.18) # schlammiges Braun-Betonung
|
||||
|
||||
## Wetter-Farbkopplung (Entscheidung der Atmosphären-Karte): Wasser-Tint je
|
||||
## Preset. farbe_flach = Seicht-Wasser, farbe_tief = tiefe Mitte, reflex =
|
||||
## Skybox-Farbreflex (Himmelsfarbe des Presets), glanz = Glint-Stärke.
|
||||
## Schlüssel = Client-Wetter-Keys (WeatherPresets). Unbekannt → "mittag".
|
||||
const WETTER_WASSER := {
|
||||
"mittag": {
|
||||
"farbe_flach": Color(0.10, 0.30, 0.34),
|
||||
"farbe_tief": Color(0.02, 0.10, 0.15),
|
||||
"reflex": Color(0.72, 0.83, 0.92),
|
||||
"glanz": 1.0,
|
||||
},
|
||||
"abend": {
|
||||
"farbe_flach": Color(0.18, 0.26, 0.28),
|
||||
"farbe_tief": Color(0.04, 0.07, 0.11),
|
||||
"reflex": Color(0.95, 0.62, 0.38),
|
||||
"glanz": 1.2,
|
||||
},
|
||||
"regen": {
|
||||
"farbe_flach": Color(0.20, 0.24, 0.26),
|
||||
"farbe_tief": Color(0.06, 0.09, 0.11),
|
||||
"reflex": Color(0.55, 0.58, 0.62),
|
||||
"glanz": 0.35,
|
||||
},
|
||||
"nacht": {
|
||||
"farbe_flach": Color(0.02, 0.05, 0.09),
|
||||
"farbe_tief": Color(0.0, 0.015, 0.03),
|
||||
"reflex": Color(0.16, 0.22, 0.38),
|
||||
"glanz": 0.9,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
## Optionales svmap-Feld `water_level` vorhanden und brauchbar? Abwesenheit
|
||||
## ODER Fehltyp = kein Wasser (Legacy-Maps unverändert, Fehltyp toleriert).
|
||||
static func hat(data: Dictionary) -> bool:
|
||||
var v: Variant = data.get("water_level", null)
|
||||
return v is float or v is int
|
||||
|
||||
|
||||
## Wasserhöhe aus der Map (INF = kein Wasser).
|
||||
static func level(data: Dictionary) -> float:
|
||||
var v: Variant = data.get("water_level", null)
|
||||
if v is float or v is int:
|
||||
return float(v)
|
||||
return INF
|
||||
|
||||
|
||||
## Wasserfläche bauen. terrain = der geparste terrain-Block, wasser = Wasser-
|
||||
## Höhe (Meter), wetter = Preset-Key ("mittag"/"abend"/"regen"/"nacht").
|
||||
## Rückgabe: Node3D mit EINER transparenten Fläche — null, wenn kein Wasser
|
||||
## sinnvoll ist (kein Feld, kein Terrain, Wasserhöhe unter dem Tiefpunkt,
|
||||
## ungültige Maße). Die Senken "füllen sich" von selbst: alles unter der
|
||||
## Höhe liegt hinterher unter der Fläche.
|
||||
static func baue(terrain: Dictionary, wasser: float, wetter: String) -> Node3D:
|
||||
if not is_finite(wasser):
|
||||
return null
|
||||
var res := int(terrain.get("resolution", 0))
|
||||
var size_x := float(terrain.get("size_x_m", 0.0))
|
||||
var size_z := float(terrain.get("size_z_m", 0.0))
|
||||
if res < 2 or size_x <= 0.0 or size_z <= 0.0:
|
||||
return null
|
||||
var heights := _decode_heights(terrain)
|
||||
if heights.size() < res * res:
|
||||
return null
|
||||
var hmin := heights[0]
|
||||
for h in heights:
|
||||
if h < hmin:
|
||||
hmin = h
|
||||
if wasser <= hmin:
|
||||
return null # Wasserhöhe unter dem Tiefpunkt — nichts gefüllt.
|
||||
var root := Node3D.new()
|
||||
root.name = "Wasser"
|
||||
var mi := MeshInstance3D.new()
|
||||
mi.name = "WasserFlaeche"
|
||||
var plane := PlaneMesh.new()
|
||||
plane.size = Vector2(size_x, size_z)
|
||||
mi.mesh = plane
|
||||
mi.position = Vector3(0.0, wasser, 0.0)
|
||||
mi.material_override = make_material(wetter, ufer_bild(heights, res, wasser))
|
||||
root.add_child(mi)
|
||||
return root
|
||||
|
||||
|
||||
## Ufer-Tiefe-Bild (R8): Pixel = Terrainhöhe der Zelle, R-Wert = Tiefe unter
|
||||
## dem Wasserlevel (0 = Wasserlinie/Ufer, 255 = tiefe_max oder tiefer).
|
||||
## Identische Index-Konvention wie das Höhenfeld: (0,0) = −X/−Z-Ecke, x → +X,
|
||||
## z → +Z (svmap-Vertrag). Der PlaneMesh des Wassers überdeckt denselben
|
||||
## Bereich (zentriert, UV 0..1), der Shader sampelt direkt mit UV.
|
||||
static func ufer_bild(heights: PackedFloat32Array, res: int, wasser: float) -> Image:
|
||||
var img := Image.create(res, res, false, Image.FORMAT_R8)
|
||||
for z in res:
|
||||
for x in res:
|
||||
var d := wasser - heights[z * res + x] # Tiefe (negativ = Land)
|
||||
var v := int(round(clampf(d / TIEFE_MAX, 0.0, 1.0) * 255.0))
|
||||
img.set_pixel(x, z, Color8(v, 0, 0))
|
||||
return img
|
||||
|
||||
|
||||
## Ufer-Automatik (Matsch-Ring): Faktor 0 (Land/tief) … 1 (Uferstreifen).
|
||||
## Band = MATSCH_HOEHE unter bis MATSCH_UEBER über dem Wasserlevel, weich
|
||||
## (smoothstep) an beiden Kanten — kein Harter Pixel-Kantensprung.
|
||||
static func ufer_faktor(h: float, wasser: float) -> float:
|
||||
if not is_finite(wasser):
|
||||
return 0.0
|
||||
var d := wasser - h # Tiefe der Zelle (negativ = über Wasser)
|
||||
var oben := clampf((d + MATSCH_UEBER) / MATSCH_UEBER, 0.0, 1.0)
|
||||
if oben <= 0.0:
|
||||
return 0.0
|
||||
var unten := clampf(d / MATSCH_HOEHE, 0.0, 1.0)
|
||||
var f := minf(oben, 1.0 - unten * unten * (3.0 - 2.0 * unten))
|
||||
return clampf(f, 0.0, 1.0)
|
||||
|
||||
|
||||
## Matsch-Ton auf eine Terrain-Zellfarbe anwenden (Client UND Editor rufen
|
||||
## dieselbe Formel — Identität der Vorschau). faktor = ufer_faktor(...).
|
||||
## BEWUSST nur RGB: die Alpha der Terrain-Zellfarbe trägt die gepackte
|
||||
## Material-ID (m/N, Karte t_ab408127) — die darf der Matsch nie anfassen,
|
||||
## sonst landen die Zellen im Splat-Shader auf dem falschen Textur-Layer.
|
||||
static func matsch_anwenden(farbe: Color, faktor: float) -> Color:
|
||||
var gemischt := farbe.lerp(MATSCH_FARBE, faktor * 0.75) # 0.75: Ton bleibt sichtbar
|
||||
gemischt.a = farbe.a
|
||||
return gemischt
|
||||
|
||||
|
||||
## Wasser-Material (dasselbe im Client UND in der Editor-Vorschau —
|
||||
## Identitäts-Vertrag): Custom-Shader + Wetter-Tint + Ufer-Tiefen-Textur.
|
||||
## Fehlt der Shader (Frisch-Klon ohne Spiegel), fällt das Material auf ein
|
||||
## simples transparentes StandardMaterial zurück — Wasser bleibt sichtbar.
|
||||
static func make_material(wetter: String, ufer: Image = null) -> Material:
|
||||
var preset: Dictionary = WETTER_WASSER.get(wetter, WETTER_WASSER["mittag"])
|
||||
var shader := _shader_laden()
|
||||
if shader != null:
|
||||
var mat := ShaderMaterial.new()
|
||||
mat.shader = shader
|
||||
mat.set_shader_parameter("farbe_flach", preset["farbe_flach"])
|
||||
mat.set_shader_parameter("farbe_tief", preset["farbe_tief"])
|
||||
mat.set_shader_parameter("reflex", preset["reflex"])
|
||||
mat.set_shader_parameter("glanz", float(preset["glanz"]))
|
||||
if ufer != null:
|
||||
mat.set_shader_parameter("ufer_tex", ImageTexture.create_from_image(ufer))
|
||||
return mat
|
||||
# Fallback ohne Shader (Robustheit — Wasser bleibt sichtbar, nur ohne Wellen).
|
||||
var std := StandardMaterial3D.new()
|
||||
std.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA
|
||||
std.albedo_color = Color(preset["farbe_flach"], 0.6)
|
||||
std.roughness = 0.15
|
||||
std.metallic = 0.1
|
||||
return std
|
||||
|
||||
|
||||
## Shader aus den Repo-Pfaden laden (erster vorhandener gewinnt).
|
||||
static func _shader_laden() -> Shader:
|
||||
for pfad in SHADER_KANDIDATEN:
|
||||
if ResourceLoader.exists(pfad):
|
||||
var s := load(pfad)
|
||||
if s is Shader:
|
||||
return s
|
||||
return null
|
||||
|
||||
|
||||
## Höhenfeld dekodieren (R16, identische Formel wie SvmapTerrain/SvmapIO/
|
||||
## match-server — hier NOCHMAL lokal, damit dieses Spiegel-Modul von keinem
|
||||
## Repo-Skript abhängt; 15 Zeilen Duplikat gegen Repo-Kopplung getauscht).
|
||||
static func _decode_heights(terrain: Dictionary) -> PackedFloat32Array:
|
||||
var res := int(terrain.get("resolution", 0))
|
||||
var out := PackedFloat32Array()
|
||||
if res < 2:
|
||||
return out
|
||||
out.resize(res * res)
|
||||
var raw: PackedByteArray = Marshalls.base64_to_raw(str(terrain.get("heightmap_r16_b64", "")))
|
||||
if raw.size() < res * res * 2:
|
||||
return PackedFloat32Array() # kaputtes/fehlendes Höhenfeld → kein Wasser
|
||||
var hmin := float(terrain.get("min_height_m", 0.0))
|
||||
var hmax := float(terrain.get("max_height_m", 1.0))
|
||||
if hmax <= hmin:
|
||||
hmax = hmin + 1.0
|
||||
var n := mini(raw.size() / 2, res * res)
|
||||
for i in n:
|
||||
var v: int = raw.decode_u16(i * 2)
|
||||
out[i] = hmin + (float(v) / 65535.0) * (hmax - hmin)
|
||||
return out
|
||||
|
|
@ -1 +0,0 @@
|
|||
uid://cppnjm0fhofpa
|
||||
|
Before Width: | Height: | Size: 1.8 KiB |
|
|
@ -1,40 +0,0 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bsnwxasr4kxnw"
|
||||
path="res://.godot/imported/acacia_003.png-780c300e868256b9a9eb8bee97e274d7.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://library/thumbs/acacia_003.png"
|
||||
dest_files=["res://.godot/imported/acacia_003.png-780c300e868256b9a9eb8bee97e274d7.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 2 KiB |
|
|
@ -1,40 +0,0 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://dpng4qbmhgaxn"
|
||||
path="res://.godot/imported/acacia_005.png-13391d2a2fbb9e1af9a9899676d6255b.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://library/thumbs/acacia_005.png"
|
||||
dest_files=["res://.godot/imported/acacia_005.png-13391d2a2fbb9e1af9a9899676d6255b.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 2.5 KiB |
|
|
@ -1,40 +0,0 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://0vjob86u0mkh"
|
||||
path="res://.godot/imported/acacia_006.png-543980dded5a44fa5e3d06584f5fe696.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://library/thumbs/acacia_006.png"
|
||||
dest_files=["res://.godot/imported/acacia_006.png-543980dded5a44fa5e3d06584f5fe696.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 2.9 KiB |
|
|
@ -1,40 +0,0 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://dxjkjfi837uo7"
|
||||
path="res://.godot/imported/air_defense_001.png-b437d643c7024a7d8c111897c2ab61ec.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://library/thumbs/air_defense_001.png"
|
||||
dest_files=["res://.godot/imported/air_defense_001.png-b437d643c7024a7d8c111897c2ab61ec.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 2.8 KiB |
|
|
@ -1,40 +0,0 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://dmkfqnti7k861"
|
||||
path="res://.godot/imported/air_defense_002.png-53fc58f2e7263c151a9515b088d1f631.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://library/thumbs/air_defense_002.png"
|
||||
dest_files=["res://.godot/imported/air_defense_002.png-53fc58f2e7263c151a9515b088d1f631.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 1.8 KiB |
|
|
@ -1,40 +0,0 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://cyvumt7k7tfkt"
|
||||
path="res://.godot/imported/air_defense_platform_001.png-f3f7931f8c44d060f84082b8977bf627.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://library/thumbs/air_defense_platform_001.png"
|
||||
dest_files=["res://.godot/imported/air_defense_platform_001.png-f3f7931f8c44d060f84082b8977bf627.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 1.8 KiB |
|
|
@ -1,40 +0,0 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://blm2ew1gswl1e"
|
||||
path="res://.godot/imported/air_defense_platform_002.png-0a5ce0c8e1362f387319264873cf529f.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://library/thumbs/air_defense_platform_002.png"
|
||||
dest_files=["res://.godot/imported/air_defense_platform_002.png-0a5ce0c8e1362f387319264873cf529f.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 1.1 KiB |
|
|
@ -1,40 +0,0 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://cu2km1kitwe32"
|
||||
path="res://.godot/imported/antenna_001.png-4dad960bc19a6b3ab31294105028d1e9.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://library/thumbs/antenna_001.png"
|
||||
dest_files=["res://.godot/imported/antenna_001.png-4dad960bc19a6b3ab31294105028d1e9.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 2.7 KiB |
|
|
@ -1,40 +0,0 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://ckp5nasktsw6d"
|
||||
path="res://.godot/imported/apc_001.png-9e80d2bf93d5fc993e616b7b32e8b724.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://library/thumbs/apc_001.png"
|
||||
dest_files=["res://.godot/imported/apc_001.png-9e80d2bf93d5fc993e616b7b32e8b724.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 2.7 KiB |
|
|
@ -1,40 +0,0 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://b75b4yhnejh2m"
|
||||
path="res://.godot/imported/apc_002.png-523f4a9b408f9b8c5eb6be67985b0502.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://library/thumbs/apc_002.png"
|
||||
dest_files=["res://.godot/imported/apc_002.png-523f4a9b408f9b8c5eb6be67985b0502.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 1.5 KiB |
|
|
@ -1,40 +0,0 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://08m553i6la3k"
|
||||
path="res://.godot/imported/apc_cap.png-23a774749caddf07feaf320bf58cabdd.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://library/thumbs/apc_cap.png"
|
||||
dest_files=["res://.godot/imported/apc_cap.png-23a774749caddf07feaf320bf58cabdd.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 1.5 KiB |
|
|
@ -1,40 +0,0 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://dkxw5r6shmdeo"
|
||||
path="res://.godot/imported/apc_cap_1.png-d621f9e71ef0b7877f2b15a48d673ee9.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://library/thumbs/apc_cap_1.png"
|
||||
dest_files=["res://.godot/imported/apc_cap_1.png-d621f9e71ef0b7877f2b15a48d673ee9.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 1.9 KiB |
|
|
@ -1,40 +0,0 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://clmsnievmhcdv"
|
||||
path="res://.godot/imported/apc_weapon.png-c1a66e252a3e0b0605bbbabef999fd28.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://library/thumbs/apc_weapon.png"
|
||||
dest_files=["res://.godot/imported/apc_weapon.png-c1a66e252a3e0b0605bbbabef999fd28.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 2.6 KiB |
|
|
@ -1,40 +0,0 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bhqfuk76plea1"
|
||||
path="res://.godot/imported/barracks_001.png-155b2e8dc1723ecd52306bc4563ba954.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://library/thumbs/barracks_001.png"
|
||||
dest_files=["res://.godot/imported/barracks_001.png-155b2e8dc1723ecd52306bc4563ba954.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 2.1 KiB |
|
|
@ -1,40 +0,0 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://8d3x37mwv6xr"
|
||||
path="res://.godot/imported/barrel_001.png-6908404f7d70f7a5c32b5535b30c54e6.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://library/thumbs/barrel_001.png"
|
||||
dest_files=["res://.godot/imported/barrel_001.png-6908404f7d70f7a5c32b5535b30c54e6.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 2.1 KiB |
|
|
@ -1,40 +0,0 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://x036pdk80s03"
|
||||
path="res://.godot/imported/barrel_002.png-9223e213854153a1cae1e6683aba7a93.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://library/thumbs/barrel_002.png"
|
||||
dest_files=["res://.godot/imported/barrel_002.png-9223e213854153a1cae1e6683aba7a93.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 2 KiB |
|
|
@ -1,40 +0,0 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://clandxfaibniy"
|
||||
path="res://.godot/imported/barrel_003.png-dced15cfc3e6c765081d15d50c27a968.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://library/thumbs/barrel_003.png"
|
||||
dest_files=["res://.godot/imported/barrel_003.png-dced15cfc3e6c765081d15d50c27a968.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 2.1 KiB |
|
|
@ -1,40 +0,0 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://r3uuorqbq6g7"
|
||||
path="res://.godot/imported/barrel_004.png-94267e67e4b759e20fe5900b875a4eef.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://library/thumbs/barrel_004.png"
|
||||
dest_files=["res://.godot/imported/barrel_004.png-94267e67e4b759e20fe5900b875a4eef.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 2 KiB |
|
|
@ -1,40 +0,0 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://d1bivgvwdvioh"
|
||||
path="res://.godot/imported/barrel_005.png-9542d468a6873a8fd580ad9cdef4fd0f.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://library/thumbs/barrel_005.png"
|
||||
dest_files=["res://.godot/imported/barrel_005.png-9542d468a6873a8fd580ad9cdef4fd0f.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 2.1 KiB |
|
|
@ -1,40 +0,0 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://3vp6eyi4g2bj"
|
||||
path="res://.godot/imported/barrel_006.png-5890db03d20712e23b0aeb0f28d480ae.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://library/thumbs/barrel_006.png"
|
||||
dest_files=["res://.godot/imported/barrel_006.png-5890db03d20712e23b0aeb0f28d480ae.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 2 KiB |
|
|
@ -1,40 +0,0 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://b4atq8e72m7my"
|
||||
path="res://.godot/imported/barrel_007.png-d90f90a76918ff4bbd0adc316d5ffdf8.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://library/thumbs/barrel_007.png"
|
||||
dest_files=["res://.godot/imported/barrel_007.png-d90f90a76918ff4bbd0adc316d5ffdf8.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 2.1 KiB |
|
|
@ -1,40 +0,0 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://co0hauu3itiu3"
|
||||
path="res://.godot/imported/barrel_008.png-5f57f9825de2472879e769759a4679a8.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://library/thumbs/barrel_008.png"
|
||||
dest_files=["res://.godot/imported/barrel_008.png-5f57f9825de2472879e769759a4679a8.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 2.1 KiB |
|
|
@ -1,40 +0,0 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://cwb0huh22ist2"
|
||||
path="res://.godot/imported/barrel_009.png-b83ebf0290fccdfee558913551761413.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://library/thumbs/barrel_009.png"
|
||||
dest_files=["res://.godot/imported/barrel_009.png-b83ebf0290fccdfee558913551761413.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 2.1 KiB |
|
|
@ -1,40 +0,0 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://nwboqq7bq5cc"
|
||||
path="res://.godot/imported/barrel_010.png-8e9db8f1f68c4fdee8260e5894adfe86.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://library/thumbs/barrel_010.png"
|
||||
dest_files=["res://.godot/imported/barrel_010.png-8e9db8f1f68c4fdee8260e5894adfe86.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 1.7 KiB |
|
|
@ -1,40 +0,0 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bf2orfs8g27pk"
|
||||
path="res://.godot/imported/barrel_011.png-e6f72afda072cf9838ed06700c6b5ebd.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://library/thumbs/barrel_011.png"
|
||||
dest_files=["res://.godot/imported/barrel_011.png-e6f72afda072cf9838ed06700c6b5ebd.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 2.5 KiB |
|
|
@ -1,40 +0,0 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://dddfloskgqjui"
|
||||
path="res://.godot/imported/barrel_012.png-69afd264c2078adae3355c1036520a7e.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://library/thumbs/barrel_012.png"
|
||||
dest_files=["res://.godot/imported/barrel_012.png-69afd264c2078adae3355c1036520a7e.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 2.6 KiB |
|
|
@ -1,40 +0,0 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://8wcuxv0v56js"
|
||||
path="res://.godot/imported/barrel_013.png-3b6581a9a4637f3f79f372095dbc1b6a.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://library/thumbs/barrel_013.png"
|
||||
dest_files=["res://.godot/imported/barrel_013.png-3b6581a9a4637f3f79f372095dbc1b6a.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 1.5 KiB |
|
|
@ -1,40 +0,0 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://drn6mij5p6hv5"
|
||||
path="res://.godot/imported/barrier_001.png-f4f9b068e708eb35cf4f0689fd3c6f74.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://library/thumbs/barrier_001.png"
|
||||
dest_files=["res://.godot/imported/barrier_001.png-f4f9b068e708eb35cf4f0689fd3c6f74.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 1.2 KiB |
|
|
@ -1,40 +0,0 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://dbhbgk7y8j54p"
|
||||
path="res://.godot/imported/barrier_002.png-226efbbe1880285f86c95e9a1be7518e.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://library/thumbs/barrier_002.png"
|
||||
dest_files=["res://.godot/imported/barrier_002.png-226efbbe1880285f86c95e9a1be7518e.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 885 B |
|
|
@ -1,40 +0,0 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://ccvfh73fkfikq"
|
||||
path="res://.godot/imported/barrier_003.png-22cd5cdb2ab7396c5afef5360b5067dd.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://library/thumbs/barrier_003.png"
|
||||
dest_files=["res://.godot/imported/barrier_003.png-22cd5cdb2ab7396c5afef5360b5067dd.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 2.3 KiB |
|
|
@ -1,40 +0,0 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bgc3wwy6b41b0"
|
||||
path="res://.godot/imported/barrier_004.png-980b996df5a61642aa5a8982d9429ff5.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://library/thumbs/barrier_004.png"
|
||||
dest_files=["res://.godot/imported/barrier_004.png-980b996df5a61642aa5a8982d9429ff5.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 2.3 KiB |
|
|
@ -1,40 +0,0 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://dmkxussbxmumo"
|
||||
path="res://.godot/imported/barrier_005.png-9239fc40b7d66072393ec05a176a0899.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://library/thumbs/barrier_005.png"
|
||||
dest_files=["res://.godot/imported/barrier_005.png-9239fc40b7d66072393ec05a176a0899.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 3 KiB |
|
|
@ -1,40 +0,0 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://cjhuexnsl151p"
|
||||
path="res://.godot/imported/barrier_006.png-a42842c6692537da809bd937c042edfc.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://library/thumbs/barrier_006.png"
|
||||
dest_files=["res://.godot/imported/barrier_006.png-a42842c6692537da809bd937c042edfc.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 2.4 KiB |
|
|
@ -1,40 +0,0 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://shriffj4a6cq"
|
||||
path="res://.godot/imported/barrier_007.png-18ef1a4c7bc9c8b4fdc1b04d8b91dad1.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://library/thumbs/barrier_007.png"
|
||||
dest_files=["res://.godot/imported/barrier_007.png-18ef1a4c7bc9c8b4fdc1b04d8b91dad1.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 2.1 KiB |
|
|
@ -1,40 +0,0 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://cgio2t6y3iuik"
|
||||
path="res://.godot/imported/barrier_008.png-f615e24e39cbfa5c4030021171d3bcc5.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://library/thumbs/barrier_008.png"
|
||||
dest_files=["res://.godot/imported/barrier_008.png-f615e24e39cbfa5c4030021171d3bcc5.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 2.1 KiB |
|
|
@ -1,40 +0,0 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://btki2yug25x23"
|
||||
path="res://.godot/imported/barrier_009.png-f723a86b81fe9b5d3d1a1ae7a8338df0.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://library/thumbs/barrier_009.png"
|
||||
dest_files=["res://.godot/imported/barrier_009.png-f723a86b81fe9b5d3d1a1ae7a8338df0.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 3 KiB |
|
|
@ -1,40 +0,0 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://cjs7nqt4rl4qr"
|
||||
path="res://.godot/imported/barrier_010.png-eb2f5f66658412f8d13ad87794ce497c.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://library/thumbs/barrier_010.png"
|
||||
dest_files=["res://.godot/imported/barrier_010.png-eb2f5f66658412f8d13ad87794ce497c.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 2.1 KiB |
|
|
@ -1,40 +0,0 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://j0rac170fjwn"
|
||||
path="res://.godot/imported/barrier_011.png-6f858b9fbbf01e80766f67abd167b690.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://library/thumbs/barrier_011.png"
|
||||
dest_files=["res://.godot/imported/barrier_011.png-6f858b9fbbf01e80766f67abd167b690.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 2 KiB |
|
|
@ -1,40 +0,0 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://e6r8uhiswdsx"
|
||||
path="res://.godot/imported/barrier_012.png-977a45ba313cbc8a3475c3b4dd181d97.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://library/thumbs/barrier_012.png"
|
||||
dest_files=["res://.godot/imported/barrier_012.png-977a45ba313cbc8a3475c3b4dd181d97.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 2.4 KiB |
|
|
@ -1,40 +0,0 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://6bx8ua6gpxf2"
|
||||
path="res://.godot/imported/barrier_013.png-873e6d19995610db66444c98f588223d.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://library/thumbs/barrier_013.png"
|
||||
dest_files=["res://.godot/imported/barrier_013.png-873e6d19995610db66444c98f588223d.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 2.5 KiB |
|
|
@ -1,40 +0,0 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://kbu8pt3aad80"
|
||||
path="res://.godot/imported/barrier_014.png-e442cc785a151929218fc114716542eb.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://library/thumbs/barrier_014.png"
|
||||
dest_files=["res://.godot/imported/barrier_014.png-e442cc785a151929218fc114716542eb.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 2.4 KiB |