Commit graph

303 commits

Author SHA1 Message Date
Kelsi
4b3375ac44 feat(editor): export NPC/M2 model textures as PNG with the zone
TextureExporter::collectUsedTextures only picked up terrain textures, so
exported zones were missing every texture referenced by NPC creature models
and placed M2 doodads. Added collectM2Textures() and unified the export
collection to include terrain + all referenced M2 paths, so the rendered
zone is fully self-contained in the PNG/WOM open formats.
2026-05-06 01:11:47 -07:00
Kelsi
732e58355a feat(editor): convert NPC creature models to WOM during zone export
Previously only placed M2 objects were converted to the WOM open format.
NPC creature models stayed as references to game M2/skin files, which
meant exported zones still depended on proprietary Blizzard assets to
render their NPCs. Now the exporter walks both placed objects and NPC
spawns and emits a WOM for every unique M2 path, making zones fully
self-contained.
2026-05-06 01:09:38 -07:00
Kelsi
35ad340ccc feat(editor): facing arrow on NPC markers + Ctrl+Wheel hint in object panel
NPC markers now show a yellow ground-triangle pointing in the orientation
direction so users can see facing without selecting. Object panel gained
the Ctrl+Wheel rotation hint to match the NPC panel.
2026-05-06 01:08:32 -07:00
Kelsi
b736c6b2e1 feat(wom): add WOM3 multi-batch format for material-aware models
WOM1/WOM2 had a single mesh with one texture, which lost the multi-submesh
structure of complex M2 models (body+hair+eyes+armor each need different
textures and blend modes).

WOM3 adds a Batch array: each batch has indexStart/indexCount + a textureIndex
into texturePaths + blendMode + flags. Loader is fully backward compatible:
WOM1/WOM2 files still load, and WOM3 with no batches block falls back to a
single full-mesh batch. fromM2 now extracts batches with materials, and toM2
emits matching M2 batches so the renderer can draw them correctly.
2026-05-06 01:07:00 -07:00
Kelsi
00c078a9af feat(editor): snapSelectedToGround now also snaps NPCs and their patrol waypoints 2026-05-06 01:03:50 -07:00
Kelsi
03a863abe1 refactor(wom): extract WOM->M2 conversion to shared helper
Adds WoweeModelLoader::toM2() and tryLoadByGamePath() to deduplicate the
identical conversion code that lived in editor_viewport for both objects
and NPCs. Cuts ~70 lines of duplicated logic and makes WOM->M2 reusable
across the codebase.
2026-05-06 01:02:56 -07:00
Kelsi
eb8f5a09b1 feat(editor): visualize patrol path of selected NPC as ribbon with waypoints
Adds setPatrolPath() that draws a multi-segment orange ribbon between the
NPC's spawn position and each waypoint, plus diamond markers at each point
(green for start = NPC home, white for waypoints). Renders only while the
NPC is selected and has a patrol path defined.
2026-05-06 00:58:30 -07:00
Kelsi
191ff9ec16 feat(editor): NPC orientation control + Ctrl+Wheel rotates placement preview
Added orientation slider in NPC panel with random button. Ctrl+Wheel now
rotates the placement preview (objects and NPCs) instead of zooming —
Shift makes the step finer (5 deg vs 15 deg). Ghost preview now shows
the actual orientation that the placed NPC will have.
2026-05-06 00:56:19 -07:00
Kelsi
1c3307a0b6 fix(editor): unload ghost preview model when path changes
setGhostPreview reused modelId 59999 for every preview, but loadModel
returns true without doing anything when the ID is already cached. So
selecting a new NPC kept the old ghost model in GPU memory and createInstance
used the stale model. Added M2Renderer::unloadModel public API and call it
from clearGhostPreview.
2026-05-06 00:51:22 -07:00
Kelsi
ca630c4e87 chore(editor): remove debug logging now that NPC rendering works 2026-05-06 00:48:41 -07:00
Kelsi
687923c885 fix(editor): call M2Renderer::prepareRender to allocate mega bone slots before render
Without prepareRender(), animated NPC creature instances had megaBoneOffset=0
which caused the render loop to skip them (filtered out at the bones check).
This is why all loaded NPC M2s produced 0 draw calls despite valid GPU buffers,
material sets, and instance creation. Matches the main game's render flow.
2026-05-06 00:47:21 -07:00
Kelsi
e97d6d0c23 fix(editor): remove nested upload batch, add instance creation diagnostics 2026-05-06 00:16:25 -07:00
Kelsi
a845723635 fix(editor): create M2 instances AFTER upload flush (isValid fix)
ROOT CAUSE: createInstance() checks mdlRef.isValid() which requires
vertexBuffer != VK_NULL_HANDLE. But vertex buffers are uploaded via
staging and only finalized by waitAllUploads(). Instances were being
created BEFORE the upload flush, so vertexBuffer was still null,
cachedIsValid was set to false, and all instances were skipped during
render (0 draws despite loaded models).

Fix: split rebuildObjects into two phases:
1. Load all models (upload geometry to staging)
2. waitAllUploads + pollUploadBatches (finalize GPU buffers)
3. Create all instances (vertexBuffer is now valid, isValid() = true)

This matches the client's terrain_manager pattern where models are
loaded on background threads and instances created after finalization.
2026-05-06 00:11:44 -07:00
Kelsi
c9c4a15e9a fix(editor): remove per-model upload waits, single batch flush
Log showed: models=2, instances=3, draws=0 — models loaded and
instances created but zero draw calls. The M2 renderer skips
instances where cachedIsValid is false, which depends on the GPU
vertex buffer being valid after upload.

The per-model waitAllUploads/pollUploadBatches calls inside the
loading loop may have corrupted the upload batch context (started
at beginUploadBatch but flushed mid-loop). Now all models upload
in a single batch with one final waitAllUploads+pollUploadBatches
at the end of rebuildObjects.
2026-05-06 00:06:40 -07:00
Kelsi
c077ee2cee fix(editor): add per-frame M2 render diagnostics (models/instances/draws) 2026-05-06 00:02:02 -07:00
Kelsi
6f066dee48 fix(editor): debounce M2 rebuild to prevent clear+reload loop
ROOT CAUSE of NPC models not rendering: every NPC placement triggered
an immediate full clear+rebuild of ALL M2 models. During rapid clicking,
this created a destroy-reload cycle where models were cleared faster
than they could render — the log showed rebuild firing every ~200ms
with models loading OK but being destroyed before the next frame.

Fix: debounce rebuilds with a 0.5s timer. Multiple rapid placements
reset the timer, so the rebuild only fires once after the user stops
clicking. Models stay loaded and visible between placements.

Before: click → clear all → reload all → click → clear all → reload...
After:  click → click → click → (0.5s pause) → single rebuild
2026-05-05 23:59:51 -07:00
Kelsi
09e867eb07 fix(editor): move rebuildObjects AFTER beginFrame (instance SSBO fix)
ROOT CAUSE of NPCs not rendering: rebuildObjects() called createInstance()
BEFORE beginFrame(), causing instance SSBO writes to use the wrong frame
index. The M2 renderer writes instance transforms to a per-frame buffer
indexed by getCurrentFrame(), but the frame index isn't valid until after
beginFrame() returns.

This is the same bug documented in the project memory:
"M2 models not rendering (draws=0): update() was called before
beginFrame(), causing frame index mismatch in instance SSBO"

Models loaded correctly (log confirmed 2192v 7926i 8b) but instances
were invisible because their transform data was written to the wrong
frame buffer.

Fix: move the rebuild block after beginFrame(), alongside update().
2026-05-05 23:53:52 -07:00
Kelsi
f1133cdfa7 fix(editor): NPC diagnostics use WARNING level (INFO invisible in Release)
Release builds set default log level to WARNING — all the NPC loading
diagnostic messages were at LOG_INFO/LOG_DEBUG and completely invisible.
This is why the log showed zero NPC messages despite NPCs being placed.

All NPC loading messages now use LOG_WARNING:
- "NPC rebuild: N creatures to load" — confirms rebuild loop runs
- "NPC M2 OK: path (Nv Ni Nb)" — model loaded successfully
- "NPC loaded from WOM: path" — WOM format used
- "NPC model file not found: path" — file missing
- "NPC model invalid: path" — parse failed
- "NPC M2 loadModel failed: path" — GPU upload failed
- "NPC has empty modelPath: name" — no model selected
2026-05-05 23:49:46 -07:00
Kelsi
5506fd155b fix(editor): all NPC loading messages now WARNING level (were DEBUG)
NPC model loading diagnostics were at LOG_DEBUG level which doesn't
appear in the default log output. Changed all NPC model loading
messages to LOG_WARNING/LOG_INFO:
- "NPC model file not found" now WARNING (was DEBUG, invisible)
- "NPC has empty modelPath" new WARNING for missing model selection
- "Loading N NPC models..." at loop entry to confirm rebuild runs
- "NPC M2 loaded" at INFO level shows successful loads

This will reveal exactly where the NPC rendering pipeline fails.
2026-05-05 23:25:57 -07:00
Kelsi
ef04159b46 fix(editor): upgrade NPC model loading diagnostics to WARNING level
Changed NPC model invalid and load success messages from LOG_DEBUG to
LOG_WARNING/LOG_INFO so they appear in the log output. This helps
diagnose why specific creature models fail to render — the log will
show vertex/index/batch counts for each load attempt.
2026-05-05 23:06:34 -07:00
Kelsi
d773109b50 feat(editor): WMO-only instance loading (Dire Maul, dungeons, raids)
Many WoW instances (Dire Maul, Blackrock Depths, etc.) are WMO-only
maps with no ADT terrain tiles. The editor now handles these:

- loadWMOInstance(): reads WDT, detects WDTF_GLOBAL_WMO flag, loads
  the root WMO path from MWMO chunk, places it as an object with
  correct position/rotation from MODF chunk
- Automatic fallback: when loadADT fails to find tiles, tries
  WMO-only loading before showing error
- Load dialog: "Find Tile" detects WMO-only instances and shows
  "WMO-only instance — click Load to open" instead of "not found"
- Camera positioned near the WMO for immediate editing
- Blank terrain floor generated as ground reference
2026-05-05 22:44:38 -07:00
Kelsi
072d0f78c2 fix(editor): begin upload batch before M2 model loading in rebuild
rebuildObjects() calls clearObjects() which clears the M2 renderer,
but didn't start a new upload batch before loading models. The M2
renderer needs an active upload batch context to upload vertex/index
buffers to the GPU. Without it, loadModel may silently fail.

Now calls vkCtx_->beginUploadBatch() after clear and before the
model loading loop. Also adds diagnostic logging when loadModel
fails for NPCs (shows vertex/index/batch counts).
2026-05-05 22:40:58 -07:00
Kelsi
98223995fc fix(editor): placed objects also use WOM format + always load skin
Applied same two fixes from NPC renderer to placed object renderer:
1. Check WOM open format before M2 fallback (custom_zones/output dirs)
2. Always load skin file regardless of initial isValid state

Both placed objects (M2 doodads from ADT import or manual placement)
and NPC creatures now have consistent WOM→M2 fallback pipeline with
proper skin file loading.
2026-05-05 22:29:31 -07:00
Kelsi
3f5b030a4a feat(editor): NPC models load from WOM open format before M2 fallback
NPC creature renderer now checks for WOM open format models in
custom_zones/models/ and output/models/ before falling back to M2
game data files. This completes the WOM integration — both placed
objects (via terrain_manager) and NPC creatures (via editor viewport)
can render from the novel open format.

WOM→M2Model conversion includes bone weights, textures, render batch,
and material setup — same pipeline as the client-side WOM loader.

Loading priority: WOM (open format) → M2 + skin (game data)
2026-05-05 22:27:35 -07:00
Kelsi
47bfe35b26 fix(editor): always load M2 skin file for NPC models
WotLK M2 models store geometry in separate .skin files. The NPC
renderer was only loading skin files when M2Loader::load() returned
invalid (empty vertices). But some M2 files have vertices in the
header yet need the skin file for indices, batches, and submeshes.

Now always attempts to load the skin file regardless of initial
isValid() state. This fixes creature models not rendering even
when the M2 and skin files exist on disk.

Also improved debug logging to show vertex/index counts when models
fail to load, making it easier to diagnose remaining issues.
2026-05-05 22:26:10 -07:00
Kelsi
92787901d8 feat(editor): tile count button in ADT load dialog
"Count" button next to "Find Tile" scans all 64x64 tile coordinates
and shows how many ADT tiles exist for the selected map. Helps users
understand the scope of a map before loading individual tiles.
2026-05-05 22:23:18 -07:00
Kelsi
cc7ec8e497 fix(editor): clear previous state on ADT load, fix model orientations
Two bugs fixed:
- Loading a new ADT tile now clears all previous objects, NPCs, quests,
  path state, and terrain before loading. Was accumulating old state
  across multiple loads
- ADT doodad/WMO rotation conversion now matches client's transform:
  renderRotX = -adtRotZ, renderRotY = -adtRotX, renderRotZ = adtRotY+180
  Was copying raw ADT rotations without coordinate system conversion,
  causing models to appear at wrong orientations
2026-05-05 22:19:18 -07:00
Kelsi
e287cc9a78 fix(editor): shrink NPC markers, add show/hide toggle
- NPC markers reduced from 30-unit poles to 8-unit poles (was
  overwhelming and obscuring terrain). Base 1.5u, diamond top 1u
- "Show Position Markers" checkbox in NPC panel to toggle visibility
- Markers hidden when checkbox unchecked — useful when M2 creature
  models are rendering and markers are redundant
- Marker alpha reduced for less visual noise
2026-05-05 22:11:53 -07:00
Kelsi
d84ad82e26 fix(editor): recompute chunk positions after ADT coord override
When loading ADT tiles, the editor overrides terrain_.coord with the
filename-derived tile coordinates (instanced maps have arbitrary
internal values). But it wasn't recomputing the per-chunk world
positions to match, causing terrain to render at wrong coordinates.

Now recalculates all 256 chunk positions from the corrected tile
coordinates using the standard WoW formula:
  chunkX = (32 - tileX) * 533.33 - cx * 33.33
  chunkY = (32 - tileY) * 533.33 - cy * 33.33

This fixes terrain appearing at the wrong location in the editor
when loading instanced maps or tiles with mismatched internal coords.
2026-05-05 22:05:43 -07:00
Kelsi
9d14bc19cb fix(editor): log when NPC model files not found (helps debug rendering) 2026-05-05 21:59:51 -07:00
Kelsi
1db1166bec fix(editor): NPC markers now always render (pipeline binding bug)
NPC position markers were silently not rendering when no object was
selected because they relied on the gizmo's pipeline being bound, but
the gizmo only binds its pipeline when active. Now explicitly binds
the water pipeline (same pos+color vertex format with alpha blend)
before drawing NPC markers, ensuring they always appear regardless of
gizmo state.

Note: M2 creature models still require extracted game data files to
render. When model files aren't found, the colored markers (poles with
diamond tops) provide reliable visual feedback for NPC positions.
2026-05-05 21:58:32 -07:00
Kelsi
fde1fa8129 fix(editor): batch convert CLI has visible output and proper exit codes
Some checks are pending
Build / Build (arm64) (push) Waiting to run
Build / Build (x86-64) (push) Waiting to run
Build / Build (macOS arm64) (push) Waiting to run
Build / Build (windows-arm64) (push) Waiting to run
Build / Build (windows-x86-64) (push) Waiting to run
Security / CodeQL (C/C++) (push) Waiting to run
Security / Semgrep (push) Waiting to run
Security / Sanitizer Build (ASan/UBSan) (push) Waiting to run
- --convert-m2 and --convert-wmo now print progress and results to
  stdout (was LOG_INFO to log file only, invisible to user)
- Failures return exit code 1 (was always 0, breaking scripting)
- Success output shows vertex/bone counts (M2) or group count (WMO)
- Error messages go to stderr for proper pipe handling
2026-05-05 16:57:06 -07:00
Kelsi
1337a963a0 fix(editor): CLI output visible on stdout (was silent LOG_INFO)
--help, --version, and --list-zones now print to stdout via printf
instead of LOG_INFO which writes to log file only. Users running
CLI commands would see no output at all — critical first-impression
bug for new users.

Also updated --version format list to include WOC.
2026-05-05 16:54:03 -07:00
Kelsi
110f250150 feat(editor): biome vegetation auto-population system
One-click procedural object placement based on biome rules:

- 10 biome vegetation rulesets with density, scale range, and slope
  constraints per asset type (trees, bushes, rocks, ferns, etc.)
- Grassland: pine trees + bushes + rocks
- Forest: ashenvale trees + ferns + forest rocks (dense canopy)
- Jungle: palm trees + ferns + vines (high density)
- Desert: cacti + desert rocks + bones (sparse)
- Barrens: scattered trees + dry bushes + rocks
- Snow: snow pines + snowdrifts + rocks
- Swamp: dark trees + mushrooms + logs
- Rocky: rock formations + rock piles
- Beach: palm trees + beach rocks
- Volcanic: lava rocks + charred trees

Objects panel > Auto-Populate Biome: select biome, set seed, click
"Populate Zone" to fill the entire tile with biome-appropriate
vegetation at rule-defined densities.
2026-05-05 16:42:41 -07:00
Kelsi
0d401c3eb8 docs: document server module generator in CHANGELOG, README, help panel
- CHANGELOG: add server module generator description
- README: add AzerothCore integration paragraph with feature summary
- Help panel (F1): add "File → Generate Server Module" to export section
2026-05-05 16:34:40 -07:00
Kelsi
cceff622b4 feat(editor): AzerothCore server module generator
One-click generation of a complete AzerothCore/TrinityCore server module
from editor zone data. File > Generate Server Module creates:

- sql/01_map.sql: map_dbc + area_table_dbc registration
- sql/02_spawns.sql: creature_template + creature + waypoint_data + quests
- sql/03_teleport.sql: game_tele entry for .tele command
- sql/04_zone_flags.sql: sanctuary/PvP area flags
- conf/mod_wowee.conf.dist: worldserver.conf snippet with zone settings
- README.md: step-by-step server admin installation guide
- module.json: machine-readable module manifest

Server admins can import the SQL files, add the config snippet, and
restart their server to have the custom zone fully operational with
NPC spawns, patrol paths, quests, teleport commands, and zone flags.
2026-05-05 16:31:13 -07:00
Kelsi
f6dfc295ab feat: WOM2 animated model format with bones and keyframe animation
Upgrades WOM from geometry-only (WOM1) to fully animated (WOM2):

- WOM2 magic (0x324D4F57) for animated models, WOM1 for static
- Vertex extended: +boneWeights[4] +boneIndices[4] (40 bytes vs 32)
- Bone data: keyBoneId, parentBone, pivot, flags per bone
- Animation data: per-sequence per-bone keyframes with translation,
  rotation (quaternion), scale at millisecond timestamps
- fromM2() now preserves all skeletal data: bone hierarchy, weights,
  and per-sequence keyframes from M2 animation tracks
- Backward compatible: WOM1 files load without bone data (32-byte
  vertices read and padded with default bone weights)
- FORMAT_SPEC.md updated with WOM2 binary layout
2026-05-05 16:16:07 -07:00
Kelsi
b19627d82c feat(editor): SQL spawn export for AzerothCore/TrinityCore
Private server integration: export creature spawns, patrol waypoints,
and quest definitions as ready-to-import SQL for AzerothCore/TrinityCore.

- creature_template: name, level, health, mana, damage, armor, faction,
  npcflag (questgiver/vendor/flightmaster/innkeeper), displayId, scale
- creature: spawn position, orientation, respawn time, wander distance,
  movement type (stationary/wander/patrol)
- creature_addon + waypoint_data: patrol path waypoints with delays
- quest_template: title, description, completion text, level, XP, money
- All use ON DUPLICATE KEY UPDATE for safe re-imports
- Auto-exported as spawns.sql alongside other assets on zone save
- File > Export Server SQL menu item for standalone export
- Map ID from zone metadata panel used in spawn table
2026-05-05 16:06:34 -07:00
Kelsi
84a431880e feat(editor): zone map image export (colored top-down PNG)
- exportZoneMap(): renders terrain as colored top-down image with
  height-based coloring (blue lowlands → green plains → brown hills →
  white peaks), water overlay, hole visualization, doodad markers
- Configurable resolution (128-2048px, default 512)
- Auto-exported as zone_map.png alongside other assets on save
- File > Export Zone Map menu with resolution slider
- Useful for documentation, server admin tools, custom map websites
2026-05-05 16:01:29 -07:00
Kelsi
9db5cced2c feat(editor): zone metadata panel with mapId, displayName, gameplay flags
- Map ID: configurable integer input (0-65535) for private server
  integration. Custom zones default to 9000+ to avoid Blizzard conflicts
- Display Name: editable text field for in-game world map/loading screen
- Description: multi-line text field for zone documentation
- Zone Flags: Allow Flying, PvP Enabled, Indoor, Sanctuary checkboxes
- All fields serialized to zone.json under "flags" key
- Info panel shows quest count alongside objects/NPCs
2026-05-05 15:52:59 -07:00
Kelsi
2136727c68 feat(editor): zone audio configuration panel
- Zone manifest gains audio fields: musicTrack, ambienceDay,
  ambienceNight, musicVolume, ambienceVolume
- Serialized to/from zone.json under "audio" key
- Info panel: collapsable "Zone Audio" section with text inputs for
  music/ambience paths and volume sliders
- Preset selector: Elwynn Forest, Durotar, Darkshore, Dungeon, None
- ZoneManifest stored persistently on EditorApp so audio settings
  survive between exports (was recreated each save)
- Custom zones can now specify their own background music and ambient
  soundscapes via zone.json
2026-05-05 15:48:49 -07:00
Kelsi
36dc9ddef7 feat(editor): PNG/JPG/BMP heightmap image import, undo for all imports
- importHeightmapImage(): loads any resolution PNG/JPG/BMP/TGA via
  stb_image, supports both 8-bit and 16-bit precision, maps to terrain
  vertices with bilinear coordinate mapping
- Both image import and RAW import now wrapped with undo
  (recordGeneratorUndo/commitGeneratorUndo)
- UI: File > Import Heightmap now offers "Import Image" (any format)
  and "Import RAW" (binary) as separate options
- Enables professional terrain workflows: paint in Photoshop/GIMP,
  generate in World Machine/Gaea, import directly as terrain
2026-05-05 15:42:35 -07:00
Kelsi
33042c3a47 feat(editor): collision slope overlay, 7/7 format references
- Minimap slope overlay: toggle "Show Slopes (collision)" to visualize
  steep terrain chunks with red intensity overlay (50 deg threshold)
- Lets zone creators preview walkability before exporting WOC
- About dialog updated to show 7/7 format replacements including WOC
- Help panel documents collision preview and export includes collision
2026-05-05 15:37:08 -07:00
Kelsi
4d5eef480e feat: WOC collision mesh format — 7th novel open format
New format: WOC (Wowee Open Collision) — binary collision mesh for
custom zone walkability. Magic WOC1 (0x31434F57).

- WoweeCollisionBuilder::fromTerrain() generates collision triangles
  from terrain heightmap with slope classification (50 deg threshold)
- Per-triangle flags: walkable (0x01), water (0x02), steep (0x04)
- Respects terrain holes (skips triangles in hole regions)
- Binary save/load with bounds, tile coords, triangle data
- Auto-exported on zone save alongside WOT/WHM/WOM/WOB
- Added to content pack validation (score now 0-7)
- FORMAT_SPEC.md v1.1 updated with WOC binary layout
- 19 new test assertions: flat terrain generation (32k tris all
  walkable), save/load round-trip, hole skipping
- 328 total assertions across 84 test cases
2026-05-05 15:23:58 -07:00
Kelsi
961d863f82 fix: shell injection in gitCommit projectDir, test directory cleanup
- gitCommit() now uses double quotes for projectDir consistently with
  gitPush/gitPull/gitStatus (was single quotes, breaking on paths with
  apostrophes like "John's Project")
- Test suite auto-cleans test_output_formats/ directory via Catch2
  event listener after all tests complete (was leaving empty dir)
2026-05-05 15:16:20 -07:00
Kelsi
47eff19cb6 feat: WOB material serialization, FORMAT_SPEC v1.1, material tests
- WOB save/load now serializes Material struct fields (flags, shader,
  blendMode, texturePath) per group — was saving only texture paths
- FORMAT_SPEC.md v1.1: documents WOT doodad/WMO placements, WOB
  material fields, doodad rotation, terrain stamps, WCP file list
- Test coverage: 5 new assertions verify material round-trip (flags,
  shader, blendMode all preserved through save→load cycle)
- 260 total assertions across 75 test cases, all passing
2026-05-05 14:53:28 -07:00
Kelsi
ca15da5e9b feat: WOT doodad/WMO placements, WOB materials, deduplicate loader
Architecture fixes for open format data fidelity:

- WOT now serializes full doodad/WMO placement arrays (positions,
  rotations, scale, flags, doodad sets) — was only storing counts,
  causing all placed objects to be lost on WOT round-trip
- WOT loader parses placements back into ADTTerrain for client rendering
- WOB Material struct added: preserves WMO material flags, shader type,
  and blend mode during WMO→WOB conversion (was geometry-only)
- WOB doodad rotation: quaternion→euler conversion instead of hardcoded
  zero (placed doodads inside buildings now retain their orientation)
- importOpen() deduplicated: delegates to pipeline::WoweeTerrainLoader
  instead of duplicating 100 lines of parsing code
2026-05-05 14:44:46 -07:00
Kelsi
d00ddd1c73 feat(editor): WCP shortcut, help panel overhaul, active path restore
- Ctrl+Shift+E keyboard shortcut for WCP content pack export
- Help panel expanded: object tools (snap/align/flatten/scatter/select
  by type), all terrain generators, stamp save/load, export shortcuts
- ObjectPlacer::loadFromFile restores activePath_ from loaded objects
  so users can continue placing the same type after loading
- WCP export menu item now shows Ctrl+Shift+E hint
2026-05-05 14:38:01 -07:00
Kelsi
7473728360 feat(editor): stamp persistence, WCP file preview, enriched stats
- Terrain stamps save/load to JSON: reuse terrain features across zones
  and sessions. Save/Load buttons in Sculpt > Stamp/Clone panel
- WCP Inspect now shows full file breakdown: terrain/model/building/
  texture/data counts with total size. Powered by readInfo file list
  parsing with auto-categorization by extension
- stats.json now includes chunk count, triangle count, tile count, and
  editor version alongside existing object/NPC/quest/texture counts
- Fix unprotected std::stoi in custom zone WOT filename parser
2026-05-05 14:33:52 -07:00
Kelsi
d3e8f999c7 feat(editor): flatten around object, scatter auto-align, manifest batch
- Flatten Ground: flattens terrain to object height with smooth falloff
  around placed buildings/structures (undoable). Button in object panel
- Scatter auto-align: checkbox enables terrain snapping + slope alignment
  for scattered objects (trees snap to ground and lean with hillsides)
- Batch convert now falls back to asset manifest when filesystem dir is
  empty — converts M2/WMO from game data without filesystem extraction
- Public terrain editor wrappers: beginGeneratorUndo, endGeneratorUndo,
  markDirty, stitchChunkEdges, getChunkVertexWorldPos
2026-05-05 14:28:14 -07:00