@adatechnology/game-floorplan-three 0.0.0-stage → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/MIGRATION.md +118 -0
- package/README.md +101 -2
- package/dist/index.d.ts +533 -0
- package/dist/index.global.js +11704 -0
- package/dist/index.global.js.map +1 -0
- package/dist/index.js +8501 -0
- package/dist/index.js.map +1 -0
- package/package.json +69 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Anderson Fernandes
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/MIGRATION.md
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# Migration: Casa3DSDK and AndaresSDK (Visor de casas 3D) to `@adatechnology/game-floorplan-three`
|
|
2
|
+
|
|
3
|
+
The port is literal: the geometry, the draws and the seeded random of `Casa3DSDK.construir` are the team's. Only names changed (English API, texts in `locales`), and
|
|
4
|
+
what the page injected through globals is now an option. The scene equals the page's, node by node, for six plans (`tests/golden-scene.test.ts`, which maps the new ids to the
|
|
5
|
+
legacy ones through `seedKey`), and the level of detail planner gives the same levels in 25 situations.
|
|
6
|
+
|
|
7
|
+
## Entry point
|
|
8
|
+
|
|
9
|
+
| Visor de casas 3D | SDK |
|
|
10
|
+
|---|---|
|
|
11
|
+
| `Casa3DSDK.criar(THREE, cfg)` | `create(THREE, options)` (alias `createHouseRenderer`) |
|
|
12
|
+
| `sdk.construir(res, opts)` | `renderer.build(plan, options)` |
|
|
13
|
+
| `sdk.novoEstado()` | `renderer.newState()` |
|
|
14
|
+
| `sdk.tipos`, `sdk.mv` | `renderer.types` (type to `{ f, source }`), `renderer.mv` (the props module) |
|
|
15
|
+
| `sdk.aplicaParte(grupo, t)` | `renderer.applyPart(group, t)` |
|
|
16
|
+
| `sdk.materiais`, `sdk.mascaraLuz`, `sdk.iluminacao` | `renderer.materials`, `renderer.roomLightMask`, `renderer.lighting` |
|
|
17
|
+
| `sdk.definirNoite(n)` | `renderer.setNight(night)` |
|
|
18
|
+
| `sdk.carros.{modelo,grupo,info}` | `renderer.cars.{model,group,info}` (`info` returns `{ parts, tris, L, W, H }`) |
|
|
19
|
+
| `Casa3DSDK.planejaLOD(casas, foco, orcamento)` | `planLod(houses, focus, budget)` returns `{ total, levels, houses }` |
|
|
20
|
+
|
|
21
|
+
## Options (`cfg` of `criar`)
|
|
22
|
+
|
|
23
|
+
| VC3 | SDK |
|
|
24
|
+
|---|---|
|
|
25
|
+
| `document` | `document` |
|
|
26
|
+
| `qualidade` `'alta'` / `'jogo'` | `quality` `'high'` / `'game'` |
|
|
27
|
+
| `Moveis3DSDK` | `props` (default: `@adatechnology/game-props3d`) |
|
|
28
|
+
| `Reflector` | `reflector` |
|
|
29
|
+
| `frota` | `fleet` |
|
|
30
|
+
| (fixed lists of car models per lot style) | `carKinds` (`budget`, `mid`, `high`; ids of `game-vehicles-fleet`) |
|
|
31
|
+
| `hp` | `hp` |
|
|
32
|
+
| `texturas`, `atlas`, `materiais` | `textures`, `atlas`, `materials` |
|
|
33
|
+
| `destruicao` (world) | `destruction` (world of `game-destruction`) |
|
|
34
|
+
| (the page's own fragment drawing) | `destructionRenderer` (`game-destruction-three`) draws fracture, fragments, spalls and the rebar cage |
|
|
35
|
+
| `interativos` | `interactives` |
|
|
36
|
+
| `vegetacao` | `vegetation` |
|
|
37
|
+
| `lod` `{ interior, ocultar }` | `lod` `{ interior, hide }`, or `false` |
|
|
38
|
+
| `orcamentoDrawCalls` | `drawCallBudget` |
|
|
39
|
+
| `onMudou`, `onColisor`, `onDano`, `onEstrago`, `onInteragir`, `onLuz`, `onMensagem` | `onChange`, `onCollider`, `onDamage`, `onWreck`, `onInteract`, `onLight`, `onMessage` |
|
|
40
|
+
| (ids of the page's plan feed the seeded random) | `seedKey(id)` |
|
|
41
|
+
| (texts in Portuguese in the code) | `locale` (`'en'`, `'pt-BR'` or a table) |
|
|
42
|
+
|
|
43
|
+
## Build options (`opts` of `construir`)
|
|
44
|
+
|
|
45
|
+
| VC3 | SDK |
|
|
46
|
+
|---|---|
|
|
47
|
+
| `qualidade` | `quality` |
|
|
48
|
+
| `noite` | `night` |
|
|
49
|
+
| `corte` | `cut` |
|
|
50
|
+
| `estado` | `state` |
|
|
51
|
+
| `terreno: false` | `terrain: false` |
|
|
52
|
+
| `semPerimetro` | `noPerimeter` |
|
|
53
|
+
| `pecas: 'malhas'` | `pieces: 'meshes'` |
|
|
54
|
+
| `predio` `{ andares, andar, unidade, mostrarPredio }` | `building` `{ floors, floor, unit, showBuilding }` |
|
|
55
|
+
| `orcamentoDrawCalls` | `drawCallBudget` |
|
|
56
|
+
|
|
57
|
+
## The house (result of `construir`)
|
|
58
|
+
|
|
59
|
+
| VC3 | SDK | VC3 | SDK |
|
|
60
|
+
|---|---|---|---|
|
|
61
|
+
| `versao` | `version` | `grupo` | `group` |
|
|
62
|
+
| `casa` | `house` | `grupos` | `groups` (`f0`, `f1`, `t1`, `roof`, `lot`...) |
|
|
63
|
+
| `andares` | `floors` | `forros` | `ceilings` |
|
|
64
|
+
| `telhado` | `roof` | `lote` | `lot` |
|
|
65
|
+
| `chao` | `ground` | `predio` | `building` |
|
|
66
|
+
| `caixaDagua` `{ parte, grupo, pos, planta }` | `waterTank` `{ part, group, pos, plant }` | `colisores` | `colliders` |
|
|
67
|
+
| `partes` | `parts` | `carros` | `cars` |
|
|
68
|
+
| `interagiveis` | `interactables` | `portas` | `doors` |
|
|
69
|
+
| `escadas` | `stairs` | `rotulos` | `labels` |
|
|
70
|
+
| `semModelo` | `noModel` | `luzes` `{ lista, porComodo }` | `lights` `{ list, byRoom }` |
|
|
71
|
+
| `limites` | `limits` | `apt` | `apartment` |
|
|
72
|
+
| `mostraPredio` | `showBuilding` | `predioCfg` `{ andares, andar, unidade }` | `buildingConfig` `{ floors, floor, unit }` |
|
|
73
|
+
| `unidadeRy` | `unitRy` | `noite`, `corte` | `night`, `cut` |
|
|
74
|
+
| `interativos` | `interactives` | `estado` | `state` |
|
|
75
|
+
| `vegetacao`, `solar`, `agua`, `eletrica`, `calhas` | `vegetation`, `solar`, `water`, `electrical`, `gutters` | `estrutura` | `structure` |
|
|
76
|
+
| `destruicao` | `destruction` | `interno` | `internal` |
|
|
77
|
+
|
|
78
|
+
Methods: `atualiza(dt, tempo, foco)` is `update(dt, time, focus)`; `mostra({ andar, corte, lote })` is `show({ floor, cut, lot })`; `alvo` is `target`; `interage` is `interact`;
|
|
79
|
+
`mensagem` is `message`; `alternaPorta` is `toggleDoor`; `luzLigada` is `lightOn`; `alternaLuz` is `toggleLight`; `colide` is `collide`; `comodoEm` is `roomAt`;
|
|
80
|
+
`escolheEspelho` is `chooseMirror`; `definirLOD` is `setLod`; `centro` is `center`; `distancia` is `distance`; `dano` is `damage`; `danoColisor` is `colliderDamage`;
|
|
81
|
+
`parteDe(obj)` is `partOf(object)`; `parteEm(p, tol)` is `partAt(point, tolerance)`; `descartar` is `dispose`.
|
|
82
|
+
|
|
83
|
+
A door of `house.doors`: `{ id, andar, tipo ('aco' or 'giro'), aberta, t, bloq, trancada, macNomes, hT, cx, cz, visH, grupos, col }` is `{ id, floor, type ('steel' or 'swing'), open, t, blockedFlag, locked, handleNames, hT, cx, cz, visH, groups, col }`.
|
|
84
|
+
|
|
85
|
+
## Names of parts, groups and lights
|
|
86
|
+
|
|
87
|
+
| VC3 | SDK | VC3 | SDK |
|
|
88
|
+
|---|---|---|---|
|
|
89
|
+
| `porta:<id>` | `door:<id>` | `janela:<id>` | `window:<id>` |
|
|
90
|
+
| `espelho:<n>` | `mirror:<n>` | `carro:<n>:<zone>:<n>` | `car:<n>:<zone>:<n>` |
|
|
91
|
+
| `torn_<seed>_<n>` (tap) | `tap_<seed>_<n>` | `chuv_<seed>` (shower) | `shower_<seed>` |
|
|
92
|
+
| `correio_<seed>` | `mailbox_<seed>` | `roupas_<seed>` | `laundry_<seed>` |
|
|
93
|
+
| `botijao_<seed>` | `gas_cylinder_<seed>` | `caixa_<seed>` | `tank_<seed>` |
|
|
94
|
+
| `tabuas:<id>` | `boards:<id>` | `disjuntor_<n>` | `breaker_<n>` |
|
|
95
|
+
| light type `externa` | `outdoor` | `ix:`, `lamp_`, `lp_`, `sw_`, `lamp_ab_`, `lamp_ar_`, `lamp_ext_`, `lamp_pe_` | the same (they feed the seeded random) |
|
|
96
|
+
| mesh groups `chapisco`, `reboco`, `calcada`, `madeira`, `vidro`, `telha`, `liso`, `lote/...` | `roughcast`, `plaster`, `sidewalk`, `wood`, `glass`, `tile`, `plain`, `lot/...` | `fonte` of a type (`moveis3d`, `jogo`) | `source` (`props3d`, `game`) |
|
|
97
|
+
|
|
98
|
+
The salts of the seeded random (`'|varal'`, `'|luz'`, `'|temp'`, `'|veg'`...) are kept as the team wrote them: changing one changes the scene.
|
|
99
|
+
|
|
100
|
+
## Messages
|
|
101
|
+
|
|
102
|
+
All the texts the house shows are in `locales` (`en`, `pt-BR`): `prompt.*` (E: abrir a porta...), `what.*`, `message.*`, `outbuilding.*`, `warn.interactablesIncomplete`.
|
|
103
|
+
|
|
104
|
+
## AndaresSDK
|
|
105
|
+
|
|
106
|
+
| AndaresSDK | SDK |
|
|
107
|
+
|---|---|
|
|
108
|
+
| `AndaresSDK.criar()` | `createFloorNavigator()` |
|
|
109
|
+
| `registra({ id, andares: [{ y, h, solidos }], escadas, grupos, telhado, proprio })` | `register({ id, floors: [{ y, h, solids }], stairs, groups, roof, own })` |
|
|
110
|
+
| `casaEm`, `bloqueio(x, z, andar)`, `nivel`, `ponta`, `escadaPara`, `rumo`, `raio`, `tetoDe`, `oclui`, `cel` | `houseAt`, `blocked`, `level`, `landing`, `stairTo`, `heading`, `ray`, `ceilingOf`, `occlude`, `cell` |
|
|
111
|
+
| `aplica(casa, andar)` (internal) | `apply(house, floor)` |
|
|
112
|
+
| (new, T2.4d) | `openCells`, `closeCells`, `undoChanges`, `houseOf` |
|
|
113
|
+
| (new, T2.4d) | `navigationDefOf(house, options)`: the registration of a built house; `bindNavigator(navigator, id, house)`: follows the destruction |
|
|
114
|
+
|
|
115
|
+
## What is not here
|
|
116
|
+
|
|
117
|
+
- `AdaptadorInterativos` (plan to objects of the interactables kit) is game code by its own header. The `interactives` option takes the adapter from the game.
|
|
118
|
+
- The globals of the page (`Moveis3DSDK`, `FrotaLeve`, `Reflector`...) are options now.
|
package/README.md
CHANGED
|
@@ -1,3 +1,102 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @adatechnology/game-floorplan-three
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The three.js renderer of `@adatechnology/game-floorplan`: it draws a generated plan as a house (walls, doors, windows, floors, slabs, stairs, roofs, gutters, lot,
|
|
4
|
+
furniture, lights, mirrors, cars, utilities) and binds it to the destruction of its structure. It is the port of the team's `Casa3DSDK` (Visor de casas 3D) and
|
|
5
|
+
`AndaresSDK` (floor navigator), literally: same geometry, same draws, same seeded random, so a plan looks the same as on the team's page
|
|
6
|
+
(`tests/golden-scene.test.ts` compares the scene node by node with the page's, for six plans).
|
|
7
|
+
|
|
8
|
+
```ts
|
|
9
|
+
import * as THREE from 'three'
|
|
10
|
+
import { engine } from '@adatechnology/game-floorplan'
|
|
11
|
+
import { register as residential } from '@adatechnology/game-floorplan-residential'
|
|
12
|
+
import { register as structure } from '@adatechnology/game-floorplan-structure'
|
|
13
|
+
import { createDestruction } from '@adatechnology/game-destruction'
|
|
14
|
+
import { createDestructionRenderer } from '@adatechnology/game-destruction-three'
|
|
15
|
+
import { create } from '@adatechnology/game-floorplan-three'
|
|
16
|
+
|
|
17
|
+
residential(engine, { region: 'br' })
|
|
18
|
+
structure(engine)
|
|
19
|
+
const plan = engine.generate('townhouse', { seed: 7, state: 'normal' })
|
|
20
|
+
|
|
21
|
+
const world = createDestruction({ seed: 1 })
|
|
22
|
+
const scene = new THREE.Scene()
|
|
23
|
+
const renderer = create(THREE, {
|
|
24
|
+
destruction: world,
|
|
25
|
+
destructionRenderer: createDestructionRenderer(THREE, { scene, world }),
|
|
26
|
+
fleet, // optional: { build(kind, { quality, seed }) } of game-vehicles-fleet
|
|
27
|
+
locale: 'en', // or 'pt-BR', or a table of messages
|
|
28
|
+
})
|
|
29
|
+
const house = renderer.build(plan, { quality: 'high', night: false })
|
|
30
|
+
scene.add(house.group)
|
|
31
|
+
|
|
32
|
+
// every frame
|
|
33
|
+
house.update(dt, performance.now(), camera.position) // doors, laundry, wind, distance LOD
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## What it draws
|
|
37
|
+
|
|
38
|
+
| Part | Where |
|
|
39
|
+
|---|---|
|
|
40
|
+
| walls, doors, windows, floors, slabs, stairs, baseboards, outbuildings, building shell | `house.floors[i]` (one group per floor), `house.doors`, `house.stairs` |
|
|
41
|
+
| lot: ground, street, sidewalk, lot wall, gates, zones, fence | `house.lot` |
|
|
42
|
+
| roof, tiles, gutters | `house.roof`, `house.gutters` |
|
|
43
|
+
| furniture (`game-props3d` plus the house's own builders) | in the floor groups, merged by material; `renderer.types` is the map |
|
|
44
|
+
| lamps, switches, room lights | `house.lights`, `house.toggleLight(room)` |
|
|
45
|
+
| mirrors (the nearest one reflects when the camera is in its room) | `house.chooseMirror(camera)` |
|
|
46
|
+
| cars (needs a `fleet`) | `house.cars`, `renderer.cars` |
|
|
47
|
+
| solar panels, water, electrical, pipes | `house.solar`, `house.water`, `house.electrical` |
|
|
48
|
+
|
|
49
|
+
`house.group` is the root. Everything is merged to one mesh per group and material (a draw call each); only what moves stays apart.
|
|
50
|
+
|
|
51
|
+
## Bound to the destruction
|
|
52
|
+
|
|
53
|
+
With `destruction` (a world of `game-destruction`) and `destructionRenderer` (`game-destruction-three`), the house registers itself in the world on first need
|
|
54
|
+
(`house.destruction.activate()`, or the first hit through `house.damage`):
|
|
55
|
+
|
|
56
|
+
- **One part per wall**, with the assembly of its masonry (units, breach, layers) and **the rebar of reinforced concrete on slabs, beams, pillars and stairs**.
|
|
57
|
+
- **A vertex range per piece.** Every wall, slab, window, door... knows its range in the merged mesh (`house.structure.meshesOf(id)`); the renderer's `bind` gets them,
|
|
58
|
+
so fracture and collapse hide the range and the renderer lets the fragments fall. `house.destruction.reset()` puts everything back.
|
|
59
|
+
- **Brick courses at LOD 0.** A masonry wall that reaches stage 2 stops being a box: its range collapses and it is drawn again as instanced units (running bond,
|
|
60
|
+
one instance per unit) without the ones inside the opening; the units around the edge show the bare brick. At LOD 1 and 2 the box comes back.
|
|
61
|
+
- **Spall decal and rebar cage** come from the destruction renderer (decals on hits, instanced bars when the concrete is exposed).
|
|
62
|
+
- `house.damage(id, point, type, amount)` keeps the legacy behaviour (hp of the part, `onDamage`) and becomes a hit in the world.
|
|
63
|
+
|
|
64
|
+
## Floor navigator
|
|
65
|
+
|
|
66
|
+
`createFloorNavigator()` is the team's AndaresSDK: a 10 cm grid per floor, stairs with banisters and U-turns, path fields, occlusion of the floors above.
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
import { createFloorNavigator, navigationDefOf, bindNavigator } from '@adatechnology/game-floorplan-three'
|
|
70
|
+
|
|
71
|
+
const navigator = createFloorNavigator()
|
|
72
|
+
navigator.register(navigationDefOf(house, { id: 'home', own: true })) // heights, wall colliders, flights, floor groups
|
|
73
|
+
const binding = bindNavigator(navigator, 'home', house) // wall stage 2 opens cells; a wall or slab that falls changes the grid
|
|
74
|
+
navigator.blocked(x, z, floor) // 1 blocked, 0 free, -1 use the ground grid
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Injected, never read from globals
|
|
78
|
+
|
|
79
|
+
| Option | What |
|
|
80
|
+
|---|---|
|
|
81
|
+
| `fleet` | cars (`game-vehicles-fleet`) |
|
|
82
|
+
| `reflector` | `THREE.Reflector` for the mirrors |
|
|
83
|
+
| `props` | `game-props3d` (default: the package's dependency) |
|
|
84
|
+
| `interactives` | `{ GameInteractables, GameInteractablesHousehold, GameInteractablesThree, adapter }`: the interactable kit in place of the static furniture. The adapter (plan to kit objects) is game code, not part of this package. |
|
|
85
|
+
| `vegetation` | `{ GameVegetation: { ...core, ...three }, GameVegetationSpecies }` |
|
|
86
|
+
| `textures`, `atlas`, `materials` | the app's replacements |
|
|
87
|
+
| `seedKey` | maps an id of the plan to the key its seeded draws use (to reproduce a scene drawn with other ids) |
|
|
88
|
+
|
|
89
|
+
Everything the house says to the player (prompts, messages) is in `locales` (`en`, `pt-BR`).
|
|
90
|
+
|
|
91
|
+
## Build
|
|
92
|
+
|
|
93
|
+
`dist/index.js` (ESM, three.js and the other packages external), `dist/index.d.ts`, and `dist/index.global.js` exposing `GameFloorplanThree` (three.js is the page's own `THREE`).
|
|
94
|
+
|
|
95
|
+
See `.claude/skills/game-floorplan-three/SKILL.md` for the API and `MIGRATION.md` for the Portuguese names the Visor de casas 3D used.
|
|
96
|
+
|
|
97
|
+
## Em português
|
|
98
|
+
|
|
99
|
+
Desenho em three.js das plantas do `game-floorplan`: porte literal do `Casa3DSDK` (Visor de casas 3D) e do `AndaresSDK` (navegação por andares). Paredes, portas, janelas,
|
|
100
|
+
pisos, lajes, escadas, telhado, calhas, lote, móveis, luzes, espelhos e carros; cada peça sabe a faixa de vértices que ocupa na malha fundida para a destruição
|
|
101
|
+
(fratura, colapso, fileiras de tijolo no LOD 0, decalque de lascamento e armadura aparente). Os pacotes (frota, interativos, vegetação, espelho) são injetados. Os
|
|
102
|
+
textos vêm de `locales` (`en`, `pt-BR`).
|