@jgengine/react 0.14.0 → 0.15.0-next.0
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 +483 -1
- package/dist/accessibility.d.ts +39 -0
- package/dist/accessibility.js +61 -0
- package/dist/achievements.d.ts +50 -0
- package/dist/achievements.js +94 -0
- package/dist/cameraShake.d.ts +52 -0
- package/dist/cameraShake.js +53 -0
- package/dist/coachMarks.d.ts +72 -0
- package/dist/coachMarks.js +136 -0
- package/dist/codex.d.ts +25 -0
- package/dist/codex.js +62 -0
- package/dist/comboMeter.d.ts +63 -0
- package/dist/comboMeter.js +93 -0
- package/dist/components.js +4 -3
- package/dist/creditsScreen.d.ts +19 -0
- package/dist/creditsScreen.js +31 -0
- package/dist/cutscene.d.ts +66 -0
- package/dist/cutscene.js +132 -0
- package/dist/damageDirection.d.ts +51 -0
- package/dist/damageDirection.js +103 -0
- package/dist/dialogueView.d.ts +69 -0
- package/dist/dialogueView.js +111 -0
- package/dist/entityFrames.d.ts +114 -0
- package/dist/entityFrames.js +55 -0
- package/dist/fastTravel.d.ts +36 -0
- package/dist/fastTravel.js +103 -0
- package/dist/floatingText.d.ts +84 -0
- package/dist/floatingText.js +61 -0
- package/dist/gameViewport.js +8 -12
- package/dist/hooks.d.ts +42 -0
- package/dist/hooks.js +85 -0
- package/dist/hudTheme.d.ts +104 -7
- package/dist/hudTheme.js +300 -2
- package/dist/i18n.d.ts +29 -0
- package/dist/i18n.js +44 -0
- package/dist/index.d.ts +34 -0
- package/dist/index.js +34 -0
- package/dist/interactionPrompt.d.ts +80 -0
- package/dist/interactionPrompt.js +112 -0
- package/dist/keybindingMenu.d.ts +59 -0
- package/dist/keybindingMenu.js +146 -0
- package/dist/killFeed.d.ts +63 -0
- package/dist/killFeed.js +88 -0
- package/dist/map.d.ts +123 -2
- package/dist/map.js +239 -36
- package/dist/menuRouter.d.ts +51 -0
- package/dist/menuRouter.js +49 -0
- package/dist/modals.d.ts +131 -0
- package/dist/modals.js +168 -0
- package/dist/notifications.d.ts +39 -0
- package/dist/notifications.js +111 -0
- package/dist/objectiveBanner.d.ts +62 -0
- package/dist/objectiveBanner.js +129 -0
- package/dist/photoMode.d.ts +21 -0
- package/dist/photoMode.js +39 -0
- package/dist/previewFixtures.d.ts +30 -0
- package/dist/previewFixtures.js +46 -0
- package/dist/questTracker.d.ts +24 -0
- package/dist/questTracker.js +31 -0
- package/dist/quickMenu.d.ts +39 -0
- package/dist/quickMenu.js +79 -0
- package/dist/radialMenu.d.ts +50 -0
- package/dist/radialMenu.js +69 -0
- package/dist/saveSlots.d.ts +81 -0
- package/dist/saveSlots.js +138 -0
- package/dist/scoreboard.d.ts +67 -0
- package/dist/scoreboard.js +71 -0
- package/dist/settings.d.ts +9 -3
- package/dist/settings.js +10 -4
- package/dist/shopGrid.d.ts +70 -0
- package/dist/shopGrid.js +129 -0
- package/dist/statusEffectBar.d.ts +52 -0
- package/dist/statusEffectBar.js +57 -0
- package/dist/streetGeometryPreview.d.ts +7 -0
- package/dist/streetGeometryPreview.js +119 -0
- package/dist/talentTree.d.ts +60 -0
- package/dist/talentTree.js +217 -0
- package/dist/timerReadout.d.ts +90 -0
- package/dist/timerReadout.js +111 -0
- package/dist/useDebouncedCommit.d.ts +54 -0
- package/dist/useDebouncedCommit.js +81 -0
- package/dist/waveHud.d.ts +49 -0
- package/dist/waveHud.js +53 -0
- package/dist/waypointMarkers.d.ts +80 -0
- package/dist/waypointMarkers.js +116 -0
- package/package.json +3 -3
- package/skills/ce-handoff/SKILL.md +149 -0
- package/skills/jgengine/SKILL.md +3 -1
- package/skills/jgengine/api.md +17 -7
- package/skills/jgengine/capabilities.md +12 -0
- package/skills/jgengine/recipes/minimal-game.md +7 -4
- package/skills/jgengine-ui/SKILL.md +5 -3
- package/skills/jgengine-ui/api.md +708 -19
- package/skills/jgengine-ui/capabilities.md +362 -1
- package/skills/jgengine-ui/recipes/overhead-entity-frames.md +136 -0
- package/skills/jgengine-ui/reference.md +7 -4
|
@@ -4,6 +4,22 @@
|
|
|
4
4
|
|
|
5
5
|
Reach for these before hand-rolling. Each row is *the thing you need* → *the primitive that already does it*.
|
|
6
6
|
|
|
7
|
+
## accessibility-provider — apply accessibility preferences to a subtree — text-scale CSS var, reduced-motion/high-contrast/colorblind/captions data attrs, and the colorblind color-matrix filter
|
|
8
|
+
|
|
9
|
+
- `AccessibilityProvider` (function) · `import { AccessibilityProvider } from "@jgengine/react"`
|
|
10
|
+
|
|
11
|
+
## accessibility-store — serializable, observable accessibility preferences (reduced motion, high contrast, text scale, colorblind mode, captions) a game binds to its settings and presentation
|
|
12
|
+
|
|
13
|
+
- `createAccessibilityStore` (function) · `import { createAccessibilityStore } from "@jgengine/core/ui"`
|
|
14
|
+
|
|
15
|
+
## achievement-gallery — responsive achievement/trophy grid with unlocked/locked state, counter progress bars, secret masking, and a completion/score header
|
|
16
|
+
|
|
17
|
+
- `AchievementGallery` (function) · `import { AchievementGallery } from "@jgengine/react"`
|
|
18
|
+
|
|
19
|
+
## achievement-toast — unlock-moment banner (icon, heading, name, points) for an achievement toast queue
|
|
20
|
+
|
|
21
|
+
- `AchievementToast` (function) · `import { AchievementToast } from "@jgengine/react"`
|
|
22
|
+
|
|
7
23
|
## action-bar — optional skinned action-bar composition over the headless model — games own chrome
|
|
8
24
|
|
|
9
25
|
- `ActionBar` (function) · `import { ActionBar } from "@jgengine/react"`
|
|
@@ -28,10 +44,22 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
|
|
|
28
44
|
|
|
29
45
|
- `ActionTooltip` (function) · `import { ActionTooltip } from "@jgengine/react"`
|
|
30
46
|
|
|
47
|
+
## auto-scroll — pin a log/chat/console panel to its newest line as entries arrive — no hand-rolled scrollTop effects
|
|
48
|
+
|
|
49
|
+
- `useAutoScroll` (function) · `import { useAutoScroll } from "@jgengine/react"`
|
|
50
|
+
|
|
51
|
+
## camera-shake-meter — HUD readout for a core camera-shake controller — a trauma meter plus current impact-kind label, reskinnable and kind-labelled
|
|
52
|
+
|
|
53
|
+
- `CameraShakeMeter` (function) · `import { CameraShakeMeter } from "@jgengine/react"`
|
|
54
|
+
|
|
31
55
|
## camera-transparent-decor — let author decor pass through the orbit spring-arm; a child opts back in with jgCameraCollide
|
|
32
56
|
|
|
33
57
|
- `isCameraOccluderTransparent` (function) · `import { isCameraOccluderTransparent } from "@jgengine/shell/camera"`
|
|
34
58
|
|
|
59
|
+
## capture-canvas — read the live R3F frame to a PNG data URL (needs preserveDrawingBuffer)
|
|
60
|
+
|
|
61
|
+
- `captureCanvas` (function) · `import { captureCanvas } from "@jgengine/shell/render/sceneCapture"`
|
|
62
|
+
|
|
35
63
|
## character-paperdoll — equip-slot paperdoll — flanking columns around a portrait, activatable slots
|
|
36
64
|
|
|
37
65
|
- `Paperdoll` (function) · `import { Paperdoll } from "@jgengine/react"`
|
|
@@ -49,18 +77,94 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
|
|
|
49
77
|
- `formatDelta` (function) · `import { formatDelta } from "@jgengine/core/ui"`
|
|
50
78
|
- `formatDuration` (function) · `import { formatDuration } from "@jgengine/core/ui"`
|
|
51
79
|
|
|
80
|
+
## coach-mark — single onboarding callout — title/body, N-of-M counter, Next + Skip controls, theme-reskinnable
|
|
81
|
+
|
|
82
|
+
- `CoachMark` (function) · `import { CoachMark } from "@jgengine/react"`
|
|
83
|
+
|
|
84
|
+
## coach-mark-host — full-screen onboarding coach-mark host — anchored/centered callout, dimmed spotlight backdrop, Next/Skip wired to the sequence
|
|
85
|
+
|
|
86
|
+
- `CoachMarkHost` (function) · `import { CoachMarkHost } from "@jgengine/react"`
|
|
87
|
+
|
|
88
|
+
## coach-marks — ordered, gated, persist-once onboarding coach-marks/tutorial callouts — anchored or centered steps with a seen set and Next/Skip
|
|
89
|
+
|
|
90
|
+
- `createCoachMarkSequence` (function) · `import { createCoachMarkSequence } from "@jgengine/core/ui"`
|
|
91
|
+
|
|
92
|
+
## codex-gallery — codex/bestiary gallery with category tabs, discovered/locked cards, secret masking, and a completion header
|
|
93
|
+
|
|
94
|
+
- `Codex` (function) · `import { Codex } from "@jgengine/react"`
|
|
95
|
+
|
|
96
|
+
## colorblind-filters — SVG feColorMatrix defs (protanopia/deuteranopia/tritanopia/grayscale) referenced by the accessibility colorblind filter
|
|
97
|
+
|
|
98
|
+
- `ColorblindFilters` (function) · `import { ColorblindFilters } from "@jgengine/react"`
|
|
99
|
+
|
|
100
|
+
## combo-meter-hud — drop-in HUD for a core combo meter — big live count, free-string tier label, derived multiplier, and a draining decay-window bar, per-tier colored from a caller map and HudTheme-token skinnable
|
|
101
|
+
|
|
102
|
+
- `ComboMeterHud` (function) · `import { ComboMeterHud } from "@jgengine/react"`
|
|
103
|
+
|
|
104
|
+
## confirm-dialog — generic themeable confirm/cancel dialog — title, body, two buttons, danger styling
|
|
105
|
+
|
|
106
|
+
- `ConfirmDialog` (function) · `import { ConfirmDialog } from "@jgengine/react"`
|
|
107
|
+
|
|
108
|
+
## controller-camera-shake — R3F consumer that applies a core camera-shake controller's pooled per-frame offset to the active camera (translation + pitch/yaw/roll) so the view visibly shakes
|
|
109
|
+
|
|
110
|
+
- `ControllerCameraShake` (function) · `import { ControllerCameraShake } from "@jgengine/shell/camera"`
|
|
111
|
+
|
|
52
112
|
## controls-list — keybind-derived control legend that hides on touch
|
|
53
113
|
|
|
54
114
|
- `ControlsList` (function) · `import { ControlsList } from "@jgengine/react"`
|
|
55
115
|
|
|
116
|
+
## credits-screen — drop-in credits view over a CreditsDocument — headed sections, optional links, HudTheme-skinned
|
|
117
|
+
|
|
118
|
+
- `CreditsScreen` (function) · `import { CreditsScreen } from "@jgengine/react/creditsScreen"`
|
|
119
|
+
|
|
120
|
+
## cutscene-letterbox — reskinnable cinematic letterbox + skip overlay for a cutscene — animated bars, caption/dialogue slot, progress line, Skip button
|
|
121
|
+
|
|
122
|
+
- `CutsceneLetterbox` (function) · `import { CutsceneLetterbox } from "@jgengine/react"`
|
|
123
|
+
|
|
124
|
+
## damage-direction-overlay — drop-in hit-from damage-direction overlay — SVG arcs flaring around a center reticle toward each recent hit and fading over time, colored per `kind`/HudTheme, pointer-events none
|
|
125
|
+
|
|
126
|
+
- `DamageDirectionOverlay` (function) · `import { DamageDirectionOverlay } from "@jgengine/react"`
|
|
127
|
+
|
|
128
|
+
## day-night-sky — drop-in R3F presenter that drives the engine's existing sky dome and lights from a serializable day-night cycle for a moving, color-graded day-night look
|
|
129
|
+
|
|
130
|
+
- `DayNightSky` (function) · `import { DayNightSky } from "@jgengine/shell/environment"`
|
|
131
|
+
|
|
132
|
+
## debounced-commit — bind a slider/number/color control to an expensive commit path (scene-document patch, settings persist) — instant local mirror, one trailing commit per pause, flush on release/blur/unmount; no raw onChange→patch wiring
|
|
133
|
+
|
|
134
|
+
- `useDebouncedCommit` (function) · `import { useDebouncedCommit } from "@jgengine/react"`
|
|
135
|
+
|
|
56
136
|
## default-look — one field that lights a scene like a shipped game (opt out with "flat")
|
|
57
137
|
|
|
58
138
|
- `LookPreset` (type) · `import { LookPreset } from "@jgengine/core/ui"`
|
|
59
139
|
|
|
140
|
+
## default-walk-codes — stock WASD + jump key codes for the shell walk controller
|
|
141
|
+
|
|
142
|
+
- `DEFAULT_WALK_CODES` (const) · `import { DEFAULT_WALK_CODES } from "@jgengine/shell/shellMovement"`
|
|
143
|
+
|
|
144
|
+
## dialogue-view — drop-in branching conversation UI — speaker + portrait slot, current line, clickable response choices that advance a DialogueRun
|
|
145
|
+
|
|
146
|
+
- `DialogueView` (function) · `import { DialogueView } from "@jgengine/react"`
|
|
147
|
+
|
|
148
|
+
## disposable-resource — memoize a three.js GPU resource (or tuple) with automatic dispose on change/unmount — no hand-rolled useMemo + dispose-effect pairs
|
|
149
|
+
|
|
150
|
+
- `useDisposable` (function) · `import { useDisposable } from "@jgengine/shell/render/useDisposable"`
|
|
151
|
+
|
|
60
152
|
## distance-format — render meters as m or km for HUD stats, telemetry, and range readouts
|
|
61
153
|
|
|
62
154
|
- `formatDistance` (function) · `import { formatDistance } from "@jgengine/core/ui"`
|
|
63
155
|
|
|
156
|
+
## dom-event — attach a window/document/element event listener with automatic cleanup and a stable handler ref — no hand-rolled addEventListener effects
|
|
157
|
+
|
|
158
|
+
- `useDomEvent` (function) · `import { useDomEvent } from "@jgengine/react"`
|
|
159
|
+
|
|
160
|
+
## entity-frames — overlay that renders caller-composed frames over on-screen entities
|
|
161
|
+
|
|
162
|
+
- `EntityFrames` (function) · `import { EntityFrames } from "@jgengine/react"`
|
|
163
|
+
- `EntityScreenProjection` (interface) · `import { EntityScreenProjection } from "@jgengine/react"`
|
|
164
|
+
- `WorldEntityFrames` (function) · `import { WorldEntityFrames } from "@jgengine/shell/world/WorldEntityFrames"`
|
|
165
|
+
- `projectWorldToScreen` (function) · `import { projectWorldToScreen } from "@jgengine/shell/world/WorldEntityFrames"`
|
|
166
|
+
- `useWorldProjection` (function) · `import { useWorldProjection } from "@jgengine/shell/world/WorldEntityFrames"`
|
|
167
|
+
|
|
64
168
|
## entity-portrait — selectable entity portrait tile with vitals and selected/focus states
|
|
65
169
|
|
|
66
170
|
- `EntityPortrait` (function) · `import { EntityPortrait } from "@jgengine/react"`
|
|
@@ -81,6 +185,22 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
|
|
|
81
185
|
|
|
82
186
|
- `useEventMeter` (function) · `import { useEventMeter } from "@jgengine/react"`
|
|
83
187
|
|
|
188
|
+
## fast-travel-menu — discovered-destinations picker grouped by region with distances, a discovery counter, and a travel callback
|
|
189
|
+
|
|
190
|
+
- `FastTravelMenu` (function) · `import { FastTravelMenu } from "@jgengine/react"`
|
|
191
|
+
|
|
192
|
+
## floating-text — overlay that renders on-screen floating combat text with per-kind color, alpha, and pop-in scale
|
|
193
|
+
|
|
194
|
+
- `FloatingText` (function) · `import { FloatingText } from "@jgengine/react"`
|
|
195
|
+
- `FloatingTextPlacement` (interface) · `import { FloatingTextPlacement } from "@jgengine/react"`
|
|
196
|
+
- `WorldFloatingText` (function) · `import { WorldFloatingText } from "@jgengine/shell/vfx/WorldFloatingText"`
|
|
197
|
+
- `createFloatingTextField` (function) · `import { createFloatingTextField } from "@jgengine/core/ui/floatingText"`
|
|
198
|
+
- `layoutFloatingText` (function) · `import { layoutFloatingText } from "@jgengine/react"`
|
|
199
|
+
|
|
200
|
+
## fullscreen-map — fullscreen pan/zoom world-map overlay over WorldMapSurface — wheel-zoom, drag-pan, click-to-place, and a freehand draw tool (onStrokeComplete)
|
|
201
|
+
|
|
202
|
+
- `FullscreenMap` (function) · `import { FullscreenMap } from "@jgengine/react"`
|
|
203
|
+
|
|
84
204
|
## game-context-bridge — re-provide the GameContext across a nested Canvas/reconciler boundary
|
|
85
205
|
|
|
86
206
|
- `GameContextBridge` (function) · `import { GameContextBridge } from "@jgengine/react"`
|
|
@@ -137,27 +257,67 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
|
|
|
137
257
|
|
|
138
258
|
- `StatBar` (function) · `import { StatBar } from "@jgengine/react"`
|
|
139
259
|
|
|
140
|
-
## hud-theme — game-authored token object
|
|
260
|
+
## hud-theme — game-authored token object covering bars, frames, slots, chrome, text, status colors, fonts, and rarity
|
|
141
261
|
|
|
142
262
|
- `HudThemePalette` (interface) · `import { HudThemePalette } from "@jgengine/react"`
|
|
143
263
|
|
|
264
|
+
## hud-theme-author — fill a full HudTheme from per-group partial overrides
|
|
265
|
+
|
|
266
|
+
- `hudTheme` (function) · `import { hudTheme } from "@jgengine/react"`
|
|
267
|
+
|
|
268
|
+
## hud-theme-derive — build a full HudTheme from an accent + surface seed pair
|
|
269
|
+
|
|
270
|
+
- `deriveHudTheme` (function) · `import { deriveHudTheme } from "@jgengine/react"`
|
|
271
|
+
|
|
272
|
+
## hud-ticker — re-render a HUD element at a steady hz for time-derived readouts (cooldowns, cast/swing bars) — no hand-rolled setInterval effects
|
|
273
|
+
|
|
274
|
+
- `useTicker` (function) · `import { useTicker } from "@jgengine/react"`
|
|
275
|
+
|
|
144
276
|
## hud-vitals — atomic purpose-named vitals bars (token-themed parts, not a finished HUD)
|
|
145
277
|
|
|
146
278
|
- `BarTokens` (interface) · `import { BarTokens } from "@jgengine/react"`
|
|
147
279
|
- `barTokens` (function) · `import { barTokens } from "@jgengine/react"`
|
|
148
280
|
|
|
281
|
+
## i18n — translate a message catalog with fallback-locale lookup, `{param}` interpolation, and Intl pluralization; observable active-locale switching
|
|
282
|
+
|
|
283
|
+
- `createI18n` (function) · `import { createI18n } from "@jgengine/core/ui"`
|
|
284
|
+
|
|
285
|
+
## interaction-prompt-host — screen-anchored "press E to…" callout rendering a prompt registry's active interactable — keybind cap+label, gauge hold bar, or plain label, theme- and per-prompt-accent skinnable
|
|
286
|
+
|
|
287
|
+
- `InteractionPrompt` (function) · `import { InteractionPrompt } from "@jgengine/react"`
|
|
288
|
+
|
|
149
289
|
## key-hint — keyboard/mouse control hint that hides itself on touch
|
|
150
290
|
|
|
151
291
|
- `KeyHint` (function) · `import { KeyHint } from "@jgengine/react"`
|
|
152
292
|
|
|
293
|
+
## keybinding-menu — drop-in controls-settings surface over a rebind session — click-to-capture rows with key glyphs, conflict badges, per-row and reset-all, HudTheme-skinnable
|
|
294
|
+
|
|
295
|
+
- `KeybindingMenu` (function) · `import { KeybindingMenu } from "@jgengine/react"`
|
|
296
|
+
|
|
153
297
|
## keycap — styled keyboard/mouse key cap for control hints
|
|
154
298
|
|
|
155
299
|
- `Keycap` (function) · `import { Keycap } from "@jgengine/react"`
|
|
156
300
|
|
|
301
|
+
## kill-feed — vertical event/kill-feed ticker rendering a core event-ticker as a fading, newest-on-top stack of per-kind iconned, accent-colored rows over HudTheme tokens
|
|
302
|
+
|
|
303
|
+
- `KillFeed` (function) · `import { KillFeed } from "@jgengine/react"`
|
|
304
|
+
|
|
157
305
|
## live-markers — a self-ticking MarkerSet kept in sync from the live scene each HUD tick — pass a rebuild(markers, ctx) that clears+repopulates, no hand-rolled setInterval
|
|
158
306
|
|
|
159
307
|
- `useLiveMarkers` (function) · `import { useLiveMarkers } from "@jgengine/react"`
|
|
160
308
|
|
|
309
|
+
## map-legend — marker-kind key (glyph + color + label per kind) sharing the map's kindStyles
|
|
310
|
+
|
|
311
|
+
- `MapLegend` (function) · `import { MapLegend } from "@jgengine/react"`
|
|
312
|
+
|
|
313
|
+
## menu-router — screen stack for a game front-end — push/back/replace/reset with optional Escape-to-back
|
|
314
|
+
|
|
315
|
+
- `useMenuRouter` (function) · `import { useMenuRouter } from "@jgengine/react/menuRouter"`
|
|
316
|
+
|
|
317
|
+
## menu-stack-reducer — pure push/back/replace/reset transitions for a menu screen stack
|
|
318
|
+
|
|
319
|
+
- `menuStackReducer` (function) · `import { menuStackReducer } from "@jgengine/react/menuRouter"`
|
|
320
|
+
|
|
161
321
|
## minimap — framed circular minimap with terrain bake, fog, markers, and facing arrow
|
|
162
322
|
|
|
163
323
|
- `Minimap` (function) · `import { Minimap } from "@jgengine/react"`
|
|
@@ -174,10 +334,39 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
|
|
|
174
334
|
|
|
175
335
|
- `MinimapTrack` (function) · `import { MinimapTrack } from "@jgengine/react"`
|
|
176
336
|
|
|
337
|
+
## modal-host — full-screen modal/dialog host over a modal stack — dimmed backdrop, focus trap, Esc/backdrop-to-cancel, aria-modal dialog
|
|
338
|
+
|
|
339
|
+
- `ModalHost` (function) · `import { ModalHost } from "@jgengine/react"`
|
|
340
|
+
|
|
341
|
+
## modal-stack — serializable, observable stack of opaque modal/dialog records — push/pop/resolve blocking overlays (pause menu, confirm dialog) with optional auto-dismiss; never interprets kind or result
|
|
342
|
+
|
|
343
|
+
- `createModalStack` (function) · `import { createModalStack } from "@jgengine/core/ui"`
|
|
344
|
+
|
|
177
345
|
## nameplates — billboarded name + HP bar over nearby entities
|
|
178
346
|
|
|
179
347
|
- `WorldNameplates` (function) · `import { WorldNameplates } from "@jgengine/shell/world/WorldHud"`
|
|
180
348
|
|
|
349
|
+
## notification-bell — icon button with a live unread-count badge over a notification store
|
|
350
|
+
|
|
351
|
+
- `NotificationBell` (function) · `import { NotificationBell } from "@jgengine/react"`
|
|
352
|
+
|
|
353
|
+
## notification-center-panel — scrollable notification log with kind markers, read tracking, relative time, and mark-all-read/clear
|
|
354
|
+
|
|
355
|
+
- `NotificationCenter` (function) · `import { NotificationCenter } from "@jgengine/react"`
|
|
356
|
+
|
|
357
|
+
## objective-banner — serializable, clock-driven stage/objective banner queue — flies a big transient centered title + optional subtitle in, holds, and fades out one at a time, with phase + progress for animation, free-string kinds the game styles, and snapshot/restore
|
|
358
|
+
|
|
359
|
+
- `createObjectiveBanner` (function) · `import { createObjectiveBanner } from "@jgengine/core/ui"`
|
|
360
|
+
|
|
361
|
+
## objective-banner-host — full-screen overlay that renders a core objective-banner controller as a fly-in / hold / fade-out centered title + subtitle stamp, theme- and per-kind-skinnable
|
|
362
|
+
|
|
363
|
+
- `ObjectiveBannerHost` (function) · `import { ObjectiveBannerHost } from "@jgengine/react"`
|
|
364
|
+
|
|
365
|
+
## offscreen-markers — serializable waypoint tracker + pure edge-clamp/bearing math for on-screen pins and off-screen directional arrows with distance
|
|
366
|
+
|
|
367
|
+
- `createWaypointTracker` (function) · `import { createWaypointTracker } from "@jgengine/core/ui"`
|
|
368
|
+
- `layoutScreenMarker` (function) · `import { layoutScreenMarker } from "@jgengine/core/ui"`
|
|
369
|
+
|
|
181
370
|
## ordinal-format — format a placement number as 1st/2nd/3rd for HUD ranks
|
|
182
371
|
|
|
183
372
|
- `formatOrdinal` (function) · `import { formatOrdinal } from "@jgengine/core/ui"`
|
|
@@ -222,6 +411,22 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
|
|
|
222
411
|
|
|
223
412
|
- `togglePanel` (function) · `import { togglePanel } from "@jgengine/core/ui"`
|
|
224
413
|
|
|
414
|
+
## particle-field — render a core particle system as a soft-point GPU cloud with per-particle size, color, and alpha
|
|
415
|
+
|
|
416
|
+
- `ParticleField` (function) · `import { ParticleField } from "@jgengine/shell/vfx/ParticleField"`
|
|
417
|
+
|
|
418
|
+
## pause-menu — reskinnable pause-menu building block — Resume plus a game-filled Settings/Quit slot list, HudTheme-driven
|
|
419
|
+
|
|
420
|
+
- `PauseMenu` (function) · `import { PauseMenu } from "@jgengine/react"`
|
|
421
|
+
|
|
422
|
+
## photo-mode — observable photo-mode state (active + hide-HUD) a game binds its screenshot/camera flow to
|
|
423
|
+
|
|
424
|
+
- `createPhotoModeStore` (function) · `import { createPhotoModeStore } from "@jgengine/core/ui"`
|
|
425
|
+
|
|
426
|
+
## photo-mode-controls — photo-mode toolbar (hide-HUD toggle, capture, exit) bound to a photo-mode store
|
|
427
|
+
|
|
428
|
+
- `PhotoModeControls` (function) · `import { PhotoModeControls } from "@jgengine/react"`
|
|
429
|
+
|
|
225
430
|
## placement-ghost — render valid/invalid placement preview mesh
|
|
226
431
|
|
|
227
432
|
- `PlacementGhost` (function) · `import { PlacementGhost } from "@jgengine/shell/structures"`
|
|
@@ -230,10 +435,46 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
|
|
|
230
435
|
|
|
231
436
|
- `Popover` (function) · `import { Popover } from "@jgengine/react"`
|
|
232
437
|
|
|
438
|
+
## quest-tracker — compact quest/objective HUD tracker — titles + labelled objective progress from describeTrackedQuest views
|
|
439
|
+
|
|
440
|
+
- `QuestTracker` (function) · `import { QuestTracker } from "@jgengine/react"`
|
|
441
|
+
|
|
442
|
+
## quick-menu — multi-form quick menu (radial / arc / list / grid) over one item model with hotkeys, badges, cooldowns, sections, and nested submenus
|
|
443
|
+
|
|
444
|
+
- `QuickMenu` (function) · `import { QuickMenu } from "@jgengine/react"`
|
|
445
|
+
|
|
446
|
+
## radial-menu — pointer/stick-driven radial or arc quick menu (weapon/emote wheel) — angular slice selection with hotkeys, badges, cooldowns, and a neutral hub
|
|
447
|
+
|
|
448
|
+
- `RadialMenu` (function) · `import { RadialMenu } from "@jgengine/react"`
|
|
449
|
+
|
|
450
|
+
## radial-select — map a pointer/stick vector to a radial-menu slice index, with a neutral dead zone and optional arc bounds
|
|
451
|
+
|
|
452
|
+
- `radialIndexFromVector` (function) · `import { radialIndexFromVector } from "@jgengine/core/ui"`
|
|
453
|
+
|
|
454
|
+
## raf-loop — run a cancellable requestAnimationFrame loop for DOM-side animation with delta seconds — no hand-rolled RAF effects
|
|
455
|
+
|
|
456
|
+
- `useRafLoop` (function) · `import { useRafLoop } from "@jgengine/react"`
|
|
457
|
+
|
|
233
458
|
## resolve-game-look — expand a look preset into concrete lighting/backdrop/post knobs
|
|
234
459
|
|
|
235
460
|
- `resolveGameLook` (function) · `import { resolveGameLook } from "@jgengine/core/ui"`
|
|
236
461
|
|
|
462
|
+
## save-slot-menu — drop-in save-select / profile menu that renders a core save-slots index as New / Continue / Load / Delete cards with free-string meta chips and relative save times, theme-skinnable
|
|
463
|
+
|
|
464
|
+
- `SaveSlotMenu` (function) · `import { SaveSlotMenu } from "@jgengine/react"`
|
|
465
|
+
|
|
466
|
+
## scene-capture-binding — expose the in-Canvas scene-capture function to outside-Canvas HUD (photo mode)
|
|
467
|
+
|
|
468
|
+
- `SceneCaptureBinding` (function) · `import { SceneCaptureBinding } from "@jgengine/shell/render/sceneCapture"`
|
|
469
|
+
|
|
470
|
+
## scoreboard-table — reskinnable ranked-score / leaderboard table over the rankLeaderboard selector — medal-colored podium, local-row highlight, HudTheme-token driven
|
|
471
|
+
|
|
472
|
+
- `Scoreboard` (function) · `import { Scoreboard } from "@jgengine/react"`
|
|
473
|
+
|
|
474
|
+
## screen-effects-overlay — shell DOM overlay that renders a core screen-effects controller as full-screen flash / edge-vignette / low-health-pulse color-grade layers
|
|
475
|
+
|
|
476
|
+
- `ScreenEffectsOverlay` (function) · `import { ScreenEffectsOverlay } from "@jgengine/shell/postfx/ScreenEffectsOverlay"`
|
|
477
|
+
|
|
237
478
|
## selection-collection — accessible portrait-strip / group-chip renderer over a selection model
|
|
238
479
|
|
|
239
480
|
- `SelectionCollectionChrome` (function) · `import { SelectionCollectionChrome } from "@jgengine/react"`
|
|
@@ -250,6 +491,10 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
|
|
|
250
491
|
|
|
251
492
|
- `SelectionPanel` (function) · `import { SelectionPanel } from "@jgengine/react"`
|
|
252
493
|
|
|
494
|
+
## shop-grid-host — drop-in vendor/shop grid over a caller-owned wallet — item cards with icon/price/stock, afford-aware Buy, optional Sell, and a balance readout, token-themed
|
|
495
|
+
|
|
496
|
+
- `ShopGrid` (function) · `import { ShopGrid } from "@jgengine/react"`
|
|
497
|
+
|
|
253
498
|
## speed-format — render a m/s speed as km/h, mph, knots, or m/s for speedometers and telemetry HUDs
|
|
254
499
|
|
|
255
500
|
- `formatSpeed` (function) · `import { formatSpeed } from "@jgengine/core/ui"`
|
|
@@ -258,26 +503,142 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
|
|
|
258
503
|
|
|
259
504
|
- `StartScreen` (function) · `import { StartScreen } from "@jgengine/react"`
|
|
260
505
|
|
|
506
|
+
## status-effect-bar — timeline HUD row of active statuses — icon + radial countdown ring + stack badge, driven off the status model, HudTheme-skinned
|
|
507
|
+
|
|
508
|
+
- `StatusEffectBar` (function) · `import { StatusEffectBar } from "@jgengine/react"`
|
|
509
|
+
|
|
261
510
|
## studio-stage — cinematic lighting rig + backdrop + turntable for parametric studios
|
|
262
511
|
|
|
263
512
|
- `StudioStage` (function) · `import { StudioStage } from "@jgengine/shell/scene/StudioStage"`
|
|
264
513
|
|
|
514
|
+
## talent-tree — drop-in skill/talent/upgrade-tree widget — pass `nodes`+`tree` for point-spend or a precomputed `view` for any unlock rule; branch/tier layout, SVG prerequisite edges, learned/available/locked/maxed styling, icon + rank, onLearn
|
|
515
|
+
|
|
516
|
+
- `TalentTree` (function) · `import { TalentTree } from "@jgengine/react"`
|
|
517
|
+
|
|
518
|
+
## timer-readout — live digital mm:ss/m:ss.d timer readout bound to a TimerSet
|
|
519
|
+
|
|
520
|
+
- `TimerReadout` (function) · `import { TimerReadout } from "@jgengine/react"`
|
|
521
|
+
|
|
522
|
+
## timer-readout-format — format milliseconds as digital timer text (mm:ss / m:ss.d / ss.d)
|
|
523
|
+
|
|
524
|
+
- `formatTimerMs` (function) · `import { formatTimerMs } from "@jgengine/react"`
|
|
525
|
+
|
|
526
|
+
## timer-ring — radial SVG charge/cooldown ring bound to a TimerSet's progress
|
|
527
|
+
|
|
528
|
+
- `TimerRing` (function) · `import { TimerRing } from "@jgengine/react"`
|
|
529
|
+
|
|
530
|
+
## trans — inline translated-message component bound to the active locale
|
|
531
|
+
|
|
532
|
+
- `Trans` (function) · `import { Trans } from "@jgengine/react"`
|
|
533
|
+
|
|
265
534
|
## transform-gizmo — in-game select/move/rotate/scale gizmo
|
|
266
535
|
|
|
267
536
|
- `TransformGizmo` (const) · `import { TransformGizmo } from "@jgengine/shell/structures"`
|
|
268
537
|
|
|
538
|
+
## use-camera-shake — React hook binding a camera-shake controller — subscribes for live trauma/kind and can self-drive its decay on a frame loop
|
|
539
|
+
|
|
540
|
+
- `useCameraShake` (function) · `import { useCameraShake } from "@jgengine/react"`
|
|
541
|
+
|
|
542
|
+
## use-coach-marks — React hook binding a coach-mark sequence to a component — re-renders on advance/skip/gate changes
|
|
543
|
+
|
|
544
|
+
- `useCoachMarks` (function) · `import { useCoachMarks } from "@jgengine/react"`
|
|
545
|
+
|
|
546
|
+
## use-combo-meter — React hook binding a combo meter — re-renders per frame so the decay-window bar drains live and returns the current combo view
|
|
547
|
+
|
|
548
|
+
- `useComboMeter` (function) · `import { useComboMeter } from "@jgengine/react"`
|
|
549
|
+
|
|
550
|
+
## use-damage-direction — React hook that animates a damage-direction tracker's fade with requestAnimationFrame and re-renders its live indicators
|
|
551
|
+
|
|
552
|
+
- `useDamageDirection` (function) · `import { useDamageDirection } from "@jgengine/react"`
|
|
553
|
+
|
|
554
|
+
## use-dialogue-run — React hook binding a branching dialogue run to a component — re-renders as the player advances the conversation
|
|
555
|
+
|
|
556
|
+
- `useDialogueRun` (function) · `import { useDialogueRun } from "@jgengine/react"`
|
|
557
|
+
|
|
558
|
+
## use-event-ticker — React hook binding an event-ticker — re-renders per frame so entries fade and drop live, returning the current newest-first views
|
|
559
|
+
|
|
560
|
+
- `useEventTicker` (function) · `import { useEventTicker } from "@jgengine/react"`
|
|
561
|
+
|
|
562
|
+
## use-fast-travel — re-render a component when a fast-travel network's discovery state changes
|
|
563
|
+
|
|
564
|
+
- `useFastTravel` (function) · `import { useFastTravel } from "@jgengine/react"`
|
|
565
|
+
|
|
566
|
+
## use-interaction-prompt — React hook binding a prompt registry to a moving player — resolves the nearest interactable prompt and returns the active one
|
|
567
|
+
|
|
568
|
+
- `useInteractionPrompt` (function) · `import { useInteractionPrompt } from "@jgengine/react"`
|
|
569
|
+
|
|
570
|
+
## use-modal-stack — React hook binding a modal stack to a component — re-renders on push/pop/resolve
|
|
571
|
+
|
|
572
|
+
- `useModalStack` (function) · `import { useModalStack } from "@jgengine/react"`
|
|
573
|
+
|
|
574
|
+
## use-objective-banner — React hook binding an objective-banner controller — advances its clock per frame and returns the current banner view
|
|
575
|
+
|
|
576
|
+
- `useObjectiveBanner` (function) · `import { useObjectiveBanner } from "@jgengine/react"`
|
|
577
|
+
|
|
269
578
|
## use-panels — headless toggleable-window manager with keybind + ESC handling over the core panel model
|
|
270
579
|
|
|
271
580
|
- `usePanels` (function) · `import { usePanels } from "@jgengine/react"`
|
|
272
581
|
|
|
582
|
+
## use-rebind-session — React hook that re-renders a component whenever a rebind session changes
|
|
583
|
+
|
|
584
|
+
- `useRebindSession` (function) · `import { useRebindSession } from "@jgengine/react"`
|
|
585
|
+
|
|
586
|
+
## use-save-slots — React hook binding a save-slots metadata index — re-renders on change and returns the ordered slot list
|
|
587
|
+
|
|
588
|
+
- `useSaveSlots` (function) · `import { useSaveSlots } from "@jgengine/react"`
|
|
589
|
+
|
|
590
|
+
## use-sequence-director — React hook that drives a cutscene director's per-frame tick loop and exposes playhead/progress + play/pause/skip controls
|
|
591
|
+
|
|
592
|
+
- `useSequenceDirector` (function) · `import { useSequenceDirector } from "@jgengine/react"`
|
|
593
|
+
|
|
594
|
+
## use-shop-stock — React hook binding a shop-stock model — re-renders on any stock change and returns the entry list
|
|
595
|
+
|
|
596
|
+
- `useShopStock` (function) · `import { useShopStock } from "@jgengine/react"`
|
|
597
|
+
|
|
598
|
+
## use-timer — React hook binding one timer to a component with a per-frame re-read
|
|
599
|
+
|
|
600
|
+
- `useTimerRead` (function) · `import { useTimerRead } from "@jgengine/react"`
|
|
601
|
+
|
|
602
|
+
## use-translate — live `t(key, params)` translator bound to the active locale, re-rendering on locale change
|
|
603
|
+
|
|
604
|
+
- `useT` (function) · `import { useT } from "@jgengine/react"`
|
|
605
|
+
|
|
606
|
+
## use-wave-runner — React hook that subscribes to a wave runner and returns its pooled current-wave view
|
|
607
|
+
|
|
608
|
+
- `useWaveRunner` (function) · `import { useWaveRunner } from "@jgengine/react"`
|
|
609
|
+
|
|
610
|
+
## use-waypoints — React binding that returns a waypoint tracker's live list (or a passthrough array)
|
|
611
|
+
|
|
612
|
+
- `useWaypoints` (function) · `import { useWaypoints } from "@jgengine/react"`
|
|
613
|
+
|
|
273
614
|
## vital-bar — compact current/max vital meter for an entity summary
|
|
274
615
|
|
|
275
616
|
- `VitalBar` (function) · `import { VitalBar } from "@jgengine/react"`
|
|
276
617
|
|
|
618
|
+
## wave-hud — drop-in wave/spawn HUD over a wave runner — big WAVE N label, wave-progress bar, spawned/total + budget + alert readouts, theme-skinnable
|
|
619
|
+
|
|
620
|
+
- `WaveHud` (function) · `import { WaveHud } from "@jgengine/react"`
|
|
621
|
+
|
|
622
|
+
## waypoint-arrow — on-screen HUD guide arrow to a tracked waypoint, rotated by facing-relative bearing with a distance readout
|
|
623
|
+
|
|
624
|
+
- `WaypointArrow` (function) · `import { WaypointArrow } from "@jgengine/react"`
|
|
625
|
+
|
|
626
|
+
## waypoint-markers — overlay rendering world waypoints as on-screen pins and off-screen edge-clamped directional arrows with distance, colored per game-owned kind
|
|
627
|
+
|
|
628
|
+
- `WaypointMarkers` (function) · `import { WaypointMarkers } from "@jgengine/react"`
|
|
629
|
+
|
|
277
630
|
## window — standalone draggable, closable window primitive over HudFrame — no manager required
|
|
278
631
|
|
|
279
632
|
- `Window` (function) · `import { Window } from "@jgengine/react"`
|
|
280
633
|
|
|
634
|
+
## world-intersections — inspect turns and junction meshes in a deterministic preview fixture
|
|
635
|
+
|
|
636
|
+
- `StreetGeometryPreview` (function) · `import { StreetGeometryPreview } from "@jgengine/react"`
|
|
637
|
+
|
|
281
638
|
## world-object-highlights — ground-ring highlight over every selected placed object
|
|
282
639
|
|
|
283
640
|
- `WorldObjectHighlights` (function) · `import { WorldObjectHighlights } from "@jgengine/shell/world/WorldHud"`
|
|
641
|
+
|
|
642
|
+
## world-pings — in-scene ping markers — a bobbing downward arrowhead, ground ring, and billboarded callout per marker, colored by kind and fading over the marker's lifetime
|
|
643
|
+
|
|
644
|
+
- `WorldPings` (function) · `import { WorldPings } from "@jgengine/shell/world/WorldPings"`
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# Overhead enemy nameplates and health bars
|
|
2
|
+
|
|
3
|
+
Use this recipe when a game needs floating world-anchored frames over entities —
|
|
4
|
+
enemy nameplates with a health bar, interaction prompts, objective pips. The
|
|
5
|
+
game keeps owning its entities; JGengine owns only the reusable behavior:
|
|
6
|
+
projecting a world position to the screen, offsetting above the head, culling
|
|
7
|
+
frames that are off-screen or behind the camera, and stacking nearer frames over
|
|
8
|
+
farther ones. You compose the frame markup itself from the shipped bars, so the
|
|
9
|
+
look is the game's, not a prefab.
|
|
10
|
+
|
|
11
|
+
The seam is data-first and caller-owned: pass an array of
|
|
12
|
+
`{ id, worldPosition, ... }` and a projector. Nothing is mirrored into a store.
|
|
13
|
+
|
|
14
|
+
## Install
|
|
15
|
+
|
|
16
|
+
```sh
|
|
17
|
+
bun add @jgengine/core @jgengine/react
|
|
18
|
+
# @jgengine/shell only for the R3F projection convenience below
|
|
19
|
+
bun add @jgengine/shell
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
`@jgengine/react/entityFrames` imports neither Three.js nor React Three Fiber and
|
|
23
|
+
needs no `GameProvider`. The `@jgengine/shell` piece is a thin R3F convenience.
|
|
24
|
+
|
|
25
|
+
## R3F game: one component from your own entity array
|
|
26
|
+
|
|
27
|
+
`WorldEntityFrames` mounts inside the R3F scene, samples the live camera each
|
|
28
|
+
frame, and renders the frames through a fullscreen overlay. Pass the entities you
|
|
29
|
+
already have and a `renderFrame` that composes the shipped `HealthBar` plus a
|
|
30
|
+
name. Projection, culling, and stacking come for free.
|
|
31
|
+
|
|
32
|
+
```tsx
|
|
33
|
+
import { WorldEntityFrames } from "@jgengine/shell/world/WorldEntityFrames";
|
|
34
|
+
import { HealthBar, barTokens } from "@jgengine/react/bars";
|
|
35
|
+
|
|
36
|
+
interface Enemy {
|
|
37
|
+
id: string;
|
|
38
|
+
name: string;
|
|
39
|
+
position: [number, number, number];
|
|
40
|
+
hp: number;
|
|
41
|
+
maxHp: number;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function EnemyNameplates({ enemies }: { enemies: readonly Enemy[] }) {
|
|
45
|
+
const entries = enemies.map((e) => ({
|
|
46
|
+
id: e.id,
|
|
47
|
+
// Anchor over the head: lift the world Y by the entity's height.
|
|
48
|
+
worldPosition: [e.position[0], e.position[1] + 2.2, e.position[2]] as const,
|
|
49
|
+
enemy: e,
|
|
50
|
+
}));
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
<WorldEntityFrames
|
|
54
|
+
entries={entries}
|
|
55
|
+
maxCount={24} // keep the nearest 24 when a crowd is on screen
|
|
56
|
+
renderFrame={({ enemy }) => (
|
|
57
|
+
<div style={{ ...barTokens({ health: "#e5484d" }), textAlign: "center" }}>
|
|
58
|
+
<span
|
|
59
|
+
style={{
|
|
60
|
+
fontSize: 12,
|
|
61
|
+
fontWeight: 700,
|
|
62
|
+
color: "#f1f5f9",
|
|
63
|
+
textShadow: "0 1px 3px rgba(0,0,0,0.9)",
|
|
64
|
+
whiteSpace: "nowrap",
|
|
65
|
+
}}
|
|
66
|
+
>
|
|
67
|
+
{enemy.name}
|
|
68
|
+
</span>
|
|
69
|
+
<HealthBar value={enemy.hp} max={enemy.maxHp} width={78} showValue={false} shape="pill" />
|
|
70
|
+
</div>
|
|
71
|
+
)}
|
|
72
|
+
/>
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Reskin the whole set with one `HudTheme`/`barTokens` object on an ancestor —
|
|
78
|
+
health color, frame material, radius, and glow flow to every plate's `HealthBar`.
|
|
79
|
+
The `enemy` payload rides along on each entry, so `renderFrame` reads live values
|
|
80
|
+
without a second lookup.
|
|
81
|
+
|
|
82
|
+
## Non-R3F game: bring your own projector
|
|
83
|
+
|
|
84
|
+
Outside R3F (a 2D or custom-renderer game), use the headless
|
|
85
|
+
`EntityFrames` directly and pass a `project` that maps a world position to a
|
|
86
|
+
screen point — return `null`, or `{ behind: true }`, to cull an entry. `depth`
|
|
87
|
+
(larger = farther) drives stacking.
|
|
88
|
+
|
|
89
|
+
```tsx
|
|
90
|
+
import { EntityFrames, type ProjectEntity } from "@jgengine/react/entityFrames";
|
|
91
|
+
import { HealthBar } from "@jgengine/react/bars";
|
|
92
|
+
|
|
93
|
+
const project: ProjectEntity = (world) => {
|
|
94
|
+
const screen = myCamera.worldToScreen(world); // your renderer's projection
|
|
95
|
+
if (screen === null) return null; // outside the frustum → culled
|
|
96
|
+
return { x: screen.x, y: screen.y, depth: screen.distance, behind: screen.behind };
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
export function Nameplates({ enemies }: { enemies: readonly Enemy[] }) {
|
|
100
|
+
return (
|
|
101
|
+
<EntityFrames
|
|
102
|
+
entries={enemies.map((e) => ({ id: e.id, worldPosition: e.position, enemy: e }))}
|
|
103
|
+
project={project}
|
|
104
|
+
offsetY={-24}
|
|
105
|
+
viewport={{ width: window.innerWidth, height: window.innerHeight }}
|
|
106
|
+
renderFrame={({ enemy }) => (
|
|
107
|
+
<HealthBar value={enemy.hp} max={enemy.maxHp} width={78} showValue={false} />
|
|
108
|
+
)}
|
|
109
|
+
/>
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Mount either component inside `HudCanvas` (or any positioned ancestor) so the
|
|
115
|
+
overlay is bounded to the viewport.
|
|
116
|
+
|
|
117
|
+
## Ownership
|
|
118
|
+
|
|
119
|
+
The game still owns its entities, their positions, health, updates, camera, and
|
|
120
|
+
the render cadence. JGengine owns the projection→offset→cull→stack behavior
|
|
121
|
+
(`layoutEntityFrames`, unit-tested) and, for R3F, the camera→screen projector
|
|
122
|
+
(`useWorldProjection` / `projectWorldToScreen`). The frame markup is yours.
|
|
123
|
+
|
|
124
|
+
## Common traps
|
|
125
|
+
|
|
126
|
+
- Pass a fresh `entries` array each frame (or memo it on your live data). The
|
|
127
|
+
component re-projects on the R3F frame loop; the pure `EntityFrames` re-projects
|
|
128
|
+
whenever it re-renders.
|
|
129
|
+
- Lift `worldPosition` by the entity's height for an overhead anchor — the seam
|
|
130
|
+
does not guess a height.
|
|
131
|
+
- Set `maxCount` for crowds so a battlefield of entities does not render hundreds
|
|
132
|
+
of plates; the nearest are kept.
|
|
133
|
+
- Do not mirror entities into a `GameProvider`/entity store to use this. If the
|
|
134
|
+
game *does* run the JGengine entity store, `WorldNameplates`
|
|
135
|
+
(`@jgengine/shell/world/WorldHud`) is the store-driven counterpart.
|
|
136
|
+
- Keep `renderFrame` cheap — it runs per visible entity per refresh.
|