@almadar/ui 5.109.0 → 5.111.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/dist/avl/index.cjs +32 -13
- package/dist/avl/index.js +32 -13
- package/dist/components/game/atoms/DrawShape.d.ts +6 -6
- package/dist/components/game/atoms/DrawSprite.d.ts +2 -2
- package/dist/components/index.cjs +29 -13
- package/dist/components/index.js +29 -13
- package/dist/lib/drawable/three/index.cjs +330 -178
- package/dist/lib/drawable/three/index.js +174 -22
- package/dist/lib/index.cjs +8 -0
- package/dist/lib/index.js +8 -1
- package/dist/lib/verificationRegistry.d.ts +6 -0
- package/dist/providers/index.cjs +29 -13
- package/dist/providers/index.js +29 -13
- package/dist/runtime/index.cjs +32 -13
- package/dist/runtime/index.js +32 -13
- package/package.json +7 -7
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import
|
|
1
|
+
import React3, { forwardRef, useRef, useState, useEffect, useMemo, useImperativeHandle, useCallback, createContext, useContext, Component, useReducer } from 'react';
|
|
2
2
|
import { EventBusContext, useTraitScope } from '@almadar/ui/providers';
|
|
3
3
|
import { createLogger } from '@almadar/logger';
|
|
4
|
-
import { Canvas, useThree, useFrame
|
|
4
|
+
import { Canvas, useThree, useFrame } from '@react-three/fiber';
|
|
5
5
|
import * as THREE9 from 'three';
|
|
6
6
|
import { Vector3, QuadraticBezierCurve3, MathUtils, Quaternion } from 'three';
|
|
7
7
|
import { Grid, OrbitControls, Billboard, Text, Stars, Sparkles, Html, RoundedBox } from '@react-three/drei';
|
|
@@ -505,6 +505,54 @@ function FollowCamera3D({
|
|
|
505
505
|
});
|
|
506
506
|
return null;
|
|
507
507
|
}
|
|
508
|
+
|
|
509
|
+
// lib/atlasSlice.ts
|
|
510
|
+
var atlasCache = /* @__PURE__ */ new Map();
|
|
511
|
+
function isTilesheet(a) {
|
|
512
|
+
return typeof a.tileWidth === "number";
|
|
513
|
+
}
|
|
514
|
+
function getAtlas(url, onReady) {
|
|
515
|
+
if (atlasCache.has(url)) return atlasCache.get(url) ?? void 0;
|
|
516
|
+
atlasCache.set(url, void 0);
|
|
517
|
+
fetch(url).then((r) => r.json()).then((json) => {
|
|
518
|
+
atlasCache.set(url, json);
|
|
519
|
+
onReady();
|
|
520
|
+
}).catch(() => {
|
|
521
|
+
atlasCache.set(url, null);
|
|
522
|
+
});
|
|
523
|
+
return void 0;
|
|
524
|
+
}
|
|
525
|
+
function subRectFor(atlas, sprite) {
|
|
526
|
+
if (isTilesheet(atlas)) {
|
|
527
|
+
let col;
|
|
528
|
+
let row;
|
|
529
|
+
if (sprite.includes(",")) {
|
|
530
|
+
const [c, r] = sprite.split(",").map((n) => Number(n.trim()));
|
|
531
|
+
col = c;
|
|
532
|
+
row = r;
|
|
533
|
+
} else {
|
|
534
|
+
const i = Number(sprite);
|
|
535
|
+
if (!Number.isFinite(i)) return null;
|
|
536
|
+
col = i % atlas.columns;
|
|
537
|
+
row = Math.floor(i / atlas.columns);
|
|
538
|
+
}
|
|
539
|
+
if (!Number.isFinite(col) || !Number.isFinite(row) || col < 0 || row < 0 || col >= atlas.columns || row >= atlas.rows) return null;
|
|
540
|
+
const margin = atlas.margin ?? 0;
|
|
541
|
+
const spacing = atlas.spacing ?? 0;
|
|
542
|
+
return {
|
|
543
|
+
sx: margin + col * (atlas.tileWidth + spacing),
|
|
544
|
+
sy: margin + row * (atlas.tileHeight + spacing),
|
|
545
|
+
sw: atlas.tileWidth,
|
|
546
|
+
sh: atlas.tileHeight
|
|
547
|
+
};
|
|
548
|
+
}
|
|
549
|
+
const st = atlas.subTextures[sprite];
|
|
550
|
+
if (!st) return null;
|
|
551
|
+
return { sx: st.x, sy: st.y, sw: st.width, sh: st.height };
|
|
552
|
+
}
|
|
553
|
+
function isAtlasAsset(asset) {
|
|
554
|
+
return !!asset && typeof asset.atlas === "string" && typeof asset.sprite === "string";
|
|
555
|
+
}
|
|
508
556
|
var log3 = createLogger("almadar:ui:game:model-loader");
|
|
509
557
|
var gltfCache = /* @__PURE__ */ new Map();
|
|
510
558
|
function loadGltfCached(url, assetRoot) {
|
|
@@ -706,22 +754,126 @@ function ModelLoader({
|
|
|
706
754
|
}
|
|
707
755
|
);
|
|
708
756
|
}
|
|
757
|
+
var CrossOriginTextureLoader = class extends THREE9.TextureLoader {
|
|
758
|
+
constructor() {
|
|
759
|
+
super();
|
|
760
|
+
this.crossOrigin = "anonymous";
|
|
761
|
+
}
|
|
762
|
+
};
|
|
763
|
+
function useBillboardTexture(url) {
|
|
764
|
+
const [state, setState] = React3.useState({
|
|
765
|
+
texture: null,
|
|
766
|
+
error: false
|
|
767
|
+
});
|
|
768
|
+
React3.useEffect(() => {
|
|
769
|
+
let active = true;
|
|
770
|
+
const loader = new CrossOriginTextureLoader();
|
|
771
|
+
loader.load(
|
|
772
|
+
url,
|
|
773
|
+
(texture) => {
|
|
774
|
+
if (!active) return;
|
|
775
|
+
console.log("[SpriteBillboard] texture loaded", url, texture.image?.width, texture.image?.height);
|
|
776
|
+
texture.colorSpace = THREE9.SRGBColorSpace;
|
|
777
|
+
setState({ texture, error: false });
|
|
778
|
+
},
|
|
779
|
+
void 0,
|
|
780
|
+
(err) => {
|
|
781
|
+
if (!active) return;
|
|
782
|
+
console.error("[SpriteBillboard] texture load error", url, err);
|
|
783
|
+
setState({ texture: null, error: true });
|
|
784
|
+
}
|
|
785
|
+
);
|
|
786
|
+
return () => {
|
|
787
|
+
active = false;
|
|
788
|
+
};
|
|
789
|
+
}, [url]);
|
|
790
|
+
return state;
|
|
791
|
+
}
|
|
792
|
+
function useAtlasFrame(asset) {
|
|
793
|
+
const [tick, setTick] = React3.useState(0);
|
|
794
|
+
React3.useEffect(() => {
|
|
795
|
+
if (!isAtlasAsset(asset)) return;
|
|
796
|
+
getAtlas(asset.atlas, () => setTick((t) => t + 1));
|
|
797
|
+
}, [asset, tick]);
|
|
798
|
+
return React3.useMemo(() => {
|
|
799
|
+
if (!isAtlasAsset(asset)) return { frame: null, ready: true };
|
|
800
|
+
const atlas = getAtlas(asset.atlas, () => setTick((t) => t + 1));
|
|
801
|
+
if (!atlas) {
|
|
802
|
+
console.log("[SpriteBillboard] atlas not ready", asset.atlas, asset.sprite);
|
|
803
|
+
return { frame: null, ready: false };
|
|
804
|
+
}
|
|
805
|
+
const r = subRectFor(atlas, asset.sprite);
|
|
806
|
+
console.log("[SpriteBillboard] atlas frame", asset.atlas, asset.sprite, r);
|
|
807
|
+
if (!r) return { frame: null, ready: true };
|
|
808
|
+
return { frame: { x: r.sx, y: r.sy, w: r.sw, h: r.sh }, ready: true };
|
|
809
|
+
}, [asset, tick]);
|
|
810
|
+
}
|
|
709
811
|
function SpriteBillboard({ node, world }) {
|
|
710
|
-
const texture =
|
|
711
|
-
const
|
|
712
|
-
const
|
|
713
|
-
const
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
812
|
+
const { texture, error: textureError } = useBillboardTexture(node.asset.url);
|
|
813
|
+
const { frame: atlasFrame, ready: atlasReady } = useAtlasFrame(node.asset);
|
|
814
|
+
const frame = node.frame ?? atlasFrame;
|
|
815
|
+
const anchor = node.anchor ?? "top-left";
|
|
816
|
+
console.log("[SpriteBillboard] render", node.asset.url, anchor, frame, "texture?", !!texture, "atlasReady?", atlasReady);
|
|
817
|
+
const size = React3.useMemo(() => {
|
|
818
|
+
const img = texture?.image;
|
|
819
|
+
const imgW = img?.width || 1;
|
|
820
|
+
const imgH = img?.height || 1;
|
|
821
|
+
const aspect = frame ? frame.w / frame.h : imgW / imgH;
|
|
822
|
+
if (anchor === "top-left") {
|
|
823
|
+
const width2 = node.width ?? 1;
|
|
824
|
+
const height2 = node.height ?? 1;
|
|
825
|
+
return { width: width2, height: height2, imgW, imgH };
|
|
826
|
+
}
|
|
827
|
+
const height = node.height ?? 1;
|
|
828
|
+
const width = node.width ?? height * aspect;
|
|
829
|
+
return { width, height, imgW, imgH };
|
|
830
|
+
}, [texture, frame, node.height, node.width, anchor]);
|
|
831
|
+
if (!texture || !atlasReady) {
|
|
832
|
+
if (anchor === "top-left") {
|
|
833
|
+
return /* @__PURE__ */ jsx("group", { position: [world[0] + size.width / 2, 0.02, world[2] + size.height / 2], children: /* @__PURE__ */ jsxs("mesh", { rotation: [-Math.PI / 2, 0, 0], children: [
|
|
834
|
+
/* @__PURE__ */ jsx("planeGeometry", { args: [size.width, size.height] }),
|
|
835
|
+
/* @__PURE__ */ jsx("meshBasicMaterial", { color: textureError ? 16729156 : 8947848, transparent: true, opacity: 0.6, side: THREE9.DoubleSide })
|
|
836
|
+
] }) });
|
|
837
|
+
}
|
|
838
|
+
return /* @__PURE__ */ jsx("group", { position: [world[0], world[1] + size.height / 2, world[2]], children: /* @__PURE__ */ jsxs("mesh", { children: [
|
|
839
|
+
/* @__PURE__ */ jsx("planeGeometry", { args: [size.width, size.height] }),
|
|
840
|
+
/* @__PURE__ */ jsx("meshBasicMaterial", { color: textureError ? 16729156 : 8947848, transparent: true, opacity: 0.6, side: THREE9.DoubleSide })
|
|
841
|
+
] }) });
|
|
842
|
+
}
|
|
843
|
+
const groundGeometry = React3.useMemo(() => {
|
|
844
|
+
if (anchor !== "top-left" || !texture || !atlasReady) return null;
|
|
845
|
+
const g = new THREE9.PlaneGeometry(size.width, size.height);
|
|
846
|
+
g.rotateX(-Math.PI / 2);
|
|
847
|
+
if (frame) {
|
|
848
|
+
const u0 = frame.x / size.imgW;
|
|
849
|
+
const v0 = 1 - (frame.y + frame.h) / size.imgH;
|
|
850
|
+
const u1 = u0 + frame.w / size.imgW;
|
|
851
|
+
const v1 = v0 + frame.h / size.imgH;
|
|
852
|
+
const uvs = new Float32Array([u0, v1, u1, v1, u0, v0, u1, v0]);
|
|
853
|
+
g.setAttribute("uv", new THREE9.BufferAttribute(uvs, 2));
|
|
854
|
+
}
|
|
855
|
+
return g;
|
|
856
|
+
}, [anchor, texture, atlasReady, size.width, size.height, size.imgW, size.imgH, frame]);
|
|
857
|
+
texture.magFilter = texture.minFilter = THREE9.NearestFilter;
|
|
858
|
+
texture.needsUpdate = true;
|
|
859
|
+
if (anchor === "top-left") {
|
|
860
|
+
return /* @__PURE__ */ jsx("group", { position: [world[0] + size.width / 2, 0.01, world[2] + size.height / 2], children: /* @__PURE__ */ jsx("mesh", { geometry: groundGeometry ?? void 0, children: /* @__PURE__ */ jsx(
|
|
861
|
+
"meshBasicMaterial",
|
|
862
|
+
{
|
|
863
|
+
map: texture,
|
|
864
|
+
transparent: true,
|
|
865
|
+
alphaTest: 0.1,
|
|
866
|
+
side: THREE9.DoubleSide,
|
|
867
|
+
opacity: node.opacity ?? 1
|
|
868
|
+
}
|
|
869
|
+
) }) });
|
|
870
|
+
}
|
|
871
|
+
if (frame) {
|
|
872
|
+
texture.repeat.set(frame.w / size.imgW, frame.h / size.imgH);
|
|
873
|
+
texture.offset.set(frame.x / size.imgW, 1 - (frame.y + frame.h) / size.imgH);
|
|
719
874
|
}
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
const width = node.width ?? height * aspect;
|
|
723
|
-
return /* @__PURE__ */ jsx(Billboard, { position: [world[0], world[1] + height / 2, world[2]], children: /* @__PURE__ */ jsxs("mesh", { children: [
|
|
724
|
-
/* @__PURE__ */ jsx("planeGeometry", { args: [width, height] }),
|
|
875
|
+
return /* @__PURE__ */ jsx(Billboard, { position: [world[0], world[1] + size.height / 2, world[2]], children: /* @__PURE__ */ jsxs("mesh", { children: [
|
|
876
|
+
/* @__PURE__ */ jsx("planeGeometry", { args: [size.width, size.height] }),
|
|
725
877
|
/* @__PURE__ */ jsx(
|
|
726
878
|
"meshBasicMaterial",
|
|
727
879
|
{
|
|
@@ -2508,7 +2660,7 @@ var positionStyles = {
|
|
|
2508
2660
|
fixed: "fixed",
|
|
2509
2661
|
sticky: "sticky"
|
|
2510
2662
|
};
|
|
2511
|
-
var Box =
|
|
2663
|
+
var Box = React3.forwardRef(
|
|
2512
2664
|
({
|
|
2513
2665
|
padding,
|
|
2514
2666
|
paddingX,
|
|
@@ -2573,7 +2725,7 @@ var Box = React6.forwardRef(
|
|
|
2573
2725
|
onPointerDown?.(e);
|
|
2574
2726
|
}, [hoverEvent, tapReveal, triggerProps, onPointerDown]);
|
|
2575
2727
|
const isClickable = action || onClick;
|
|
2576
|
-
return
|
|
2728
|
+
return React3.createElement(
|
|
2577
2729
|
Component2,
|
|
2578
2730
|
{
|
|
2579
2731
|
ref,
|
|
@@ -2694,7 +2846,7 @@ var Typography = ({
|
|
|
2694
2846
|
}) => {
|
|
2695
2847
|
const variant = variantProp ?? (level ? `h${level}` : "body1");
|
|
2696
2848
|
const Component2 = as || defaultElements[variant];
|
|
2697
|
-
return
|
|
2849
|
+
return React3.createElement(
|
|
2698
2850
|
Component2,
|
|
2699
2851
|
{
|
|
2700
2852
|
id,
|
|
@@ -2767,7 +2919,7 @@ var Stack = ({
|
|
|
2767
2919
|
};
|
|
2768
2920
|
const isHorizontal = direction === "horizontal";
|
|
2769
2921
|
const directionClass = responsive && isHorizontal ? reverse ? "flex-col-reverse md:flex-row-reverse" : "flex-col md:flex-row" : isHorizontal ? reverse ? "flex-row-reverse" : "flex-row" : reverse ? "flex-col-reverse" : "flex-col";
|
|
2770
|
-
return
|
|
2922
|
+
return React3.createElement(
|
|
2771
2923
|
Component2,
|
|
2772
2924
|
{
|
|
2773
2925
|
className: cn(
|
|
@@ -5062,7 +5214,7 @@ var Avl3DViewer = ({
|
|
|
5062
5214
|
const handleTraitClick = useCallback((name) => {
|
|
5063
5215
|
dispatch({ type: "ZOOM_INTO_TRAIT", trait: name, targetPosition: { x: 0, y: 0 } });
|
|
5064
5216
|
}, []);
|
|
5065
|
-
const [highlightedTrait, setHighlightedTrait] =
|
|
5217
|
+
const [highlightedTrait, setHighlightedTrait] = React3.useState(null);
|
|
5066
5218
|
const handleTransitionClick = useCallback((index) => {
|
|
5067
5219
|
dispatch({ type: "ZOOM_INTO_TRANSITION", transitionIndex: index, targetPosition: { x: 0, y: 0 } });
|
|
5068
5220
|
}, []);
|
|
@@ -5149,7 +5301,7 @@ var Avl3DViewer = ({
|
|
|
5149
5301
|
gap: "xs",
|
|
5150
5302
|
align: "center",
|
|
5151
5303
|
className: "absolute top-2 left-2 z-10 bg-surface/80 backdrop-blur rounded-md px-3 py-1.5",
|
|
5152
|
-
children: breadcrumbs.map((crumb, i) => /* @__PURE__ */ jsxs(
|
|
5304
|
+
children: breadcrumbs.map((crumb, i) => /* @__PURE__ */ jsxs(React3.Fragment, { children: [
|
|
5153
5305
|
i > 0 && /* @__PURE__ */ jsx(Typography, { variant: "small", color: "muted", className: "mx-1", children: "/" }),
|
|
5154
5306
|
i < breadcrumbs.length - 1 ? /* @__PURE__ */ jsx(
|
|
5155
5307
|
Box,
|
package/dist/lib/index.cjs
CHANGED
|
@@ -737,6 +737,13 @@ function bindCanvasCapture(captureFn) {
|
|
|
737
737
|
window.__orbitalVerification.captureFrame = captureFn;
|
|
738
738
|
}
|
|
739
739
|
}
|
|
740
|
+
function bindLastDrawables(getDrawables) {
|
|
741
|
+
if (typeof window === "undefined") return;
|
|
742
|
+
exposeOnWindow();
|
|
743
|
+
if (window.__orbitalVerification) {
|
|
744
|
+
window.__orbitalVerification.getLastDrawables = getDrawables;
|
|
745
|
+
}
|
|
746
|
+
}
|
|
740
747
|
function updateAssetStatus(url, status) {
|
|
741
748
|
if (typeof window === "undefined") return;
|
|
742
749
|
exposeOnWindow();
|
|
@@ -1818,6 +1825,7 @@ exports.apiClient = apiClient;
|
|
|
1818
1825
|
exports.arrowheadPath = arrowheadPath;
|
|
1819
1826
|
exports.bindCanvasCapture = bindCanvasCapture;
|
|
1820
1827
|
exports.bindEventBus = bindEventBus;
|
|
1828
|
+
exports.bindLastDrawables = bindLastDrawables;
|
|
1821
1829
|
exports.bindTraitStateGetter = bindTraitStateGetter;
|
|
1822
1830
|
exports.brainIconPath = brainIconPath;
|
|
1823
1831
|
exports.clearDebugEvents = clearDebugEvents;
|
package/dist/lib/index.js
CHANGED
|
@@ -735,6 +735,13 @@ function bindCanvasCapture(captureFn) {
|
|
|
735
735
|
window.__orbitalVerification.captureFrame = captureFn;
|
|
736
736
|
}
|
|
737
737
|
}
|
|
738
|
+
function bindLastDrawables(getDrawables) {
|
|
739
|
+
if (typeof window === "undefined") return;
|
|
740
|
+
exposeOnWindow();
|
|
741
|
+
if (window.__orbitalVerification) {
|
|
742
|
+
window.__orbitalVerification.getLastDrawables = getDrawables;
|
|
743
|
+
}
|
|
744
|
+
}
|
|
738
745
|
function updateAssetStatus(url, status) {
|
|
739
746
|
if (typeof window === "undefined") return;
|
|
740
747
|
exposeOnWindow();
|
|
@@ -1809,4 +1816,4 @@ var JAZARI_COLORS = {
|
|
|
1809
1816
|
darkBg: "#1a1a2e"
|
|
1810
1817
|
};
|
|
1811
1818
|
|
|
1812
|
-
export { ApiError, DEFAULT_CONFIG, JAZARI_COLORS, apiClient, arrowheadPath, bindCanvasCapture, bindEventBus, bindTraitStateGetter, brainIconPath, clearDebugEvents, clearEntityProvider, clearGuardHistory, clearTicks, clearTraits, clearVerification, cn, computeJazariLayout, debug, debugCollision, debugError, debugGameState, debugGroup, debugGroupEnd, debugInput, debugPhysics, debugTable, debugTime, debugTimeEnd, debugWarn, eightPointedStarPath, extractOutputsFromTransitions, extractStateMachine, formatGuard, formatNestedFieldLabel, gearTeethPath, getAllChecks, getAllTicks, getAllTraits, getBridgeHealth, getDebugEvents, getEffectSummary, getEntitiesByType, getEntityById, getEntitySnapshot, getEventsBySource, getEventsByType, getGuardEvaluationsForTrait, getGuardHistory, getNestedValue, getRecentEvents, getRecentGuardEvaluations, getSnapshot, getSummary, getTick, getTrait, getTraitSnapshots, getTransitions, getTransitionsForTrait, initDebugShortcut, isDebugEnabled, lockIconPath, logDebugEvent, logEffectExecuted, logError, logEventFired, logInfo, logStateChange, logWarning, onDebugToggle, parseContentSegments, parseMarkdownWithCodeBlocks, pipeIconPath, recordGuardEvaluation, recordServerResponse, recordTransition, registerCheck, registerTick, registerTrait, registerTraitSnapshot, renderStateMachineToDomData, renderStateMachineToSvg, setDebugEnabled, setEntityProvider, setTickActive, subscribeToDebugEvents, subscribeToGuardChanges, subscribeToTickChanges, subscribeToTraitChanges, subscribeToVerification, toggleDebug, unregisterTick, unregisterTrait, updateAssetStatus, updateBridgeHealth, updateCheck, updateGuardResult, updateTickExecution, updateTraitState, waitForTransition };
|
|
1819
|
+
export { ApiError, DEFAULT_CONFIG, JAZARI_COLORS, apiClient, arrowheadPath, bindCanvasCapture, bindEventBus, bindLastDrawables, bindTraitStateGetter, brainIconPath, clearDebugEvents, clearEntityProvider, clearGuardHistory, clearTicks, clearTraits, clearVerification, cn, computeJazariLayout, debug, debugCollision, debugError, debugGameState, debugGroup, debugGroupEnd, debugInput, debugPhysics, debugTable, debugTime, debugTimeEnd, debugWarn, eightPointedStarPath, extractOutputsFromTransitions, extractStateMachine, formatGuard, formatNestedFieldLabel, gearTeethPath, getAllChecks, getAllTicks, getAllTraits, getBridgeHealth, getDebugEvents, getEffectSummary, getEntitiesByType, getEntityById, getEntitySnapshot, getEventsBySource, getEventsByType, getGuardEvaluationsForTrait, getGuardHistory, getNestedValue, getRecentEvents, getRecentGuardEvaluations, getSnapshot, getSummary, getTick, getTrait, getTraitSnapshots, getTransitions, getTransitionsForTrait, initDebugShortcut, isDebugEnabled, lockIconPath, logDebugEvent, logEffectExecuted, logError, logEventFired, logInfo, logStateChange, logWarning, onDebugToggle, parseContentSegments, parseMarkdownWithCodeBlocks, pipeIconPath, recordGuardEvaluation, recordServerResponse, recordTransition, registerCheck, registerTick, registerTrait, registerTraitSnapshot, renderStateMachineToDomData, renderStateMachineToSvg, setDebugEnabled, setEntityProvider, setTickActive, subscribeToDebugEvents, subscribeToGuardChanges, subscribeToTickChanges, subscribeToTraitChanges, subscribeToVerification, toggleDebug, unregisterTick, unregisterTrait, updateAssetStatus, updateBridgeHealth, updateCheck, updateGuardResult, updateTickExecution, updateTraitState, waitForTransition };
|
|
@@ -83,6 +83,12 @@ export declare function registerTraitSnapshot(traitName: string, getter: TraitSn
|
|
|
83
83
|
* so the verifier can snapshot canvas content at checkpoints.
|
|
84
84
|
*/
|
|
85
85
|
export declare function bindCanvasCapture(captureFn: () => string | null): void;
|
|
86
|
+
/**
|
|
87
|
+
* Bind a reader for the last drawables list received by a canvas host.
|
|
88
|
+
* Lets verification scripts inspect exactly which neutral descriptors reached
|
|
89
|
+
* the painter without re-deriving them from state.
|
|
90
|
+
*/
|
|
91
|
+
export declare function bindLastDrawables(getDrawables: () => unknown[] | null): void;
|
|
86
92
|
/**
|
|
87
93
|
* Update asset load status for canvas verification.
|
|
88
94
|
* Game organisms call this when images load or fail.
|
package/dist/providers/index.cjs
CHANGED
|
@@ -7407,6 +7407,13 @@ function bindCanvasCapture(captureFn) {
|
|
|
7407
7407
|
window.__orbitalVerification.captureFrame = captureFn;
|
|
7408
7408
|
}
|
|
7409
7409
|
}
|
|
7410
|
+
function bindLastDrawables(getDrawables) {
|
|
7411
|
+
if (typeof window === "undefined") return;
|
|
7412
|
+
exposeOnWindow();
|
|
7413
|
+
if (window.__orbitalVerification) {
|
|
7414
|
+
window.__orbitalVerification.getLastDrawables = getDrawables;
|
|
7415
|
+
}
|
|
7416
|
+
}
|
|
7410
7417
|
function updateAssetStatus(url, status) {
|
|
7411
7418
|
if (typeof window === "undefined") return;
|
|
7412
7419
|
exposeOnWindow();
|
|
@@ -9251,8 +9258,9 @@ var init_DrawSprite = __esm({
|
|
|
9251
9258
|
if (!r) return;
|
|
9252
9259
|
src = { x: r.sx, y: r.sy, w: r.sw, h: r.sh };
|
|
9253
9260
|
}
|
|
9254
|
-
const
|
|
9255
|
-
const
|
|
9261
|
+
const tw = dctx.projector.tileWidth;
|
|
9262
|
+
const w = node.width !== void 0 ? node.width * tw : src ? src.w : tex.width;
|
|
9263
|
+
const h = node.height !== void 0 ? node.height * tw : src ? src.h : tex.height;
|
|
9256
9264
|
const anchor = node.anchor ?? "top-left";
|
|
9257
9265
|
const p = dctx.projector.anchorPoint(node.position, anchor);
|
|
9258
9266
|
const dx = anchor === "top-left" ? p.x : p.x - w / 2;
|
|
@@ -9299,27 +9307,30 @@ var init_DrawShape = __esm({
|
|
|
9299
9307
|
}
|
|
9300
9308
|
case "rect": {
|
|
9301
9309
|
const p = dctx.projector.anchorPoint(node.position, node.anchor ?? "top-left");
|
|
9302
|
-
const
|
|
9303
|
-
const
|
|
9304
|
-
const
|
|
9305
|
-
const
|
|
9310
|
+
const tw = dctx.projector.tileWidth;
|
|
9311
|
+
const x = p.x + (node.offsetX ?? 0) * tw;
|
|
9312
|
+
const y = p.y + (node.offsetY ?? 0) * tw;
|
|
9313
|
+
const w = (node.width ?? 0) * tw;
|
|
9314
|
+
const h = (node.height ?? 0) * tw;
|
|
9306
9315
|
if (node.fill) painter.fillRect(x, y, w, h, node.fill);
|
|
9307
9316
|
if (node.stroke) painter.strokeRect(x, y, w, h, node.stroke, node.strokeWidth ?? 1);
|
|
9308
9317
|
break;
|
|
9309
9318
|
}
|
|
9310
9319
|
case "ellipse": {
|
|
9311
9320
|
const p = dctx.projector.anchorPoint(node.position, node.anchor ?? "ground");
|
|
9312
|
-
const
|
|
9313
|
-
const
|
|
9314
|
-
const
|
|
9315
|
-
const
|
|
9321
|
+
const tw = dctx.projector.tileWidth;
|
|
9322
|
+
const cx = p.x + (node.offsetX ?? 0) * tw;
|
|
9323
|
+
const cy = p.y + (node.offsetY ?? 0) * tw;
|
|
9324
|
+
const rx = (node.radiusX ?? 0) * tw;
|
|
9325
|
+
const ry = (node.radiusY ?? rx) * tw;
|
|
9316
9326
|
if (node.fill) painter.fillEllipse(cx, cy, rx, ry, node.fill);
|
|
9317
9327
|
if (node.stroke) painter.strokeEllipse(cx, cy, rx, ry, node.stroke, node.strokeWidth ?? 1);
|
|
9318
9328
|
break;
|
|
9319
9329
|
}
|
|
9320
9330
|
case "poly": {
|
|
9321
9331
|
const base = dctx.projector.project(node.position);
|
|
9322
|
-
const
|
|
9332
|
+
const tw = dctx.projector.tileWidth;
|
|
9333
|
+
const pts = (node.points ?? []).map((pt) => ({ x: base.x + pt.x * tw, y: base.y + pt.y * tw }));
|
|
9323
9334
|
if (node.fill) painter.fillPoly(pts, node.fill);
|
|
9324
9335
|
if (node.stroke) painter.strokePoly(pts, node.stroke, node.strokeWidth ?? 1, true);
|
|
9325
9336
|
break;
|
|
@@ -9550,10 +9561,12 @@ function Canvas2D({
|
|
|
9550
9561
|
const canvas = canvasRef.current;
|
|
9551
9562
|
if (!canvas) return;
|
|
9552
9563
|
bindCanvasCapture(() => canvas.toDataURL("image/png"));
|
|
9564
|
+
bindLastDrawables(() => drawables ?? null);
|
|
9553
9565
|
return () => {
|
|
9554
9566
|
bindCanvasCapture(() => null);
|
|
9567
|
+
bindLastDrawables(() => null);
|
|
9555
9568
|
};
|
|
9556
|
-
}, []);
|
|
9569
|
+
}, [drawables]);
|
|
9557
9570
|
const enableCamera = camera === "pan-zoom";
|
|
9558
9571
|
const {
|
|
9559
9572
|
cameraRef,
|
|
@@ -9568,7 +9581,7 @@ function Canvas2D({
|
|
|
9568
9581
|
screenToWorld,
|
|
9569
9582
|
lerpToTarget
|
|
9570
9583
|
} = useCamera();
|
|
9571
|
-
const [, setAtlasVersion] = React83.useState(0);
|
|
9584
|
+
const [atlasVersion, setAtlasVersion] = React83.useState(0);
|
|
9572
9585
|
const bumpAtlas = React83.useCallback(() => setAtlasVersion((v) => v + 1), []);
|
|
9573
9586
|
const miniMapTiles = React83.useMemo(() => {
|
|
9574
9587
|
if (!showMinimap) return [];
|
|
@@ -9636,6 +9649,9 @@ function Canvas2D({
|
|
|
9636
9649
|
React83.useEffect(() => {
|
|
9637
9650
|
draw();
|
|
9638
9651
|
}, [_imagePendingCount, draw]);
|
|
9652
|
+
React83.useEffect(() => {
|
|
9653
|
+
draw();
|
|
9654
|
+
}, [atlasVersion, draw]);
|
|
9639
9655
|
React83.useEffect(() => {
|
|
9640
9656
|
if (camera !== "follow" || !followTarget) return;
|
|
9641
9657
|
let running = true;
|
package/dist/providers/index.js
CHANGED
|
@@ -7362,6 +7362,13 @@ function bindCanvasCapture(captureFn) {
|
|
|
7362
7362
|
window.__orbitalVerification.captureFrame = captureFn;
|
|
7363
7363
|
}
|
|
7364
7364
|
}
|
|
7365
|
+
function bindLastDrawables(getDrawables) {
|
|
7366
|
+
if (typeof window === "undefined") return;
|
|
7367
|
+
exposeOnWindow();
|
|
7368
|
+
if (window.__orbitalVerification) {
|
|
7369
|
+
window.__orbitalVerification.getLastDrawables = getDrawables;
|
|
7370
|
+
}
|
|
7371
|
+
}
|
|
7365
7372
|
function updateAssetStatus(url, status) {
|
|
7366
7373
|
if (typeof window === "undefined") return;
|
|
7367
7374
|
exposeOnWindow();
|
|
@@ -9206,8 +9213,9 @@ var init_DrawSprite = __esm({
|
|
|
9206
9213
|
if (!r) return;
|
|
9207
9214
|
src = { x: r.sx, y: r.sy, w: r.sw, h: r.sh };
|
|
9208
9215
|
}
|
|
9209
|
-
const
|
|
9210
|
-
const
|
|
9216
|
+
const tw = dctx.projector.tileWidth;
|
|
9217
|
+
const w = node.width !== void 0 ? node.width * tw : src ? src.w : tex.width;
|
|
9218
|
+
const h = node.height !== void 0 ? node.height * tw : src ? src.h : tex.height;
|
|
9211
9219
|
const anchor = node.anchor ?? "top-left";
|
|
9212
9220
|
const p = dctx.projector.anchorPoint(node.position, anchor);
|
|
9213
9221
|
const dx = anchor === "top-left" ? p.x : p.x - w / 2;
|
|
@@ -9254,27 +9262,30 @@ var init_DrawShape = __esm({
|
|
|
9254
9262
|
}
|
|
9255
9263
|
case "rect": {
|
|
9256
9264
|
const p = dctx.projector.anchorPoint(node.position, node.anchor ?? "top-left");
|
|
9257
|
-
const
|
|
9258
|
-
const
|
|
9259
|
-
const
|
|
9260
|
-
const
|
|
9265
|
+
const tw = dctx.projector.tileWidth;
|
|
9266
|
+
const x = p.x + (node.offsetX ?? 0) * tw;
|
|
9267
|
+
const y = p.y + (node.offsetY ?? 0) * tw;
|
|
9268
|
+
const w = (node.width ?? 0) * tw;
|
|
9269
|
+
const h = (node.height ?? 0) * tw;
|
|
9261
9270
|
if (node.fill) painter.fillRect(x, y, w, h, node.fill);
|
|
9262
9271
|
if (node.stroke) painter.strokeRect(x, y, w, h, node.stroke, node.strokeWidth ?? 1);
|
|
9263
9272
|
break;
|
|
9264
9273
|
}
|
|
9265
9274
|
case "ellipse": {
|
|
9266
9275
|
const p = dctx.projector.anchorPoint(node.position, node.anchor ?? "ground");
|
|
9267
|
-
const
|
|
9268
|
-
const
|
|
9269
|
-
const
|
|
9270
|
-
const
|
|
9276
|
+
const tw = dctx.projector.tileWidth;
|
|
9277
|
+
const cx = p.x + (node.offsetX ?? 0) * tw;
|
|
9278
|
+
const cy = p.y + (node.offsetY ?? 0) * tw;
|
|
9279
|
+
const rx = (node.radiusX ?? 0) * tw;
|
|
9280
|
+
const ry = (node.radiusY ?? rx) * tw;
|
|
9271
9281
|
if (node.fill) painter.fillEllipse(cx, cy, rx, ry, node.fill);
|
|
9272
9282
|
if (node.stroke) painter.strokeEllipse(cx, cy, rx, ry, node.stroke, node.strokeWidth ?? 1);
|
|
9273
9283
|
break;
|
|
9274
9284
|
}
|
|
9275
9285
|
case "poly": {
|
|
9276
9286
|
const base = dctx.projector.project(node.position);
|
|
9277
|
-
const
|
|
9287
|
+
const tw = dctx.projector.tileWidth;
|
|
9288
|
+
const pts = (node.points ?? []).map((pt) => ({ x: base.x + pt.x * tw, y: base.y + pt.y * tw }));
|
|
9278
9289
|
if (node.fill) painter.fillPoly(pts, node.fill);
|
|
9279
9290
|
if (node.stroke) painter.strokePoly(pts, node.stroke, node.strokeWidth ?? 1, true);
|
|
9280
9291
|
break;
|
|
@@ -9505,10 +9516,12 @@ function Canvas2D({
|
|
|
9505
9516
|
const canvas = canvasRef.current;
|
|
9506
9517
|
if (!canvas) return;
|
|
9507
9518
|
bindCanvasCapture(() => canvas.toDataURL("image/png"));
|
|
9519
|
+
bindLastDrawables(() => drawables ?? null);
|
|
9508
9520
|
return () => {
|
|
9509
9521
|
bindCanvasCapture(() => null);
|
|
9522
|
+
bindLastDrawables(() => null);
|
|
9510
9523
|
};
|
|
9511
|
-
}, []);
|
|
9524
|
+
}, [drawables]);
|
|
9512
9525
|
const enableCamera = camera === "pan-zoom";
|
|
9513
9526
|
const {
|
|
9514
9527
|
cameraRef,
|
|
@@ -9523,7 +9536,7 @@ function Canvas2D({
|
|
|
9523
9536
|
screenToWorld,
|
|
9524
9537
|
lerpToTarget
|
|
9525
9538
|
} = useCamera();
|
|
9526
|
-
const [, setAtlasVersion] = useState(0);
|
|
9539
|
+
const [atlasVersion, setAtlasVersion] = useState(0);
|
|
9527
9540
|
const bumpAtlas = useCallback(() => setAtlasVersion((v) => v + 1), []);
|
|
9528
9541
|
const miniMapTiles = useMemo(() => {
|
|
9529
9542
|
if (!showMinimap) return [];
|
|
@@ -9591,6 +9604,9 @@ function Canvas2D({
|
|
|
9591
9604
|
useEffect(() => {
|
|
9592
9605
|
draw();
|
|
9593
9606
|
}, [_imagePendingCount, draw]);
|
|
9607
|
+
useEffect(() => {
|
|
9608
|
+
draw();
|
|
9609
|
+
}, [atlasVersion, draw]);
|
|
9594
9610
|
useEffect(() => {
|
|
9595
9611
|
if (camera !== "follow" || !followTarget) return;
|
|
9596
9612
|
let running = true;
|
package/dist/runtime/index.cjs
CHANGED
|
@@ -7861,6 +7861,13 @@ function bindCanvasCapture(captureFn) {
|
|
|
7861
7861
|
window.__orbitalVerification.captureFrame = captureFn;
|
|
7862
7862
|
}
|
|
7863
7863
|
}
|
|
7864
|
+
function bindLastDrawables(getDrawables) {
|
|
7865
|
+
if (typeof window === "undefined") return;
|
|
7866
|
+
exposeOnWindow();
|
|
7867
|
+
if (window.__orbitalVerification) {
|
|
7868
|
+
window.__orbitalVerification.getLastDrawables = getDrawables;
|
|
7869
|
+
}
|
|
7870
|
+
}
|
|
7864
7871
|
function updateAssetStatus(url, status) {
|
|
7865
7872
|
if (typeof window === "undefined") return;
|
|
7866
7873
|
exposeOnWindow();
|
|
@@ -9598,8 +9605,9 @@ var init_DrawSprite = __esm({
|
|
|
9598
9605
|
if (!r) return;
|
|
9599
9606
|
src = { x: r.sx, y: r.sy, w: r.sw, h: r.sh };
|
|
9600
9607
|
}
|
|
9601
|
-
const
|
|
9602
|
-
const
|
|
9608
|
+
const tw = dctx.projector.tileWidth;
|
|
9609
|
+
const w = node.width !== void 0 ? node.width * tw : src ? src.w : tex.width;
|
|
9610
|
+
const h = node.height !== void 0 ? node.height * tw : src ? src.h : tex.height;
|
|
9603
9611
|
const anchor = node.anchor ?? "top-left";
|
|
9604
9612
|
const p = dctx.projector.anchorPoint(node.position, anchor);
|
|
9605
9613
|
const dx = anchor === "top-left" ? p.x : p.x - w / 2;
|
|
@@ -9646,27 +9654,30 @@ var init_DrawShape = __esm({
|
|
|
9646
9654
|
}
|
|
9647
9655
|
case "rect": {
|
|
9648
9656
|
const p = dctx.projector.anchorPoint(node.position, node.anchor ?? "top-left");
|
|
9649
|
-
const
|
|
9650
|
-
const
|
|
9651
|
-
const
|
|
9652
|
-
const
|
|
9657
|
+
const tw = dctx.projector.tileWidth;
|
|
9658
|
+
const x = p.x + (node.offsetX ?? 0) * tw;
|
|
9659
|
+
const y = p.y + (node.offsetY ?? 0) * tw;
|
|
9660
|
+
const w = (node.width ?? 0) * tw;
|
|
9661
|
+
const h = (node.height ?? 0) * tw;
|
|
9653
9662
|
if (node.fill) painter.fillRect(x, y, w, h, node.fill);
|
|
9654
9663
|
if (node.stroke) painter.strokeRect(x, y, w, h, node.stroke, node.strokeWidth ?? 1);
|
|
9655
9664
|
break;
|
|
9656
9665
|
}
|
|
9657
9666
|
case "ellipse": {
|
|
9658
9667
|
const p = dctx.projector.anchorPoint(node.position, node.anchor ?? "ground");
|
|
9659
|
-
const
|
|
9660
|
-
const
|
|
9661
|
-
const
|
|
9662
|
-
const
|
|
9668
|
+
const tw = dctx.projector.tileWidth;
|
|
9669
|
+
const cx = p.x + (node.offsetX ?? 0) * tw;
|
|
9670
|
+
const cy = p.y + (node.offsetY ?? 0) * tw;
|
|
9671
|
+
const rx = (node.radiusX ?? 0) * tw;
|
|
9672
|
+
const ry = (node.radiusY ?? rx) * tw;
|
|
9663
9673
|
if (node.fill) painter.fillEllipse(cx, cy, rx, ry, node.fill);
|
|
9664
9674
|
if (node.stroke) painter.strokeEllipse(cx, cy, rx, ry, node.stroke, node.strokeWidth ?? 1);
|
|
9665
9675
|
break;
|
|
9666
9676
|
}
|
|
9667
9677
|
case "poly": {
|
|
9668
9678
|
const base = dctx.projector.project(node.position);
|
|
9669
|
-
const
|
|
9679
|
+
const tw = dctx.projector.tileWidth;
|
|
9680
|
+
const pts = (node.points ?? []).map((pt) => ({ x: base.x + pt.x * tw, y: base.y + pt.y * tw }));
|
|
9670
9681
|
if (node.fill) painter.fillPoly(pts, node.fill);
|
|
9671
9682
|
if (node.stroke) painter.strokePoly(pts, node.stroke, node.strokeWidth ?? 1, true);
|
|
9672
9683
|
break;
|
|
@@ -9897,10 +9908,12 @@ function Canvas2D({
|
|
|
9897
9908
|
const canvas = canvasRef.current;
|
|
9898
9909
|
if (!canvas) return;
|
|
9899
9910
|
bindCanvasCapture(() => canvas.toDataURL("image/png"));
|
|
9911
|
+
bindLastDrawables(() => drawables ?? null);
|
|
9900
9912
|
return () => {
|
|
9901
9913
|
bindCanvasCapture(() => null);
|
|
9914
|
+
bindLastDrawables(() => null);
|
|
9902
9915
|
};
|
|
9903
|
-
}, []);
|
|
9916
|
+
}, [drawables]);
|
|
9904
9917
|
const enableCamera = camera === "pan-zoom";
|
|
9905
9918
|
const {
|
|
9906
9919
|
cameraRef,
|
|
@@ -9915,7 +9928,7 @@ function Canvas2D({
|
|
|
9915
9928
|
screenToWorld,
|
|
9916
9929
|
lerpToTarget
|
|
9917
9930
|
} = useCamera();
|
|
9918
|
-
const [, setAtlasVersion] = React81.useState(0);
|
|
9931
|
+
const [atlasVersion, setAtlasVersion] = React81.useState(0);
|
|
9919
9932
|
const bumpAtlas = React81.useCallback(() => setAtlasVersion((v) => v + 1), []);
|
|
9920
9933
|
const miniMapTiles = React81.useMemo(() => {
|
|
9921
9934
|
if (!showMinimap) return [];
|
|
@@ -9983,6 +9996,9 @@ function Canvas2D({
|
|
|
9983
9996
|
React81.useEffect(() => {
|
|
9984
9997
|
draw();
|
|
9985
9998
|
}, [_imagePendingCount, draw]);
|
|
9999
|
+
React81.useEffect(() => {
|
|
10000
|
+
draw();
|
|
10001
|
+
}, [atlasVersion, draw]);
|
|
9986
10002
|
React81.useEffect(() => {
|
|
9987
10003
|
if (camera !== "follow" || !followTarget) return;
|
|
9988
10004
|
let running = true;
|
|
@@ -45234,6 +45250,9 @@ function collectEmbeddedTraits(schema) {
|
|
|
45234
45250
|
if (!traitRef || typeof traitRef !== "object") continue;
|
|
45235
45251
|
const resolved = traitRef._resolved;
|
|
45236
45252
|
const target = resolved && typeof resolved === "object" ? resolved : traitRef;
|
|
45253
|
+
if (target.config) {
|
|
45254
|
+
collectTraitRefsFromValue(target.config, out);
|
|
45255
|
+
}
|
|
45237
45256
|
const transitions = target.stateMachine?.transitions;
|
|
45238
45257
|
if (!Array.isArray(transitions)) continue;
|
|
45239
45258
|
for (const t of transitions) {
|