tosijs-3d 0.10.4 → 0.10.6
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/CHANGELOG.md +99 -0
- package/README.md +2 -2
- package/dist/anchor-layout.d.ts +60 -0
- package/dist/anchor-layout.d.ts.map +1 -0
- package/dist/anchor-layout.js +140 -0
- package/dist/anchor-layout.js.map +1 -0
- package/dist/b3d-biped.d.ts +17 -3
- package/dist/b3d-biped.d.ts.map +1 -1
- package/dist/b3d-biped.js +83 -14
- package/dist/b3d-biped.js.map +1 -1
- package/dist/b3d-panel.d.ts +10 -1
- package/dist/b3d-panel.d.ts.map +1 -1
- package/dist/b3d-panel.js +21 -0
- package/dist/b3d-panel.js.map +1 -1
- package/dist/b3d-planet.d.ts +28 -0
- package/dist/b3d-planet.d.ts.map +1 -1
- package/dist/b3d-planet.js +301 -52
- package/dist/b3d-planet.js.map +1 -1
- package/dist/b3d-primitives.d.ts +13 -0
- package/dist/b3d-primitives.d.ts.map +1 -1
- package/dist/b3d-primitives.js +57 -10
- package/dist/b3d-primitives.js.map +1 -1
- package/dist/b3d-reflections.js +1 -1
- package/dist/b3d-shadows.d.ts +9 -2
- package/dist/b3d-shadows.d.ts.map +1 -1
- package/dist/b3d-shadows.js +17 -6
- package/dist/b3d-shadows.js.map +1 -1
- package/dist/b3d-star-system.d.ts +36 -3
- package/dist/b3d-star-system.d.ts.map +1 -1
- package/dist/b3d-star-system.js +455 -198
- package/dist/b3d-star-system.js.map +1 -1
- package/dist/b3d-star.d.ts +1 -0
- package/dist/b3d-star.d.ts.map +1 -1
- package/dist/b3d-star.js +48 -59
- package/dist/b3d-star.js.map +1 -1
- package/dist/b3d-svg-plane.d.ts +5 -0
- package/dist/b3d-svg-plane.d.ts.map +1 -1
- package/dist/b3d-svg-plane.js +1 -0
- package/dist/b3d-svg-plane.js.map +1 -1
- package/dist/b3d-utils.d.ts.map +1 -1
- package/dist/b3d-utils.js +2 -0
- package/dist/b3d-utils.js.map +1 -1
- package/dist/box.d.ts +16 -0
- package/dist/box.d.ts.map +1 -1
- package/dist/box.js +155 -16
- package/dist/box.js.map +1 -1
- package/dist/buoyancy.d.ts +11 -0
- package/dist/buoyancy.d.ts.map +1 -1
- package/dist/buoyancy.js +19 -2
- package/dist/buoyancy.js.map +1 -1
- package/dist/carry-box.d.ts +128 -0
- package/dist/carry-box.d.ts.map +1 -0
- package/dist/carry-box.js +809 -0
- package/dist/carry-box.js.map +1 -0
- package/dist/carry.d.ts +52 -0
- package/dist/carry.d.ts.map +1 -0
- package/dist/carry.js +140 -0
- package/dist/carry.js.map +1 -0
- package/dist/demo-utils.d.ts +1 -1
- package/dist/demo-utils.d.ts.map +1 -1
- package/dist/demo-utils.js +1 -1
- package/dist/demo-utils.js.map +1 -1
- package/dist/frame-panel.d.ts +69 -0
- package/dist/frame-panel.d.ts.map +1 -1
- package/dist/frame-panel.js +200 -16
- package/dist/frame-panel.js.map +1 -1
- package/dist/gas-giant.d.ts +1 -1
- package/dist/gas-giant.d.ts.map +1 -1
- package/dist/gas-giant.js +36 -15
- package/dist/gas-giant.js.map +1 -1
- package/dist/index.d.ts +22 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -2
- package/dist/index.js.map +1 -1
- package/dist/inventory-box.d.ts +144 -0
- package/dist/inventory-box.d.ts.map +1 -0
- package/dist/inventory-box.js +1123 -0
- package/dist/inventory-box.js.map +1 -0
- package/dist/inventory.d.ts +193 -0
- package/dist/inventory.d.ts.map +1 -0
- package/dist/inventory.js +495 -0
- package/dist/inventory.js.map +1 -0
- package/dist/landform.d.ts +43 -0
- package/dist/landform.d.ts.map +1 -1
- package/dist/landform.js +84 -11
- package/dist/landform.js.map +1 -1
- package/dist/planet-clouds.d.ts.map +1 -1
- package/dist/planet-clouds.js +9 -3
- package/dist/planet-clouds.js.map +1 -1
- package/dist/planet-map.d.ts.map +1 -1
- package/dist/planet-map.js +2 -3
- package/dist/planet-map.js.map +1 -1
- package/dist/planet-surface-material.d.ts +5 -0
- package/dist/planet-surface-material.d.ts.map +1 -1
- package/dist/planet-surface-material.js +26 -7
- package/dist/planet-surface-material.js.map +1 -1
- package/dist/playground.d.ts +2 -0
- package/dist/playground.d.ts.map +1 -1
- package/dist/playground.js +77 -15
- package/dist/playground.js.map +1 -1
- package/dist/rocky-world.d.ts +73 -0
- package/dist/rocky-world.d.ts.map +1 -0
- package/dist/rocky-world.js +260 -0
- package/dist/rocky-world.js.map +1 -0
- package/dist/scene-schemas.d.ts.map +1 -1
- package/dist/scene-schemas.js +2 -1
- package/dist/scene-schemas.js.map +1 -1
- package/dist/sol.d.ts +3 -0
- package/dist/sol.d.ts.map +1 -0
- package/dist/sol.js +205 -0
- package/dist/sol.js.map +1 -0
- package/dist/solar-system.d.ts +2 -0
- package/dist/solar-system.d.ts.map +1 -0
- package/dist/solar-system.js +150 -0
- package/dist/solar-system.js.map +1 -0
- package/dist/space-backdrop.d.ts +17 -0
- package/dist/space-backdrop.d.ts.map +1 -0
- package/dist/space-backdrop.js +54 -0
- package/dist/space-backdrop.js.map +1 -0
- package/dist/star-material.d.ts +12 -0
- package/dist/star-material.d.ts.map +1 -0
- package/dist/star-material.js +102 -0
- package/dist/star-material.js.map +1 -0
- package/dist/svg-texture.d.ts +9 -0
- package/dist/svg-texture.d.ts.map +1 -1
- package/dist/svg-texture.js +6 -2
- package/dist/svg-texture.js.map +1 -1
- package/dist/system-layout.d.ts +149 -0
- package/dist/system-layout.d.ts.map +1 -0
- package/dist/system-layout.js +168 -0
- package/dist/system-layout.js.map +1 -0
- package/dist/tosi-b3d.d.ts.map +1 -1
- package/dist/tosi-b3d.js +91 -8
- package/dist/tosi-b3d.js.map +1 -1
- package/package.json +2 -2
- package/static/attributes.json +131 -46
- package/static/attributes.txt +44 -16
- package/dist/rocket-ascent.d.ts +0 -20
- package/dist/rocket-ascent.d.ts.map +0 -1
- package/dist/rocket-ascent.js +0 -410
- package/dist/rocket-ascent.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,98 @@ All notable changes to **tosijs-3d**. This project is pre-1.0 (`0.x`), so minor
|
|
|
6
6
|
versions may carry breaking peer-dependency changes — each is called out in a
|
|
7
7
|
**⚠️ Breaking** block in its version section below, with what a consumer must do.
|
|
8
8
|
|
|
9
|
+
## 0.10.6
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- **Flat panels can be placed in screen terms**: `screenAnchor` (on `b3dPanel` and frame panels) pins a panel to the view's edges in pixels, a fraction of the axis (`'5%'`) or of the shorter side (`'3vmin'`), with an anchor point, and `height` sets its size on screen. It is solved with `anchorLayout` every frame and placed square to the screen in the head-locked frame, so a resize or a different window shape keeps it where you put it; it wins over `flatAnchor`'s degrees, which suit a headset, where a panel is around you. The demo loadouts use it: 64 px in, 2vmin down, 14% of the screen tall. Opened, a screen-pinned panel comes to the middle of the screen square to it, not tilted up from below eye level.
|
|
14
|
+
- **A box scrolls with a pointer alone**: a scrollbar on its right edge when its content overflows a fixed height (drag the thumb; press the track to page). A wheel scrolls a box on a page, but a panel in a scene gets no wheel and a headset has none, so a long list was cut off with no way to reach the rest. **Sticky children** (`sticky: true` on a leading run) stay put while the rest scrolls under them: the inventory list's heading and drop row (#3290).
|
|
15
|
+
- **The Biped Playground has the loadout, and the pistol lives on your hip.** Firing mode follows where the pistol is: in a hand the gun is up, on the hip it is down, in the bag or dropped there is nothing to raise. The weapon button draws it from the hip or holsters it, and dragging it into a hand does the same. `b3dBiped`'s new `whenWeapon` (JS) lets a game answer the weapon button itself and call `setGunplay`; `demoLoadout({ equip })` starts with things worn and returns its `inv` (#3305).
|
|
16
|
+
- **The Biped Playground has a pool**: 14 x 10 m, 3.5 m deep, in the far corner past the catwalk, with a shelving ramp at one end to walk in on (where `isSwimming`'s hysteresis is tested) and caustics on the floor. Sunk into the ground, because a biped swims anywhere below the water's height: `b3dGround`'s new `holes` (JS) cuts rectangles out of it, keeping its texture unbroken around them. `playground({ pool: false })` leaves it out.
|
|
17
|
+
- **A drop target.** `inventoryPanel`/`inventoryDock` `handleDrop(item, kind, from)` adds a **drop** row at the top of the list: a thing dropped there leaves the inventory, after the game has had its say (return reasons to refuse and it springs back; otherwise put it in the world). Both demos have one (#3290).
|
|
18
|
+
- **`ui.anchorLayout`, the third layout** beside the flow: positioned and layered. An item is pinned to any edge with an offset (units or a fraction, `'50%'`), with a natural or fixed size; between two pins its size is what they leave and a stated size is a minimum. Its anchor (`anchorX`/`anchorY`, `anchor: 'center'`; default the top left) is the point a pin places and the way a minimum that does not fit overflows. `within` pins it inside a rectangle of the container (a window in the artwork). Paint order is the order given or `z`. Pure and unit-tested; the box mode that uses it is next (#3309).
|
|
19
|
+
- **Things have pictures, and say what they are.** An item kind's `icon` (SVG markup) is drawn on its tile: beside the name in a list, alone and filling a socket, and as the ghost a drag carries. Pointing at a thing, or selecting it with a gamepad, shows an info floater (its name, `description`, mass and what it adds by default; `info` replaces that), drawn in the ghost's layer so nothing clips it. `carryTile` takes `icon` and `info`. The demos load one picture per kind from `/item-icons.json` (#3290).
|
|
20
|
+
- **A frame panel can come to you.** Content that dispatches `panelfocus` (`detail: { focus: true }`) on its SVG brings its panel front and centre (`focusAnchor`, default straight ahead and a little low), enlarged (`focusScale`, default 1.9, at 0.75 m) and always revealed; `focus: false` sends it back. A focused panel never sits inside the camera's near plane (it is pushed out and scaled to look the same size) and is never bigger than the view (it fits 92% of it, allowing for being off-centre), so a monitor shows all of it. `flatAnchor` places a panel somewhere else in the flat view (the shoulder is off a monitor's edge), and `<tosi-b3d-panel>` takes `svg`, `flatAnchor`, `focusAnchor` and `focusScale` as JS properties. A frame panel also grows with its SVG's viewBox now, so content that opens wider gets a wider plane. `inventoryDock` asks for focus as it opens, and the main `tosi-b3d` demo pins your loadout up and to the left (over the shoulder in VR, the top left flat): touch or click it and it comes front and centre with your bag (#3290).
|
|
21
|
+
- **An inventory in 3D: `inventoryDock`.** A loadout that lives on a plane in the scene, flat and in a headset. Closed, it is the schematic alone, small; a tap opens it, with the list beside it (a bag) to drag to and from, and a button closes it. Both are drawn in one SVG, so a drag between them is one plane with one ghost (`carryGhostLayer`). Without a `list` it opens to the schematic alone (a craft fitted from a carrier's stock). Demo: "In 3D" on the inventory-box page, where the loadout replaces the "Inventory" placeholder over your shoulder (top left flat) and a touch brings it front and centre (#3290).
|
|
22
|
+
- **A two-handed weapon shows in both hands**: `inventoryPanel`'s `alsoIn(item, kind, at)` names the other slots an item takes up, where it is drawn faded (and can be picked up from either). The game decides which; the panel only draws it (#3290).
|
|
23
|
+
- **Drag and drop, as a model and on a panel** (INVENTORY-DESIGN step 1). `createCarry` is picking up and putting down with nothing drawn: what is carried and from where, the target under the pointer, and its verdict as REASONS; drop is all or nothing; dragging and two taps are one model, and one carry spans every panel. `carryTile`, `carrySocket` and `carryPanel` draw it on a box: things with decorations (a status bar, a damaged or broken outline, a badge), sockets that light when the held thing would fit, dim when not and say why, and a ghost that follows the pointer. A drag goes from one panel to another (they share the carry), and letting go outside every panel puts the thing back.
|
|
24
|
+
- **An inventory model** (`createInventory`, INVENTORY-DESIGN step 2): pure, with the game's catalogue, rules, contributions and prices plugged in. Holders hold slots (a paper doll, hardpoints, mounts), lists (a bag, a stock) and grids (a hull of boxes). A move is checked against every rule on a copy and kept only if all pass, so it happens completely or not at all; it can swap, split a stack, take from the catalogue, or pay. `stage()` is a draft that may be incomplete (a cart, a barter, a design not yet committed); `totals` adds up what is fitted (and what its mount adds); `damage` crosses off a system's boxes. `craft` runs a recipe (inputs used up, tools required but kept, outputs made, one move) and `compile` turns a finished design into a new kind (a ship class, a learned spell, a forged sword). Tested against a party, a loadout, a starship design, a shop and a smithy.
|
|
25
|
+
- **`inventoryPanel`**: one holder of an inventory on a panel, with drag and drop wired to the model, so a socket lights, dims and explains with the game's own rules. Panels sharing an inventory and a carry are a party, a trade or (with `moveFor` adding a price) a shop.
|
|
26
|
+
- **Schematics**: `inventoryPanel({ schematics: { body: svgText } })` draws a container as art, and its slots go where the art's sockets are (`data-slot="…"`, or ids in a `Sockets` group; `readSchematic` reads one). Sockets on art draw nothing at rest, outline when what is held fits, darken when not, and name themselves and the reason on hover. Demos: equip a person, arm a Manta from a carrier's counted stock, and a shop (its goods left, yours right, the deal in the middle: one `move` that buys, sells and pays, or does none of it). Panels take `height` (a scrolling list), `only`/`hide` (split one holder across panels) and `refuse` (a view's own reasons), and show the holder's purse.
|
|
27
|
+
- **A schematic is drawn at the art's own scale**, cropped to what it draws and shrunk only when the panel is too narrow (`schematicFit`), so a socket designed 44 units square is a 44-unit target, not whatever the file's margins left of it.
|
|
28
|
+
- **The demo schematics are coloured by CSS variables** with defaults for a dark panel (`--schematic-body`, `--schematic-socket`, `--schematic-socket-edge`, `--schematic-label`): a host restyles them on the page, and a texture draws the defaults.
|
|
29
|
+
- **A box child can be placed** (`at: { x, y }`): over the flowed child before it, at that offset, taking no flow space and hit first. Sockets on a schematic are this.
|
|
30
|
+
|
|
31
|
+
### Changed
|
|
32
|
+
|
|
33
|
+
- **The closed loadout is a small picture**: no heading over it and no sockets drawn, only what is in them (all return when open), corners rounded well past the panel's own, 0.125 m wide (was 0.3; `focusScale` 4.56 keeps the opened size), and flat it sits nearer the top-left corner (18° up, was 10°), square to the screen. Frame panel anchors gain `flatOn` (parallel to the frame's view plane rather than turned to face the eye) and `tiltDeg` (tip it about its own horizontal axis without moving it) (#3290).
|
|
34
|
+
- **Inventory list rows are full width**, so a row is a button you can hit anywhere along it. **Swimming starts chest deep** (0.65 submerged, down to 0.5 to stand again; it was waist deep, 0.5 and 0.35), and a swimmer rides a little higher than the last change (12 cm of water above the head bone, was 20; treading unchanged) (#3290).
|
|
35
|
+
- **The opened dock's list is as tall as the loadout beside it** (it scrolls), not a fixed 540 that made the whole dock taller than its picture. `height` still sets it explicitly (#3290).
|
|
36
|
+
- **An inventory panel's heading sits over its schematic's top left** (title, totals, the container's name) instead of stacked above it, so the picture is larger, which matters most on the small pinned loadout. A panel whose first container is not a schematic keeps its heading above (#3290).
|
|
37
|
+
- **SVG panels are mipmapped** (`SvgTexture` `mipmaps`, default `true`: trilinear, anisotropic 4). A panel is nearly always drawn smaller than its texture (1024 px over ~300 px of a Quest 3's view at arm's length), and unfiltered its hairlines broke up and its text crawled; the small pinned loadout's socket outlines were visibly broken and now draw whole. Every in-scene panel, popup and HUD goes through it. Mip generation measured under 0.1 ms per repaint at 1024 px; it costs a third more texture memory. `mipmaps: false` for a texture always seen at about a texel per pixel.
|
|
38
|
+
- **An inventory panel on a page fits the space it is given** instead of being cropped (`fit`, default on): side by side they shrink in proportion, in a column it is no wider than the column, never taller than its container, never larger than drawn, always the same shape. Anything the page sets inline on the host wins (#3290).
|
|
39
|
+
- The default body panels are an inventory over the left shoulder and a **journal** over the right (both were "Inventory") (#3290).
|
|
40
|
+
- `panelScene`'s orbit camera stops at half its starting distance (`camera.minRadius`), so zooming cannot pass through the panel (#3290).
|
|
41
|
+
- **A planet's edge has a golden hour.** Where you see its air edge on and the sun is low over it, the air takes the colour left when its own is scattered out: Earth's goes gold, Mars's dusty air goes blue. The whole lit rim takes it together, by how far the sun has gone behind the planet from where you are: lit from the side, the rim (its "poles" included) stays the air's own colour. Face on, nothing changes (#3285).
|
|
42
|
+
- **The Solar System's sky is tilted as ours is**: the planets orbit about 60.2° to the galaxy's plane, so the Milky Way crosses the orbits steeply instead of running along them (`spaceBackdrop({ tilt })`).
|
|
43
|
+
- **While you carry something, the sockets that would take it light up**, the one under the pointer brighter and named, and the rest go dark. The ghost hangs above the pointer, so the socket you are over stays in sight (#3290).
|
|
44
|
+
- **A panel that shows one list takes a drop anywhere on it**, not just on its tiles or the "put in" row at the bottom of a scrolled list, and is outlined while it would take what you carry. Dragging a thing off a socket back into the bag is a drop on the bag (`carryPanel(box, carry, { fallback })`) (#3290).
|
|
45
|
+
- **A drop that does not land springs back.** Refused by its target, let go on nothing, or released outside every panel, the ghost returns to where it was picked up and shows why it was refused there for a moment. `carryPanel` now returns `dispose`, and `inventoryPanel` calls it on each rebuild (a rebuilt panel used to leave its old carry subscription behind) (#3290).
|
|
46
|
+
|
|
47
|
+
### Fixed
|
|
48
|
+
|
|
49
|
+
- **In a headset, a screen-pinned panel is where its VR anchor says** (found by the release review). Screen pins are for a monitor: in a session they were still applied, putting the loadout a metre ahead, sized from the flat canvas, instead of on your left shoulder. `presentationSpec(spec, flat)` is now the one rule every attach site uses (flat: the flat anchor and screen pins; in VR: neither). Checked in the emulated headset.
|
|
50
|
+
- **Two-tap works on a page** (found by the release review). The page examples cancelled the carry on every `pointerup`, and a tap pick-up happens ON a release, so it was put straight back. `carryOverlay` now cancels a drag let go over nothing itself, after the panels have had the release, and never a tap; the examples no longer add their own.
|
|
51
|
+
- **A press on a panel in the scene no longer also works the game's controls.** The biped reads mouse buttons (the left button is A, a jump), so every press on the playground's loadout made the hero jump, and with a weapon up could fire it. A frame panel now cancels the `pointerdown` it takes, which by the web's own rule stops the matching `mousedown`/`mouseup`; the scene's picking is pointer events and carries on.
|
|
52
|
+
- **A focused panel fits the view a looking-down camera actually has.** Its room was worked out from where it sits in its frame, which is level while a follow camera pitches down; it is now measured in the camera's own view.
|
|
53
|
+
- **Swimmers ride lower.** The water sat at the head bone (the base of the skull), which left a treader's shoulders and arms out and a swimmer's head, shoulders and back riding on top. It now sits 10 cm higher on a treader (at the jaw: the head out) and 20 cm on a swimmer (over the back: the head breaking).
|
|
54
|
+
- **Raising the weapon aims straight ahead.** The aim is the look pitch, which kept whatever it was left at (looking at the ground, the last dive), so the gun often came up pointing at your feet. `setGunplay(true)` levels it, flat only (in a headset the aim is the controller); lowering the weapon leaves the view alone.
|
|
55
|
+
- **First person shows the world, not the back of your head.** Sprinting leans the head 22° forward and swimming far more, and the back and underside of the skull filled the view (measured in the playground: half the screen while sprinting). The head bone is collapsed while in first person, the way first-person games do it, so the arms and body stay (your hands show as you swim); it is restored out of first person, and the shadow is headless while you are in it. The eye now sits along the head's own axes, 10 cm up the skull, rather than offset along the body's level facing (#3291).
|
|
56
|
+
- **Aiming down while swimming dives.** At the surface a swimmer's buoyancy (set so the swim pose floats on the waterline) lifted about as fast as a downward stroke sank, so pitching down with the right stick and swimming went nowhere, and up is capped at the surface by design: the stick seemed to do nothing either way. A stroke aimed down now takes the vertical from buoyancy in proportion to how steeply and how hard you swim (`diveBuoyancy`); let go and buoyancy surfaces you as before. Measured in the new pool: 1.3 m deeper in two seconds, where it was 0.3.
|
|
57
|
+
- **An open inventory survives entering or leaving a headset.** Opened flat, then into VR, the loadout came up small on its shoulder still showing the bag, and a tap did nothing (it was already open), there and back out. A session change rebuilds the frame panels, and the new one never heard the dock's `panelfocus`. Content now also marks its SVG `data-focus="true"` while focused, and a frame panel made later starts from it (#3290).
|
|
58
|
+
- **A sun's shadows can be turned off**: `<tosi-b3d-sun shadows="off">` (`'on'` by default; live, so a toggle works). The demos, the README and this repo's notes passed `shadowCascading: true`, which was never an attribute: shadows are always cascaded, and `shadowCascading: false` silently did nothing. It is gone from every example.
|
|
59
|
+
- **No more fine bands over every lit surface.** `<tosi-b3d-sun>`'s `shadowBias` default is 0.0005 (was Babylon's 0.00005). With `shadowNormalBias` at 0.02, which has to stay low or thin limbs lose their shadow, plain scenes (the primitives and getting-started demos) were striped with shadow acne on the ground, the boxes and the spheres. A character's shadow is unchanged. The attribute table also said `shadowNormalBias` defaulted to 0.05; it is 0.02.
|
|
60
|
+
- **The checker ground is checkered.** `b3dGround({ texture: 'checker' })` drew one flat grey: the texture clamped at its edge instead of repeating, so every tile past the first was the edge colour. It repeats now, and is mipmapped so it does not shimmer toward the horizon. Its dark squares are 70% of the ground colour (they were a fixed grey barely darker than the default ground).
|
|
61
|
+
- **Getting started opens on a running scene**: the first scene is a live example, and below it the same scene as plain HTML markup, live too.
|
|
62
|
+
- **A star system keeps real time.** Every day, month and year is the real one, and a new `timeScale` attribute (simulated seconds per real second, default 3600: an hour a second, an Earth day in 24 seconds) says how fast it runs; both demos have a log **time** slider from real time to a year every ten seconds. Planets used to turn once in about 80 seconds against a 60-second year, so they looked still, and moons took longer to go round their planet than the planet took to go round the Sun. Now `SystemPlanetSpec.day` (Earth days, negative backwards) and `SystemBodySpec.period` (a moon's month in days, negative backwards) carry the truth for Sol (Venus and Uranus turn backwards, Triton goes round backwards); a generated moon gets Kepler's month for a true distance (`moonPeriod`), a generated rock an Earth day, a giant a Jupiter one. Orbits, months and days are angles of one clock (`spinAngle`), so they keep time together and stop together with `animate`.
|
|
63
|
+
- **Dragging on a frame panel no longer turns the camera.** Flat, the camera's own controls took the same pointer, so a drag across a panel orbited the view behind it. A press on a frame panel now holds the camera's controls until release (#3290).
|
|
64
|
+
- **A drag that leaves its panel at once still drags.** A press on a thing, then a pointer that was already over another panel by its next move (a controller ray moves in big steps; so does a fast flick), forgot the press and dragged nothing. Leaving a panel with a thing pressed now starts the drag. Found driving the loadout with an emulated controller (#3290).
|
|
65
|
+
- **A trigger press in VR always counts, whichever hand it is.** Babylon points with one controller, the first to connect, and a press on the other one only switched to it: the press was dropped, so the first press of a session (and any press after the headset swapped controllers) did nothing. Now the right hand points first, and a press on the hand that is not pointing switches to it and is delivered. It reads Babylon's private per-controller state; a Babylon upgrade that renames it brings back the dropped press rather than breaking anything (#3290).
|
|
66
|
+
- An inventory panel's totals line is always there, so the first thing worn no longer pushes the schematic down (#3290).
|
|
67
|
+
- **Dragging between inventory panels works with a finger or a headset's laser.** Both are captured by the element they press, so the moves and the release never reached another panel; `inventoryPanel` now lets the capture go as it arrives (a mouse was never captured, which is why it worked on a desktop). And on a page the ghost is drawn in one overlay above every panel (`carryOverlay(carry)`, with `carryPanel(…, { ghost: false })`), so it crosses from one panel to the next instead of being clipped by each. A panel on a 3D plane keeps its own ghost (#3290).
|
|
68
|
+
|
|
69
|
+
- **A thing can be dragged out of a socket** (it could only be dragged out of a list), and a thing in a list is itself a place to drop into that list, so a long, scrolled list takes a drop anywhere. A thing put back in a list joins a stack of its kind with room (a missile returned to the carrier is counted again); one drawn from a stack swaps with what a slot held.
|
|
70
|
+
|
|
71
|
+
Size: barrel (min, packages external) 1082.1 KB raw / 368.9 KB gz, +3.80% on 0.10.5.
|
|
72
|
+
|
|
73
|
+
## 0.10.5
|
|
74
|
+
|
|
75
|
+
### Added
|
|
76
|
+
|
|
77
|
+
- **The Solar System demo** (Demos): our own system from the library's parts, every planet and moon a planet, Phobos, Deimos, Vesta and Pallas as lumpy rocks, the asteroid belt, a `look at` camera that follows a body from its sunlit side, and **real maps** for the Earth, the Moon and Mars at the flick of a toggle. `SOL` is the system as data; a star system draws any `SystemSpec` you give its `system` property (`maps="on"` uses a body's real maps), and `layoutSystem` takes known moons and belt bodies. A new `ice` world (Europa, Enceladus, Triton).
|
|
78
|
+
- **Rocky worlds: `<tosi-b3d-planet world="moon">`.** `ROCKY_WORLDS` has the Moon, Mercury, Mars, Venus, Io, Titan and an Earth as data (sea and its colour, air, clouds, relief, craters, climate, and for Io and Titan their own ground colours), the rocky half of `GAS_GIANTS`. `world` is a preset: choosing one writes its values into the planet's own settings, which stay yours to tune (`worldOverrides` changes the preset for one planet). A planet takes `seaShallow`/`seaDeep` for its sea's colour (Titan's methane). The colours are the biome chart's (a dry warm world is red, a dry cold one grey).
|
|
79
|
+
- **`spaceBackdrop()`: space, set up once.** A sun and the airless star sky with the galaxy tilted off the scene's plane, to spread into a `b3d(…)`. The planet, gas giant and planet-map demos share it (untilted, the Milky Way ran exactly along Saturn's rings). Defaults to the pinned versioned sky, `PINNED_SKY_URL`. The planet demo has a world picker.
|
|
80
|
+
- **A star system is made of real planets.** `<tosi-b3d-star-system>` draws every body as a `<tosi-b3d-planet>`: giants banded and ringed, rocky worlds picked from what the generator says about each (`rockyWorldFor`: airless rock, seas, a toxic hot sky, or dust), moons locked to their planets, and an asteroid belt (`beltCount` rocks, thin-instanced, with its few big bodies picked out) in a wide gap before the first giant. Its `bodies` list names every planet, moon and named asteroid with the node that carries it, and the demo's `look at` follows one with the camera, under the shared star sky (`spaceBackdrop({ sun: false })`: a system lights itself). ⚠️ It looks different: distances are on a log scale and sizes on a square root (`system-layout`, pure and tested), so a system fits on a screen without being empty.
|
|
81
|
+
- **Craters on a planet.** `sphereCraters` (landform) is `craterField` on a whole body: no seam, no squeeze at the poles, and an `asymmetry` toward a direction, for a tidally locked moon's leading side. A planet takes `craters`, `craterSize`, `craterWear` and `craterAsymmetry`, or its `world`'s. `craterProfile` is the one crater shape both share.
|
|
82
|
+
|
|
83
|
+
### Removed
|
|
84
|
+
|
|
85
|
+
- ⚠️ **The Rocket Ascent demo and `rocketAscent()`**, outdated; the Solar System demo replaces it in the demos.
|
|
86
|
+
|
|
87
|
+
### Changed
|
|
88
|
+
|
|
89
|
+
- **Stars look like stars.** `<tosi-b3d-star>` and a star system's star share one surface material (`star-material`): white-hot in the middle and shading into the star's own colour toward a darker limb (only a warm star reddens there), slowly boiling granulation and a few sunspots; the glow peaks at the edge and fades outward instead of washing the disc out. They were a flat emissive colour, a white ball. The spectral colours are stylised so each class reads as its own: O white with a trace of violet, B violet-blue, A blue, F green, G a clear yellow (the Sun too), K orange, M red.
|
|
90
|
+
- **Gas giants tear at their band edges.** Turbulence is eddies where the wind reverses, in patches along the edges, instead of a warp that made every band wavy; inside a band the texture is billow filaments along the wind. A storm brighter than the zones (Neptune's) is dark with bright cloud at its rim.
|
|
91
|
+
- **A planet's ring lies in its equator.** It was tipped off it, and as the planet turned the ring precessed.
|
|
92
|
+
|
|
93
|
+
### Fixed
|
|
94
|
+
|
|
95
|
+
- **A gas giant's storm had a seam** where its swirl read noise at an angle that jumps a full turn.
|
|
96
|
+
- **Gas giant poles had a dark blotch**, a cap of a different colour; the bands now close in on the pole, a little darker.
|
|
97
|
+
- **Rings are sharp, and no longer flicker.** The density along the radius is 1D noise at several scales, terraced into plateaus of different widths with edges about a pixel wide, under a broad profile (faint inside, brightest a little out), with a wide gap and a narrow one cut clean. A shepherd moon's wake ripples the edges either side of the narrow gap. Only detail finer than a pixel fades to its average, which is what stopped the flicker; the band frequency no longer grows with the seed.
|
|
98
|
+
|
|
99
|
+
Size: barrel (min, packages external) 1042.5 KB raw / 353.5 KB gz, +3.67% on 0.10.4.
|
|
100
|
+
|
|
9
101
|
## 0.10.4
|
|
10
102
|
|
|
11
103
|
### Added
|
|
@@ -63,6 +155,13 @@ versions may carry breaking peer-dependency changes — each is called out in a
|
|
|
63
155
|
|
|
64
156
|
### Fixed
|
|
65
157
|
|
|
158
|
+
- **A dry world's crater floors were drawn as sea bed**, a flat dark patch: the classifier took the zero height for a sea. A world with no sea now has none under its ground, and its classifier works at the planet's own scale (a datum at 0.001 had put its noise past float precision).
|
|
159
|
+
- **Small bodies in a star system were coarse** (a belt body's mesh was 16 divisions a face, so crater rims drew straight lines across Ceres); moons and named asteroids are 40 now.
|
|
160
|
+
- **A large planet was frozen and speckled.** The biome's lengths (height cooling, climate noise, dither, strata, the latitude wobble, surf) were tuned on radius 50; they scale with the planet's radius now, so a radius-3000 world reads as one at 50 does (board #3280, from Manta).
|
|
161
|
+
- **A world's volcanism outlived it**: Io's glowing plates stayed on the next world chosen.
|
|
162
|
+
- **A planet's cooling with height stuck from its first build**, so a dry world chosen after one with a sea was frozen pale.
|
|
163
|
+
- **Planet clouds can close**: `clouds` runs past 1, to 3 for a solid deck (Venus); at 1 it still left holes.
|
|
164
|
+
- **Rock on a planet was blocky.** The cliff test read a slope that was constant across each triangle (from screen derivatives), so bare rock stepped in squares. On land, and anywhere on a world with no sea, it reads the mesh's own smooth normal now; only a sea bed, held flat in the mesh, still needs the derivative one.
|
|
66
165
|
- **A sphere world was drier than a flat one.** The rain shadow's wind was fixed in the planet's frame, so level ground on one side of the planet read as a leeward slope everywhere, about 0.12 off the moisture. The wind now blows along the ground: slopes still get wet and dry sides, level ground gets neither. The decorator's mirror of it had the same bias and now has none.
|
|
67
166
|
- **Changing a terrain's `surfaceType` or radius rebuilds its surface.** The sampler was built once at scene-ready, so the tiles kept the old shape while everything that reads the radius live moved on.
|
|
68
167
|
- **Land and Sky: the eye height slider works in a headset.** It moved the flat camera only; the headset's rig took its height once, on entry.
|
package/README.md
CHANGED
|
@@ -17,7 +17,7 @@ markup you can read:
|
|
|
17
17
|
|
|
18
18
|
```javascript
|
|
19
19
|
b3d(
|
|
20
|
-
b3dSun(
|
|
20
|
+
b3dSun(),
|
|
21
21
|
b3dSkybox({ timeOfDay: 6 }),
|
|
22
22
|
b3dLoader({ url: './scene.glb' }),
|
|
23
23
|
b3dWater({ y: -0.2 })
|
|
@@ -45,7 +45,7 @@ import { b3d, b3dSun, b3dSkybox, b3dGround, b3dBox, b3dSphere } from 'tosijs-3d'
|
|
|
45
45
|
|
|
46
46
|
document.body.append(
|
|
47
47
|
b3d(
|
|
48
|
-
b3dSun(
|
|
48
|
+
b3dSun(),
|
|
49
49
|
b3dSkybox({ timeOfDay: 10 }),
|
|
50
50
|
b3dGround({ size: 24, texture: 'checker' }),
|
|
51
51
|
b3dBox({ x: -1.5, y: 0.5, color: '#c8553d' }),
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/** A length: layout units, or a fraction of the container (`'50%'`). */
|
|
2
|
+
export type AnchorLength = number | `${number}%`;
|
|
3
|
+
/** A rectangle, top-left origin, in layout units. */
|
|
4
|
+
export interface AnchorBox {
|
|
5
|
+
x: number;
|
|
6
|
+
y: number;
|
|
7
|
+
width: number;
|
|
8
|
+
height: number;
|
|
9
|
+
}
|
|
10
|
+
export interface AnchorItem {
|
|
11
|
+
left?: AnchorLength;
|
|
12
|
+
right?: AnchorLength;
|
|
13
|
+
top?: AnchorLength;
|
|
14
|
+
bottom?: AnchorLength;
|
|
15
|
+
/**
|
|
16
|
+
* The point of the item a pin places, as a fraction of its width: 0 its
|
|
17
|
+
* left edge (default), 0.5 its centre, 1 its right edge. Between two pins,
|
|
18
|
+
* which way a minimum that does not fit overflows.
|
|
19
|
+
*/
|
|
20
|
+
anchorX?: number;
|
|
21
|
+
/** The same, of its height: 0 its top edge (default). */
|
|
22
|
+
anchorY?: number;
|
|
23
|
+
/** Both anchors at once: `'center'` is `anchorX: 0.5, anchorY: 0.5`. */
|
|
24
|
+
anchor?: 'center';
|
|
25
|
+
/** Exact with one pin or none; a minimum between two pins. */
|
|
26
|
+
width?: AnchorLength;
|
|
27
|
+
/** Exact with one pin or none; a minimum between two pins. */
|
|
28
|
+
height?: AnchorLength;
|
|
29
|
+
/** Paint order; higher is on top. Default 0, ties keep the order given. */
|
|
30
|
+
z?: number;
|
|
31
|
+
/**
|
|
32
|
+
* The item's natural size: called with no width for its natural width,
|
|
33
|
+
* then with the resolved width for its height. Leave `width` out of the
|
|
34
|
+
* answer to fill what it is given. Absent: no natural size, so it fills
|
|
35
|
+
* what it is given on both axes.
|
|
36
|
+
*/
|
|
37
|
+
measure?: (width?: number) => {
|
|
38
|
+
width?: number;
|
|
39
|
+
height: number;
|
|
40
|
+
};
|
|
41
|
+
/** Pin within this rectangle of the container instead of its edges. */
|
|
42
|
+
within?: AnchorBox;
|
|
43
|
+
}
|
|
44
|
+
export interface AnchorResult {
|
|
45
|
+
/** One box per item, in the order given. */
|
|
46
|
+
boxes: AnchorBox[];
|
|
47
|
+
/** Item indices bottom to top: paint in this order, hit-test from the end. */
|
|
48
|
+
order: number[];
|
|
49
|
+
}
|
|
50
|
+
/** A length in layout units, given the size a fraction is of. */
|
|
51
|
+
export declare function anchorLength(v: AnchorLength, of: number): number;
|
|
52
|
+
/**
|
|
53
|
+
* Lay out `items` in a container `width` x `height`. Returns a box per item
|
|
54
|
+
* and the order to paint them in.
|
|
55
|
+
*/
|
|
56
|
+
export declare function anchorLayout(items: AnchorItem[], container: {
|
|
57
|
+
width: number;
|
|
58
|
+
height: number;
|
|
59
|
+
}): AnchorResult;
|
|
60
|
+
//# sourceMappingURL=anchor-layout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anchor-layout.d.ts","sourceRoot":"","sources":["../src/anchor-layout.ts"],"names":[],"mappings":"AA4EA,wEAAwE;AACxE,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,GAAG,MAAM,GAAG,CAAA;AAEhD,qDAAqD;AACrD,MAAM,WAAW,SAAS;IACxB,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,CAAC,EAAE,YAAY,CAAA;IACnB,KAAK,CAAC,EAAE,YAAY,CAAA;IACpB,GAAG,CAAC,EAAE,YAAY,CAAA;IAClB,MAAM,CAAC,EAAE,YAAY,CAAA;IACrB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,yDAAyD;IACzD,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,wEAAwE;IACxE,MAAM,CAAC,EAAE,QAAQ,CAAA;IACjB,8DAA8D;IAC9D,KAAK,CAAC,EAAE,YAAY,CAAA;IACpB,8DAA8D;IAC9D,MAAM,CAAC,EAAE,YAAY,CAAA;IACrB,2EAA2E;IAC3E,CAAC,CAAC,EAAE,MAAM,CAAA;IACV;;;;;OAKG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,KAAK;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;IAChE,uEAAuE;IACvE,MAAM,CAAC,EAAE,SAAS,CAAA;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,4CAA4C;IAC5C,KAAK,EAAE,SAAS,EAAE,CAAA;IAClB,8EAA8E;IAC9E,KAAK,EAAE,MAAM,EAAE,CAAA;CAChB;AAED,iEAAiE;AACjE,wBAAgB,YAAY,CAAC,CAAC,EAAE,YAAY,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAGhE;AAuCD;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,UAAU,EAAE,EACnB,SAAS,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC3C,YAAY,CAoCd"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/*#
|
|
2
|
+
# anchor-layout
|
|
3
|
+
|
|
4
|
+
Pure **anchored layout**: the third way to lay out the SVG UI, beside the
|
|
5
|
+
flow ([flow-layout](/flow-layout/)). Where the flow stacks and wraps, this
|
|
6
|
+
**positions and layers**: each item is pinned to the edges of its container
|
|
7
|
+
(or to a named rectangle inside it, such as a window in a piece of artwork),
|
|
8
|
+
and is drawn over whatever came before it. A HUD, widgets composed onto
|
|
9
|
+
artwork, a desktop-style window with its title bar and close button: all of
|
|
10
|
+
these are this.
|
|
11
|
+
|
|
12
|
+
Like the flow it is pure (no DOM, no Babylon), measured in layout units, and
|
|
13
|
+
re-run whenever the container changes size.
|
|
14
|
+
|
|
15
|
+
## The rule, per axis
|
|
16
|
+
|
|
17
|
+
Horizontally (vertically the same, with `top`, `bottom`, `anchorY` and
|
|
18
|
+
`height`):
|
|
19
|
+
|
|
20
|
+
| Pins | Width | Where |
|
|
21
|
+
| --- | --- | --- |
|
|
22
|
+
| `left` and `right` | what the pins leave, but never less than `width` (a stated width is a MINIMUM) | between the pins; a minimum that does not fit overflows by the anchor |
|
|
23
|
+
| `left` | `width`, else the item's natural width | its anchor point at `left` |
|
|
24
|
+
| `right` | the same | its right edge at `right` from the right edge (its anchor point, if you give one) |
|
|
25
|
+
| none | the same | as `left: 0` |
|
|
26
|
+
|
|
27
|
+
An offset or a size is a number (layout units) or a **fraction** of the
|
|
28
|
+
container, written `'50%'`.
|
|
29
|
+
|
|
30
|
+
**The anchor** is the point of the ITEM that a pin places, as fractions of its
|
|
31
|
+
own size: `anchorX` 0 is its left edge, 0.5 its centre, 1 its right edge. The
|
|
32
|
+
default is the TOP LEFT, to keep surprises down, so `left: '50%'` puts the left
|
|
33
|
+
edge at the middle and **`anchor: 'center'` with `left: '50%'` and `top: '50%'`
|
|
34
|
+
centres an item**. A lone `right` (or `bottom`) pin places the right (bottom)
|
|
35
|
+
edge unless an anchor is given, or a default top-left anchor would hang the
|
|
36
|
+
item outside the container.
|
|
37
|
+
|
|
38
|
+
**The anchor also decides overflow.** Between two pins the item is stretched;
|
|
39
|
+
when its minimum does not fit, the anchor says which way the excess goes: 0
|
|
40
|
+
runs past the right pin (as CSS's `min-width` does), 1 past the left, 0.5
|
|
41
|
+
spills evenly both ways. It is never squashed below its minimum.
|
|
42
|
+
|
|
43
|
+
- **Width comes first.** The item is then asked for its height AT that width,
|
|
44
|
+
so text in a stretched item wraps to the width it was given.
|
|
45
|
+
- **An item with no natural width** (a block that fills what it is given)
|
|
46
|
+
fills from its pin to the opposite edge, or the whole width with no pin.
|
|
47
|
+
- **Layers** paint in the order given unless an item has a `z` (higher is
|
|
48
|
+
on top; equal `z` keeps the order given). `order` lists the items bottom
|
|
49
|
+
to top; hit-test it from the end.
|
|
50
|
+
- **`within`** is a rectangle inside the container (a window in the art, by
|
|
51
|
+
name, measured by the caller) that the item's pins and fractions are
|
|
52
|
+
measured against instead of the container's edges.
|
|
53
|
+
|
|
54
|
+
## Example
|
|
55
|
+
|
|
56
|
+
```javascript
|
|
57
|
+
import { ui } from 'tosijs-3d'
|
|
58
|
+
const { anchorLayout } = ui
|
|
59
|
+
|
|
60
|
+
// A 400 x 300 window: a title bar across the top, a close button in its
|
|
61
|
+
// corner, content filling the rest, and a dialog centred over it all.
|
|
62
|
+
const { boxes } = anchorLayout(
|
|
63
|
+
[
|
|
64
|
+
{ left: 0, right: 0, top: 0, height: 28 },
|
|
65
|
+
{ right: 4, top: 4, width: 20, height: 20 },
|
|
66
|
+
{ left: 0, right: 0, top: 28, bottom: 0 },
|
|
67
|
+
{ left: '50%', top: '50%', anchor: 'center', width: '60%', height: 120 },
|
|
68
|
+
],
|
|
69
|
+
{ width: 400, height: 300 }
|
|
70
|
+
)
|
|
71
|
+
// boxes[0] = { x: 0, y: 0, width: 400, height: 28 }
|
|
72
|
+
// boxes[3] = { x: 80, y: 90, width: 240, height: 120 }
|
|
73
|
+
```
|
|
74
|
+
*/
|
|
75
|
+
/*{ "parent": "box", "order": 11 }*/
|
|
76
|
+
/** A length in layout units, given the size a fraction is of. */
|
|
77
|
+
export function anchorLength(v, of) {
|
|
78
|
+
if (typeof v === 'number')
|
|
79
|
+
return v;
|
|
80
|
+
return (parseFloat(v) / 100) * of;
|
|
81
|
+
}
|
|
82
|
+
/** Size and offset along one axis; `natural` is the item's own size, if any. */
|
|
83
|
+
function solveAxis(a, span, natural) {
|
|
84
|
+
const L = (v) => anchorLength(v, span);
|
|
85
|
+
const stated = a.size != null ? L(a.size) : undefined;
|
|
86
|
+
const anchor = a.anchor ?? 0;
|
|
87
|
+
if (a.start != null && a.end != null) {
|
|
88
|
+
const at = L(a.start);
|
|
89
|
+
const between = span - at - L(a.end);
|
|
90
|
+
const size = Math.max(between, stated ?? 0);
|
|
91
|
+
return { at: at - anchor * (size - between), size };
|
|
92
|
+
}
|
|
93
|
+
const own = (room) => stated ?? natural() ?? room;
|
|
94
|
+
if (a.start != null) {
|
|
95
|
+
const p = L(a.start);
|
|
96
|
+
const size = own(span - p);
|
|
97
|
+
return { at: p - anchor * size, size };
|
|
98
|
+
}
|
|
99
|
+
if (a.end != null) {
|
|
100
|
+
const p = span - L(a.end);
|
|
101
|
+
const size = own(p);
|
|
102
|
+
return { at: p - (a.anchor ?? 1) * size, size };
|
|
103
|
+
}
|
|
104
|
+
const size = own(span);
|
|
105
|
+
return { at: -anchor * size, size };
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Lay out `items` in a container `width` x `height`. Returns a box per item
|
|
109
|
+
* and the order to paint them in.
|
|
110
|
+
*/
|
|
111
|
+
export function anchorLayout(items, container) {
|
|
112
|
+
const boxes = items.map((it) => {
|
|
113
|
+
const r = it.within ?? {
|
|
114
|
+
x: 0,
|
|
115
|
+
y: 0,
|
|
116
|
+
width: container.width,
|
|
117
|
+
height: container.height,
|
|
118
|
+
};
|
|
119
|
+
const centre = it.anchor === 'center' ? 0.5 : undefined;
|
|
120
|
+
const h = solveAxis({
|
|
121
|
+
start: it.left,
|
|
122
|
+
end: it.right,
|
|
123
|
+
anchor: it.anchorX ?? centre,
|
|
124
|
+
size: it.width,
|
|
125
|
+
}, r.width, () => it.measure?.().width);
|
|
126
|
+
const v = solveAxis({
|
|
127
|
+
start: it.top,
|
|
128
|
+
end: it.bottom,
|
|
129
|
+
anchor: it.anchorY ?? centre,
|
|
130
|
+
size: it.height,
|
|
131
|
+
}, r.height, () => it.measure?.(h.size).height);
|
|
132
|
+
return { x: r.x + h.at, y: r.y + v.at, width: h.size, height: v.size };
|
|
133
|
+
});
|
|
134
|
+
const order = items
|
|
135
|
+
.map((it, i) => ({ z: it.z ?? 0, i }))
|
|
136
|
+
.sort((a, b) => a.z - b.z || a.i - b.i)
|
|
137
|
+
.map((o) => o.i);
|
|
138
|
+
return { boxes, order };
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=anchor-layout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anchor-layout.js","sourceRoot":"","sources":["../src/anchor-layout.ts"],"names":[],"mappings":"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"}
|
package/dist/b3d-biped.d.ts
CHANGED
|
@@ -219,9 +219,16 @@ export declare class B3dBiped extends B3dControllable {
|
|
|
219
219
|
/** Eye position for first-person: the head bone (or eyeHeight fallback) nudged
|
|
220
220
|
* up + forward to roughly the eyes, so the camera sits at the eyes rather than
|
|
221
221
|
* the neck / head-bone base — which would leave the head & neck in front of the
|
|
222
|
-
* view.
|
|
223
|
-
*
|
|
224
|
-
|
|
222
|
+
* view. Returns a cached vector — read it now, don't retain.
|
|
223
|
+
*
|
|
224
|
+
* ALONG THE HEAD'S OWN AXES, not the body's. A sprint leans the head 22°
|
|
225
|
+
* forward and a swim far more, and an offset along the body's level facing
|
|
226
|
+
* left the eye inside the skull: in first person the back of your own head
|
|
227
|
+
* filled the screen as you ran (Tonio: "first person view when swimming is a
|
|
228
|
+
* disaster and it's still a big problem when running"). The UAL head bone's
|
|
229
|
+
* forward is the face's, measured. Only the eye's POSITION follows the head;
|
|
230
|
+
* the view's orientation does not (no bob in the rotation, no roll). */
|
|
231
|
+
getHeadPosition(extraForward?: number): BABYLON.Vector3 | null;
|
|
225
232
|
xrStuff?: XRStuff;
|
|
226
233
|
private xrInputProvider?;
|
|
227
234
|
animationState?: AnimState;
|
|
@@ -302,6 +309,13 @@ export declare class B3dBiped extends B3dControllable {
|
|
|
302
309
|
*/
|
|
303
310
|
gunplay: boolean;
|
|
304
311
|
private weaponWasPressed;
|
|
312
|
+
/**
|
|
313
|
+
* What the weapon button does, when a game decides (JS only). Called with
|
|
314
|
+
* whether the button asks for the weapon UP; the game moves it (draw from
|
|
315
|
+
* the hip, holster it) and calls `setGunplay` if and when it is in hand.
|
|
316
|
+
* Unset, the button toggles `gunplay` as before.
|
|
317
|
+
*/
|
|
318
|
+
whenWeapon: ((up: boolean) => void) | null;
|
|
305
319
|
/**
|
|
306
320
|
* Put the weapon up or down.
|
|
307
321
|
*
|
package/dist/b3d-biped.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"b3d-biped.d.ts","sourceRoot":"","sources":["../src/b3d-biped.ts"],"names":[],"mappings":"AAkOA,OAAO,KAAK,OAAO,MAAM,iBAAiB,CAAA;AAC1C,OAAO,EACL,OAAO,EAKR,MAAM,gBAAgB,CAAA;
|
|
1
|
+
{"version":3,"file":"b3d-biped.d.ts","sourceRoot":"","sources":["../src/b3d-biped.ts"],"names":[],"mappings":"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"}
|
package/dist/b3d-biped.js
CHANGED
|
@@ -226,7 +226,7 @@ document.body.append(
|
|
|
226
226
|
import * as BABYLON from '@babylonjs/core';
|
|
227
227
|
import { collidable, isOff, markUiMesh, refuseOwnAncestor, } from './b3d-utils.js';
|
|
228
228
|
import { CLIMB_PHASE, canMantle, mantleClip, mantlePath, defaultMantleLimits, } from './mantle.js';
|
|
229
|
-
import { buoyantStep, submergedFraction, isSwimming, swimBuoyancy, } from './buoyancy.js';
|
|
229
|
+
import { buoyantStep, diveBuoyancy, submergedFraction, isSwimming, swimBuoyancy, } from './buoyancy.js';
|
|
230
230
|
import { aimFromLook, clampAim, easeAim, aimTarget, surfaceAimLimit, } from './swim-aim.js';
|
|
231
231
|
import { iceSide } from './water-shore.js';
|
|
232
232
|
import { fitChase } from './camera-fit.js';
|
|
@@ -374,6 +374,10 @@ const ICE_GROUP = ['ice'];
|
|
|
374
374
|
* jetpack.
|
|
375
375
|
*/
|
|
376
376
|
const SWIM_THRUST = 6;
|
|
377
|
+
// How far above the head bone the water sits, metres: treading (water at the
|
|
378
|
+
// jaw, the head out) and stroking (over the back, the head breaking).
|
|
379
|
+
const TREAD_SINK = 0.1;
|
|
380
|
+
const SWIM_SINK = 0.12;
|
|
377
381
|
/** Local +Z. Allocated once — this is read every frame while swimming. */
|
|
378
382
|
const LOCAL_FORWARD = new BABYLON.Vector3(0, 0, 1);
|
|
379
383
|
/** Scratch for the yaw read-back; never allocate inside the per-frame loop. */
|
|
@@ -602,21 +606,32 @@ export class B3dBiped extends B3dControllable {
|
|
|
602
606
|
/** Eye position for first-person: the head bone (or eyeHeight fallback) nudged
|
|
603
607
|
* up + forward to roughly the eyes, so the camera sits at the eyes rather than
|
|
604
608
|
* the neck / head-bone base — which would leave the head & neck in front of the
|
|
605
|
-
* view.
|
|
606
|
-
*
|
|
607
|
-
|
|
609
|
+
* view. Returns a cached vector — read it now, don't retain.
|
|
610
|
+
*
|
|
611
|
+
* ALONG THE HEAD'S OWN AXES, not the body's. A sprint leans the head 22°
|
|
612
|
+
* forward and a swim far more, and an offset along the body's level facing
|
|
613
|
+
* left the eye inside the skull: in first person the back of your own head
|
|
614
|
+
* filled the screen as you ran (Tonio: "first person view when swimming is a
|
|
615
|
+
* disaster and it's still a big problem when running"). The UAL head bone's
|
|
616
|
+
* forward is the face's, measured. Only the eye's POSITION follows the head;
|
|
617
|
+
* the view's orientation does not (no bob in the rotation, no roll). */
|
|
618
|
+
getHeadPosition(extraForward = 0) {
|
|
608
619
|
if (this.mesh == null)
|
|
609
620
|
return null;
|
|
610
|
-
const f = this.mesh.forward;
|
|
611
621
|
const EYE_FWD = 0.12;
|
|
612
|
-
|
|
622
|
+
// The head bone is at the base of the skull; the eyes are ~10 cm up it.
|
|
623
|
+
const EYE_UP = 0.1;
|
|
613
624
|
if (this.headNode != null) {
|
|
614
625
|
const hp = this.headNode.getAbsolutePosition();
|
|
615
|
-
|
|
626
|
+
const hf = this.headNode.forward;
|
|
627
|
+
const hu = this.headNode.up;
|
|
628
|
+
const fwd = EYE_FWD + extraForward;
|
|
629
|
+
this._eyePos.set(hp.x + hf.x * fwd + hu.x * EYE_UP, hp.y + hf.y * fwd + hu.y * EYE_UP, hp.z + hf.z * fwd + hu.z * EYE_UP);
|
|
616
630
|
}
|
|
617
631
|
else {
|
|
632
|
+
const f = this.mesh.forward;
|
|
618
633
|
const o = this.mesh.getAbsolutePosition();
|
|
619
|
-
this._eyePos.set(o.x + f.x * EYE_FWD, o.y + this.eyeHeight, o.z + f.z * EYE_FWD);
|
|
634
|
+
this._eyePos.set(o.x + f.x * (EYE_FWD + extraForward), o.y + this.eyeHeight, o.z + f.z * (EYE_FWD + extraForward));
|
|
620
635
|
}
|
|
621
636
|
return this._eyePos;
|
|
622
637
|
}
|
|
@@ -703,6 +718,13 @@ export class B3dBiped extends B3dControllable {
|
|
|
703
718
|
*/
|
|
704
719
|
gunplay = false;
|
|
705
720
|
weaponWasPressed = false;
|
|
721
|
+
/**
|
|
722
|
+
* What the weapon button does, when a game decides (JS only). Called with
|
|
723
|
+
* whether the button asks for the weapon UP; the game moves it (draw from
|
|
724
|
+
* the hip, holster it) and calls `setGunplay` if and when it is in hand.
|
|
725
|
+
* Unset, the button toggles `gunplay` as before.
|
|
726
|
+
*/
|
|
727
|
+
whenWeapon = null;
|
|
706
728
|
/**
|
|
707
729
|
* Put the weapon up or down.
|
|
708
730
|
*
|
|
@@ -710,6 +732,16 @@ export class B3dBiped extends B3dControllable {
|
|
|
710
732
|
* a mode a consumer cannot set is a mode they have to fight.
|
|
711
733
|
*/
|
|
712
734
|
setGunplay(on) {
|
|
735
|
+
/*
|
|
736
|
+
RAISING THE WEAPON AIMS STRAIGHT AHEAD. The aim is the look pitch, and the
|
|
737
|
+
look pitch is whatever it was left at: walking around looking at the
|
|
738
|
+
ground, or the last dive, so the gun came up pointing at your feet. Tonio:
|
|
739
|
+
"It seems quite common for it to be aiming at your feet which is weird."
|
|
740
|
+
Levelled only on the way UP (lowering it leaves the view alone) and only
|
|
741
|
+
flat: in a headset the aim is the controller.
|
|
742
|
+
*/
|
|
743
|
+
if (on && !this.gunplay && !this.owner?.xrActive)
|
|
744
|
+
this._lookPitch = 0;
|
|
713
745
|
this.gunplay = on;
|
|
714
746
|
this._showWeapons(on);
|
|
715
747
|
}
|
|
@@ -1694,7 +1726,12 @@ export class B3dBiped extends B3dControllable {
|
|
|
1694
1726
|
*/
|
|
1695
1727
|
const weaponPressed = (input.weapon ?? 0) > 0.5;
|
|
1696
1728
|
if (weaponPressed && !this.weaponWasPressed) {
|
|
1697
|
-
|
|
1729
|
+
// A game that owns where the weapon IS (an inventory: on the hip, in
|
|
1730
|
+
// the hand) answers the button itself, and calls setGunplay.
|
|
1731
|
+
if (this.whenWeapon)
|
|
1732
|
+
this.whenWeapon(!this.gunplay);
|
|
1733
|
+
else
|
|
1734
|
+
this.setGunplay(!this.gunplay);
|
|
1698
1735
|
}
|
|
1699
1736
|
this.weaponWasPressed = weaponPressed;
|
|
1700
1737
|
/*
|
|
@@ -1739,6 +1776,20 @@ export class B3dBiped extends B3dControllable {
|
|
|
1739
1776
|
this.setCameraView(this.cameraView === 'chase' ? 'fpv' : 'chase');
|
|
1740
1777
|
}
|
|
1741
1778
|
this.viewWasPressed = viewPressed;
|
|
1779
|
+
/*
|
|
1780
|
+
NO HEAD IN FIRST PERSON. Whatever the eye offset, a sprint or a stroke
|
|
1781
|
+
swings the head through the view: the back and underside of your own skull
|
|
1782
|
+
filled the screen as you ran. Every first-person game hides it, and the
|
|
1783
|
+
standard way is to collapse the head BONE, which takes the head's geometry
|
|
1784
|
+
with it and leaves the arms and body (you still see your hands swim). Set
|
|
1785
|
+
every frame, after the clips have had their say; restored out of first
|
|
1786
|
+
person. The cost is a headless shadow while you are in it.
|
|
1787
|
+
*/
|
|
1788
|
+
if (this.headNode != null) {
|
|
1789
|
+
const k = this.cameraView === 'fpv' ? 0.001 : 1;
|
|
1790
|
+
if (this.headNode.scaling.x !== k)
|
|
1791
|
+
this.headNode.scaling.setAll(k);
|
|
1792
|
+
}
|
|
1742
1793
|
// First-person camera tracks the head node — so it doesn't fall behind the
|
|
1743
1794
|
// head when walking, or float above it when crouching. Orientation stays
|
|
1744
1795
|
// root-aligned (yaw only) to avoid the head's animation bob/rotation. Flat
|
|
@@ -1747,7 +1798,8 @@ export class B3dBiped extends B3dControllable {
|
|
|
1747
1798
|
this.fpvCamera != null &&
|
|
1748
1799
|
this.mesh != null &&
|
|
1749
1800
|
!this.owner?.xrActive) {
|
|
1750
|
-
|
|
1801
|
+
// The extra `eyeForward` along the head too (see getHeadPosition).
|
|
1802
|
+
const eye = this.getHeadPosition(attrs.eyeForward);
|
|
1751
1803
|
this.fpvCamera.parent = null;
|
|
1752
1804
|
if (eye != null) {
|
|
1753
1805
|
/*
|
|
@@ -1765,8 +1817,7 @@ export class B3dBiped extends B3dControllable {
|
|
|
1765
1817
|
any wall you stand against — and standing against walls is most of what
|
|
1766
1818
|
this arena is for.
|
|
1767
1819
|
*/
|
|
1768
|
-
|
|
1769
|
-
this.fpvCamera.position.set(eye.x + f.x * attrs.eyeForward, eye.y, eye.z + f.z * attrs.eyeForward);
|
|
1820
|
+
this.fpvCamera.position.copyFrom(eye);
|
|
1770
1821
|
}
|
|
1771
1822
|
const f = this.mesh.forward;
|
|
1772
1823
|
/*
|
|
@@ -2476,9 +2527,25 @@ export class B3dBiped extends B3dControllable {
|
|
|
2476
2527
|
Below, `swimBuoyancy` blends this toward neutral as you go deeper, so
|
|
2477
2528
|
diving still holds its depth; this only sets where the SURFACE is.
|
|
2478
2529
|
*/
|
|
2479
|
-
|
|
2530
|
+
/*
|
|
2531
|
+
HOW DEEP THE BODY RIDES. Water at the head bone (the base of the
|
|
2532
|
+
skull) left a treader's shoulders and arms out and a swimmer's head,
|
|
2533
|
+
shoulders and back riding on top. Tonio: "They should be almost
|
|
2534
|
+
completely submerged when swimming and just head mostly above water
|
|
2535
|
+
when treading water." So the water sits higher up the body: at the jaw
|
|
2536
|
+
treading, over the back with only the head breaking while stroking.
|
|
2537
|
+
*/
|
|
2538
|
+
const stroking = this.animationState?.name === 'swim';
|
|
2539
|
+
const poseBuoyancy = this._swimWaterline(pose, attrs.buoyancy - (stroking ? SWIM_SINK : TREAD_SINK));
|
|
2540
|
+
/*
|
|
2541
|
+
AIMING DOWN AND SWIMMING DIVES. That surface buoyancy floats the root
|
|
2542
|
+
on the waterline, a lift of about 1.1 m/s, which cancelled a downward
|
|
2543
|
+
stroke: the right stick tipped the swimmer and nothing happened. Tonio:
|
|
2544
|
+
"I can't seem to steer swimming up or down with right stick." So a
|
|
2545
|
+
stroke aimed down takes the vertical from buoyancy in proportion.
|
|
2546
|
+
*/
|
|
2480
2547
|
this._fallVel = buoyantStep(this._fallVel, submerged, dt, {
|
|
2481
|
-
buoyancy: swimBuoyancy(headDepth, { buoyancy: poseBuoyancy }),
|
|
2548
|
+
buoyancy: diveBuoyancy(swimBuoyancy(headDepth, { buoyancy: poseBuoyancy }), (this._swimPitch * Math.PI) / 180, input.forward ?? 0),
|
|
2482
2549
|
thrust: (swimUp - swimDown) * SWIM_THRUST,
|
|
2483
2550
|
});
|
|
2484
2551
|
let nextY = node.position.y + this._fallVel * dt;
|
|
@@ -2788,6 +2855,8 @@ export class B3dBiped extends B3dControllable {
|
|
|
2788
2855
|
// Create XR experience first
|
|
2789
2856
|
const xr = await scene.createDefaultXRExperienceAsync({
|
|
2790
2857
|
uiOptions: { sessionMode: mode },
|
|
2858
|
+
// The right hand points first (see tosi-b3d: otherwise a first press is lost).
|
|
2859
|
+
pointerSelectionOptions: { preferredHandedness: 'right' },
|
|
2791
2860
|
});
|
|
2792
2861
|
// Register controller observables BEFORE entering XR so we catch controller connect events
|
|
2793
2862
|
this.setupXRInput(xr);
|