-
-
Notifications
You must be signed in to change notification settings - Fork 2
feat(Building): interior systems, NPC navigation, terrain prep, and post-build customization #6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
65 commits
Select commit
Hold shift + click to select a range
fa5bf4d
fix(Building): correct door top segment positioning above roofline
hdlmrell 524cfa1
feat(Building): add TerrainClearer for clearing terrain around placed…
hdlmrell f9ee2a1
Merge branch 'fix/door-top-segment-positioning' into fix/urp-light-de…
hdlmrell 0d53891
fix(Lighting): set URP-correct light defaults for Schedule I's pipeline
hdlmrell 379d045
fix(Building): clear renderer-less objects and tree rustle sounds in …
hdlmrell 2529131
feat(Building): add onCreated callback to AddPrefab and AddSlidingDoors
hdlmrell 5955683
fix(Building): use instance IDs for preserved set and protect road we…
hdlmrell 64a4cac
feat(Building): add stair style system with Solid, ClosedRiser, and O…
hdlmrell 1eeb58a
fix(Building): gap base molding around door openings
hdlmrell f86e2c9
fix(Building): position base molding to protrude past walls like roof…
hdlmrell c7fff2a
feat(Building): add opt-in door frames with wall inset for clean fit
hdlmrell 23ca7a6
feat(Building): add support for windows alongside door openings
hdlmrell fc6ef6b
feat(Building): make AddWalls boolean overload support doors and wind…
hdlmrell 9eabccf
feat(Building): support multiple windows per wall and fix glass material
hdlmrell dbac6e5
feat(Building): add RoofBuilder with parapet and hip roof styles
hdlmrell f47b0e1
fix(Building): extend N/S walls to cover corner gaps with E/W walls
hdlmrell 22d763f
feat(Building): add AddCornerTrim for vertical corner trim strips
hdlmrell 5b83958
feat(Building): add WallOpening.Offset for off-center doors and windows
hdlmrell 75b1297
feat(Building): add interior walls with doorway tracking for NavMesh
hdlmrell 40da7b1
feat(Building): add WithInteriorWallLayer for placement raycast control
hdlmrell be633a8
feat(Building): add color and material parameters to AddFoundation an…
hdlmrell e0b262c
feat(Building): add NavMeshRepairer for runtime interior NavMesh
hdlmrell 227f0e1
fix(Building): fix NavMesh doorway filter and add interior doorway su…
hdlmrell 37e74c3
fix: replace foreach Transform with GetChild for IL2CPP compatibility
hdlmrell 71d20c1
feat(Building): add per-wall material and color overrides for exterio…
hdlmrell 5451ea9
feat(Building): add skipWalls parameter to AddBaseMolding
hdlmrell 4ce9cda
feat(Building): add TerrainFlattener for runtime height and detail cl…
hdlmrell a2030f2
feat(Building): add interior door frames with wall segment insetting
hdlmrell 0ab0bb7
fix(ProceduralMesh): enable all rendering layers for decal projection…
hdlmrell 5bf084b
refactor(Building): replace SnapToGrid with ComputeGridCellSize and a…
hdlmrell fe5f29e
fix(Building): harden TerrainClearer with living entity detection and…
hdlmrell b1a032c
refactor(Building): remove dead heightmap snapshot system from Terrai…
hdlmrell 85c9898
feat(Building): unify NPC navigation on custom A* pathfinding
hdlmrell 6f2b83b
fix(Building): clear FoliageRustleSound objects during terrain clearing
hdlmrell 96f54fa
fix(Building): improve NPC chase repath and stuck detection in interi…
hdlmrell 957804b
fix(Building): add terrain retry queue for IL2CPP late-load race cond…
hdlmrell c705123
feat(Building): add client-side FishNet prefab linking and inactive s…
hdlmrell 31de7a7
feat(Building): add BuildingPartRegistry and document multiplayer doo…
hdlmrell eddf87a
docs: fix XML doc generic syntax in OrganicShapeGenerator example
hdlmrell a19bdd0
docs: add advanced building example with terrain, navigation, and net…
hdlmrell 010ef8d
docs: expand building guide with interiors, roofs, terrain, navigatio…
hdlmrell 061f515
docs: add missing param tags to BuildingPartRegistry and NavigationBu…
hdlmrell 04f7427
docs: update api-overview with new building systems and components
hdlmrell 4502bfd
feat(Building): add interior/exterior dual-material support for exter…
hdlmrell c4b9eb3
feat(Building): stair doorway lerp, directed NPC routing, and interio…
hdlmrell a852e7f
fix(Building): replace MonoBehaviour with plain class for BuildingPar…
hdlmrell 9be6d4e
fix(Building): prevent NavMeshAgent re-enable from warping NPCs out o…
hdlmrell 51cebab
fix(Building): remove Vector3.zero guard from agent warp-back restore
hdlmrell b3b1298
docs: add missing XML summaries for Constants.Layers, Tags, and Roof …
hdlmrell 2cef68b
fix(Building): fail fast in CreateNavigationBuilder when no exterior …
hdlmrell 32ac0be
fix(Building): apply floor/ceiling overrides to palette before memoiz…
hdlmrell ea92629
fix(Building): use real stair params in ComputeStairBasePosition nav …
hdlmrell 9be0a3f
fix(Building): guard against negative submeshIndex in SetSubmeshMaterial
hdlmrell 7bcd984
refactor(Building): use NavMeshAgent/CharacterController for living e…
hdlmrell 980e71f
fix(Building): restore HasDestination flag in ReleaseAllNPCs during c…
hdlmrell d9647ef
fix(Building): use ReferenceEquals for chase target null check to det…
hdlmrell 90ee628
feat(Building): expose walkability queries on NavigationBuilder
hdlmrell f988e87
fix(Building): clamp door/window offsets to wall bounds with warning
hdlmrell 2da788b
fix(Building): trigger dual-material walls on interior color-only ove…
hdlmrell acfe35d
docs(ProceduralMesh): fix generic syntax in OrganicShapeGenerator XML…
hdlmrell 111c39f
fix(Building): reject WithInteriorWallLayer after AddInteriorWall
hdlmrell 58fa051
fix(Building): move AddSlidingDoors onCreated callback to pre-activat…
hdlmrell 3207abf
fix(Building): return false for out-of-bounds positions in IsWalkable
hdlmrell 1d3dcd7
fix(Building): include foundation expansion in FlattenTerrain footprint
hdlmrell 11b1aa2
fix(Building): preserve interior doorway metadata across InvalidateBu…
hdlmrell File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,215 @@ | ||
| using System.Collections.Generic; | ||
| using S1MAPI.Building.Config; | ||
| using S1MAPI.Building.Structural; | ||
| using UnityEngine; | ||
|
|
||
| namespace S1MAPI.Building | ||
| { | ||
| /// <summary> | ||
| /// Post-build registry that tracks building parts by category. | ||
| /// Attached to the building root during construction by <see cref="BuildingBuilder"/>. | ||
| /// Consumers use this to target specific parts (all exterior walls, just the north wall, | ||
| /// the floor, trim, etc.) and get their renderers for material swaps. | ||
| /// </summary> | ||
| public sealed class BuildingPartRegistry | ||
| { | ||
| private readonly Dictionary<BuildingPart, List<GameObject>> _parts = new Dictionary<BuildingPart, List<GameObject>>(); | ||
| private readonly Dictionary<WallSide, List<GameObject>> _wallsByDirection = new Dictionary<WallSide, List<GameObject>>(); | ||
|
|
||
| #region Registration (called by BuildingBuilder during construction) | ||
|
|
||
| internal void Register(BuildingPart part, GameObject go) | ||
| { | ||
| if (!_parts.TryGetValue(part, out var list)) | ||
| { | ||
| list = new List<GameObject>(); | ||
| _parts[part] = list; | ||
| } | ||
| list.Add(go); | ||
| } | ||
|
|
||
| internal void Register(WallSide side, GameObject go) | ||
| { | ||
| if (!_wallsByDirection.TryGetValue(side, out var list)) | ||
| { | ||
| list = new List<GameObject>(); | ||
| _wallsByDirection[side] = list; | ||
| } | ||
| list.Add(go); | ||
|
|
||
| Register(BuildingPart.ExteriorWalls, go); | ||
| } | ||
|
|
||
| #endregion | ||
|
|
||
| #region Consumer API — Renderers | ||
|
|
||
| /// <summary> | ||
| /// Get all renderers for a building part category. | ||
| /// </summary> | ||
| /// <param name="part">The building part category to query.</param> | ||
| public Renderer[] GetRenderers(BuildingPart part) | ||
| { | ||
| if (!_parts.TryGetValue(part, out var list)) | ||
| return System.Array.Empty<Renderer>(); | ||
|
|
||
| var renderers = new List<Renderer>(); | ||
| for (int i = 0; i < list.Count; i++) | ||
| { | ||
| if (list[i] != null) | ||
| renderers.AddRange(list[i].GetComponentsInChildren<Renderer>()); | ||
| } | ||
| return renderers.ToArray(); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Get all renderers for a specific wall direction. | ||
| /// </summary> | ||
| /// <param name="side">The specific wall side to query.</param> | ||
| public Renderer[] GetRenderers(WallSide side) | ||
| { | ||
| if (!_wallsByDirection.TryGetValue(side, out var list)) | ||
| return System.Array.Empty<Renderer>(); | ||
|
|
||
| var renderers = new List<Renderer>(); | ||
| for (int i = 0; i < list.Count; i++) | ||
| { | ||
| if (list[i] != null) | ||
| renderers.AddRange(list[i].GetComponentsInChildren<Renderer>()); | ||
| } | ||
| return renderers.ToArray(); | ||
| } | ||
|
|
||
| #endregion | ||
|
|
||
| #region Consumer API — GameObjects | ||
|
|
||
| /// <summary> | ||
| /// Get all GameObjects for a building part category. | ||
| /// </summary> | ||
| /// <param name="part">The building part category to query.</param> | ||
| public GameObject[] GetParts(BuildingPart part) | ||
| { | ||
| if (!_parts.TryGetValue(part, out var list)) | ||
| return System.Array.Empty<GameObject>(); | ||
|
|
||
| var result = new List<GameObject>(list.Count); | ||
| for (int i = 0; i < list.Count; i++) | ||
| { | ||
| if (list[i] != null) | ||
| result.Add(list[i]); | ||
| } | ||
| return result.ToArray(); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Get all GameObjects for a specific wall direction. | ||
| /// </summary> | ||
| /// <param name="side">The specific wall side to query.</param> | ||
| public GameObject[] GetParts(WallSide side) | ||
| { | ||
| if (!_wallsByDirection.TryGetValue(side, out var list)) | ||
| return System.Array.Empty<GameObject>(); | ||
|
|
||
| var result = new List<GameObject>(list.Count); | ||
| for (int i = 0; i < list.Count; i++) | ||
| { | ||
| if (list[i] != null) | ||
| result.Add(list[i]); | ||
| } | ||
| return result.ToArray(); | ||
| } | ||
|
|
||
| #endregion | ||
|
|
||
| #region Consumer API — Material swap | ||
|
|
||
| /// <summary> | ||
| /// Set the material on all renderers for a building part category. | ||
| /// </summary> | ||
| /// <param name="part">The building part category to modify.</param> | ||
| /// <param name="material">The material to apply.</param> | ||
| public void SetMaterial(BuildingPart part, Material material) | ||
| { | ||
| var renderers = GetRenderers(part); | ||
| for (int i = 0; i < renderers.Length; i++) | ||
| renderers[i].material = material; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Set the material on all renderers for a specific wall direction. | ||
| /// </summary> | ||
| /// <param name="side">The specific wall side to modify.</param> | ||
| /// <param name="material">The material to apply.</param> | ||
| public void SetMaterial(WallSide side, Material material) | ||
| { | ||
| var renderers = GetRenderers(side); | ||
| for (int i = 0; i < renderers.Length; i++) | ||
| renderers[i].material = material; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Set the material on a specific submesh index across all renderers for a building part. | ||
| /// Use submesh 0 for exterior faces, submesh 1 for interior faces on dual-material walls. | ||
| /// Renderers with fewer submeshes than <paramref name="submeshIndex"/> are skipped. | ||
| /// </summary> | ||
| /// <param name="part">The building part category to modify.</param> | ||
| /// <param name="material">The material to apply.</param> | ||
| /// <param name="submeshIndex">The submesh index to target (0 = exterior, 1 = interior).</param> | ||
| public void SetMaterial(BuildingPart part, Material material, int submeshIndex) | ||
| { | ||
| var renderers = GetRenderers(part); | ||
| SetSubmeshMaterial(renderers, material, submeshIndex); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Set the material on a specific submesh index across all renderers for a wall direction. | ||
| /// Use submesh 0 for exterior faces, submesh 1 for interior faces on dual-material walls. | ||
| /// Renderers with fewer submeshes than <paramref name="submeshIndex"/> are skipped. | ||
| /// </summary> | ||
| /// <param name="side">The specific wall side to modify.</param> | ||
| /// <param name="material">The material to apply.</param> | ||
| /// <param name="submeshIndex">The submesh index to target (0 = exterior, 1 = interior).</param> | ||
| public void SetMaterial(WallSide side, Material material, int submeshIndex) | ||
| { | ||
| var renderers = GetRenderers(side); | ||
| SetSubmeshMaterial(renderers, material, submeshIndex); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Set the exterior face material on all exterior wall renderers (submesh 0). | ||
| /// Only affects dual-material walls created with <see cref="Config.BuildingPalette.InteriorWallMaterial"/>. | ||
| /// Single-material walls are updated normally. | ||
| /// </summary> | ||
| /// <param name="material">The material to apply to exterior faces.</param> | ||
| public void SetExteriorWallMaterial(Material material) | ||
| { | ||
| SetMaterial(BuildingPart.ExteriorWalls, material, 0); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Set the interior (room-facing) material on all exterior wall renderers (submesh 1). | ||
| /// Only affects dual-material walls. Renderers with a single material are skipped. | ||
| /// </summary> | ||
| /// <param name="material">The material to apply to interior faces.</param> | ||
| public void SetInteriorFaceMaterial(Material material) | ||
| { | ||
| SetMaterial(BuildingPart.ExteriorWalls, material, 1); | ||
| } | ||
|
|
||
| private static void SetSubmeshMaterial(Renderer[] renderers, Material material, int submeshIndex) | ||
| { | ||
| for (int i = 0; i < renderers.Length; i++) | ||
| { | ||
| Material[] mats = renderers[i].materials; | ||
| if (submeshIndex >= 0 && submeshIndex < mats.Length) | ||
| { | ||
| mats[submeshIndex] = material; | ||
| renderers[i].materials = mats; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| #endregion | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.