phaser-jsx
Version:
Use JSX in Phaser.
119 lines • 4.28 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.getRenderContext = getRenderContext;
exports.setRenderContext = setRenderContext;
exports.createRenderContext = createRenderContext;
exports.resetRenderContext = resetRenderContext;
var reconcile_1 = require("../render/reconcile");
var _context = null;
function getRenderContext() {
_context !== null && _context !== void 0 ? _context : (_context = createRenderContext());
return _context;
}
function setRenderContext(context) {
_context = context;
}
function createRenderContext(element, scene, componentFn, componentProps) {
if (element === void 0) { element = null; }
if (scene === void 0) { scene = null; }
if (componentFn === void 0) { componentFn = null; }
if (componentProps === void 0) { componentProps = null; }
var state = new Map();
var effects = new Map();
var pendingEffects = [];
var stateIndex = 0;
var effectIndex = 0;
var gameObjectTree = null;
var isRendering = false;
var needsEffectFlush = false;
function flushEffects() {
if (isRendering) {
needsEffectFlush = true;
return;
}
isRendering = true;
needsEffectFlush = false;
try {
for (var _i = 0, pendingEffects_1 = pendingEffects; _i < pendingEffects_1.length; _i++) {
var _a = pendingEffects_1[_i], key = _a.key, callback = _a.callback, deps = _a.deps;
var prev = effects.get(key);
var shouldRun = !prev || deps === undefined || !areDepsEqual(prev.deps, deps);
if (shouldRun) {
if (typeof (prev === null || prev === void 0 ? void 0 : prev.cleanup) === 'function') {
prev.cleanup();
}
var cleanup = callback();
effects.set(key, { deps: deps, cleanup: cleanup });
}
}
pendingEffects.length = 0;
effectIndex = 0;
}
finally {
isRendering = false;
// If effects were queued during effect execution, flush them
if (needsEffectFlush && pendingEffects.length > 0) {
// Use setTimeout to break the synchronous cycle
setTimeout(flushEffects);
}
}
}
return {
state: state,
effects: effects,
pendingEffects: pendingEffects,
scene: scene,
componentFn: componentFn,
componentProps: componentProps,
gameObjectTree: gameObjectTree,
getNextStateIndex: function () { return stateIndex++; },
resetStateIndex: function () {
stateIndex = 0;
},
getNextEffectIndex: function () { return effectIndex++; },
resetEffectIndex: function () {
effectIndex = 0;
},
flushEffects: flushEffects,
rerender: function () {
stateIndex = 0;
effectIndex = 0;
if (componentFn && componentProps && scene) {
var newElement = componentFn(componentProps);
gameObjectTree = (0, reconcile_1.reconcileTree)(newElement, gameObjectTree, scene);
}
else if (element && scene) {
gameObjectTree = (0, reconcile_1.reconcileTree)(element, gameObjectTree, scene);
}
// Defer effect flushing to prevent infinite loops
setTimeout(flushEffects);
},
};
}
function resetRenderContext() {
if (_context) {
_context.effects.forEach(function (_a) {
var cleanup = _a.cleanup;
if (typeof cleanup === 'function') {
cleanup();
}
});
}
_context = null;
}
function areDepsEqual(prevDeps, nextDeps) {
if (prevDeps === undefined || nextDeps === undefined) {
return false;
}
if (prevDeps.length !== nextDeps.length) {
return false;
}
// TODO: refactor to `nextDeps.every((dep, i) => Object.is(dep, prevDeps[i]))`
for (var i = 0; i < nextDeps.length; i++) {
if (!Object.is(prevDeps[i], nextDeps[i])) {
return false;
}
}
return true;
}
//# sourceMappingURL=context.js.map