phaser-jsx
Version:
Use JSX in Phaser.
244 lines • 13.2 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.reconcileTree = reconcileTree;
var phaser_1 = __importDefault(require("phaser"));
var components_1 = require("../components");
var GameObjects = __importStar(require("../components/GameObjects"));
var constants_1 = require("../constants");
var element_1 = require("../element");
var props_1 = require("./props");
var ref_1 = require("./ref");
/**
* Reconciles a new JSX element tree against the existing game object tree.
*
* @param element - The new JSX element to reconcile.
* @param oldNode - The existing game object node (or null if none).
* @param scene - The Phaser scene.
* @param parent - Optional parent container/layer.
* @returns The new game object node tree.
*/
function reconcileTree(element, oldNode, scene, parent) {
var _a, _b, _c;
switch (true) {
case element === undefined:
case element === null:
if (oldNode) {
destroyNode(oldNode);
}
return null;
case Array.isArray(element):
return reconcileArray(element, (_a = oldNode === null || oldNode === void 0 ? void 0 : oldNode.children) !== null && _a !== void 0 ? _a : null, scene, parent);
case (element === null || element === void 0 ? void 0 : element.type) === components_1.Fragment: {
var children = (_b = element.props) === null || _b === void 0 ? void 0 : _b.children;
return reconcileArray(children ? toArray(children) : [], (_c = oldNode === null || oldNode === void 0 ? void 0 : oldNode.children) !== null && _c !== void 0 ? _c : null, scene, parent);
}
case !(0, element_1.isValidElement)(element):
if (oldNode) {
destroyNode(oldNode);
}
return null;
// function component
case typeof (element === null || element === void 0 ? void 0 : element.type) === 'function' && !isGameObject(element.type):
return reconcileTree(element.type(element.props), oldNode, scene, parent);
case isGameObject(element === null || element === void 0 ? void 0 : element.type):
default:
return reconcileGameObject(element, oldNode, scene, parent);
}
}
function reconcileArray(elements, oldChildren, scene, parent) {
var _a, _b;
var node = {
gameObject: null,
props: {},
children: [],
};
var oldLength = (_a = oldChildren === null || oldChildren === void 0 ? void 0 : oldChildren.length) !== null && _a !== void 0 ? _a : 0;
for (var i = 0; i < elements.length; i++) {
var oldChild = (_b = oldChildren === null || oldChildren === void 0 ? void 0 : oldChildren[i]) !== null && _b !== void 0 ? _b : null;
var newChild = reconcileTree(elements[i], oldChild, scene, parent);
node.children.push(newChild);
if (oldChild && !newChild) {
destroyNode(oldChild);
}
}
// Destroy any extra old children beyond new length
for (var i = elements.length; i < oldLength; i++) {
var oldChild = oldChildren[i];
if (oldChild) {
destroyNode(oldChild);
}
}
return node;
}
function reconcileGameObject(element, oldNode, scene, parent) {
var _a, _b, _c;
var _d = element.props, children = _d.children, ref = _d.ref, props = __rest(_d, ["children", "ref"]);
var gameObject;
if (oldNode) {
// Reuse existing game object - just patch changed props
gameObject = oldNode.gameObject;
patchProps(gameObject, oldNode.props, props, scene);
(0, ref_1.attachRef)(gameObject, ref);
}
else {
// Create new game object
var newGameObject = createGameObject(element, scene);
// Add to scene
if (typeof (parent === null || parent === void 0 ? void 0 : parent.add) === 'function') {
parent.add(newGameObject);
}
else {
scene.add.existing(newGameObject);
}
(0, props_1.setProps)(newGameObject, props, scene);
(0, ref_1.attachRef)(newGameObject, ref);
gameObject = newGameObject;
}
// Reconcile children for Container/Layer
var node = {
gameObject: gameObject,
props: props,
children: [],
};
if (element.type === phaser_1.default.GameObjects.Container ||
element.type === phaser_1.default.GameObjects.Layer) {
var childArray = children ? toArray(children) : [];
var oldChildren = (_a = oldNode === null || oldNode === void 0 ? void 0 : oldNode.children) !== null && _a !== void 0 ? _a : null;
var oldLength = (_b = oldChildren === null || oldChildren === void 0 ? void 0 : oldChildren.length) !== null && _b !== void 0 ? _b : 0;
for (var i = 0; i < childArray.length; i++) {
var oldChild = (_c = oldChildren === null || oldChildren === void 0 ? void 0 : oldChildren[i]) !== null && _c !== void 0 ? _c : null;
var newChild = reconcileTree(childArray[i], oldChild, scene, gameObject);
node.children.push(newChild);
if (oldChild && !newChild) {
destroyNode(oldChild);
}
}
// Destroy extra old children beyond new length
for (var i = childArray.length; i < oldLength; i++) {
var oldChild = oldChildren[i];
if (oldChild) {
destroyNode(oldChild);
}
}
}
return node;
}
function createGameObject(element, scene) {
var _a = element.props, props = _a.props, color = _a.color, frame = _a.frame, points = _a.points, shader = _a.shader, style = _a.style, texture = _a.texture;
switch (true) {
case element.type === phaser_1.default.GameObjects.BitmapText:
case element.type === phaser_1.default.GameObjects.DynamicBitmapText:
return new element.type(scene, props === null || props === void 0 ? void 0 : props.x, props === null || props === void 0 ? void 0 : props.y, props === null || props === void 0 ? void 0 : props.font);
case element.type === phaser_1.default.GameObjects.Bob:
return new element.type(scene, props === null || props === void 0 ? void 0 : props.x, props === null || props === void 0 ? void 0 : props.y, frame, props === null || props === void 0 ? void 0 : props.visible);
case element.type === phaser_1.default.GameObjects.Container:
case element.type === phaser_1.default.GameObjects.Layer:
return new element.type(scene);
case element.type === phaser_1.default.GameObjects.GameObject:
return new element.type(scene, props === null || props === void 0 ? void 0 : props.type);
case element.type === phaser_1.default.GameObjects.Image:
case element.type === phaser_1.default.GameObjects.Sprite:
case element.type === phaser_1.default.GameObjects.NineSlice:
return new element.type(scene, props === null || props === void 0 ? void 0 : props.x, props === null || props === void 0 ? void 0 : props.y, texture, frame);
case element.type === phaser_1.default.GameObjects.Light:
return new element.type(scene, props === null || props === void 0 ? void 0 : props.x, props === null || props === void 0 ? void 0 : props.y, props === null || props === void 0 ? void 0 : props.radius, color === null || color === void 0 ? void 0 : color.r, color === null || color === void 0 ? void 0 : color.g, color === null || color === void 0 ? void 0 : color.b, props === null || props === void 0 ? void 0 : props.intensity);
case element.type === phaser_1.default.GameObjects.PathFollower:
return new element.type(scene, props === null || props === void 0 ? void 0 : props.path, props === null || props === void 0 ? void 0 : props.x, props === null || props === void 0 ? void 0 : props.y, texture, frame);
case element.type === phaser_1.default.GameObjects.Plane:
return new element.type(scene, props === null || props === void 0 ? void 0 : props.x, props === null || props === void 0 ? void 0 : props.y, texture, frame, props === null || props === void 0 ? void 0 : props.width, props === null || props === void 0 ? void 0 : props.height, props === null || props === void 0 ? void 0 : props.isTiled);
case element.type === phaser_1.default.GameObjects.PointLight:
return new element.type(scene, props === null || props === void 0 ? void 0 : props.x, props === null || props === void 0 ? void 0 : props.y, color);
case element.type === phaser_1.default.GameObjects.Rectangle:
case element.type === phaser_1.default.GameObjects.Zone:
return new element.type(scene, props === null || props === void 0 ? void 0 : props.x, props === null || props === void 0 ? void 0 : props.y);
case element.type === phaser_1.default.GameObjects.Rope:
return new element.type(scene, props === null || props === void 0 ? void 0 : props.x, props === null || props === void 0 ? void 0 : props.y, texture, frame, points);
case element.type === phaser_1.default.GameObjects.Shader:
return new element.type(scene, shader);
case element.type === phaser_1.default.GameObjects.Text:
return new element.type(scene, props === null || props === void 0 ? void 0 : props.x, props === null || props === void 0 ? void 0 : props.y, props === null || props === void 0 ? void 0 : props.text, style);
case element.type === phaser_1.default.GameObjects.TileSprite:
return new element.type(scene, props === null || props === void 0 ? void 0 : props.x, props === null || props === void 0 ? void 0 : props.y, props === null || props === void 0 ? void 0 : props.width, props === null || props === void 0 ? void 0 : props.height, texture, frame);
case element.type === phaser_1.default.GameObjects.Video:
return new element.type(scene, props === null || props === void 0 ? void 0 : props.x, props === null || props === void 0 ? void 0 : props.y, props === null || props === void 0 ? void 0 : props.cacheKey);
default:
return new element.type(scene);
}
}
function patchProps(gameObject, oldProps, newProps, scene) {
// Remove old event listeners
for (var key in oldProps) {
if (constants_1.events[key] && typeof oldProps[key] === 'function') {
var eventName = key.slice(2).toLowerCase();
gameObject.off(eventName);
}
}
(0, props_1.setProps)(gameObject, newProps, scene);
}
function destroyNode(node) {
var _a;
if ((_a = node.gameObject) === null || _a === void 0 ? void 0 : _a.active) {
node.gameObject.destroy();
}
for (var _i = 0, _b = node.children; _i < _b.length; _i++) {
var child = _b[_i];
if (child) {
destroyNode(child);
}
}
}
var gameObjects = Object.keys(GameObjects).map(function (key) { return GameObjects[key]; });
function isGameObject(type) {
return gameObjects.some(function (gameObject) { return gameObject === type; });
}
function toArray(item) {
return Array.isArray(item) ? item : [item];
}
//# sourceMappingURL=reconcile.js.map