smolworld / src /js /layer.js
p3nGu1nZz's picture
✨ Refactor physics module; add math utilities and event handling classes; update state structure for 3D entities
7ffaa9e
export const LayerType = {
GAME: 'game',
GUI: 'gui', // Add GUI layer type
DEBUG: 'debug',
TERMINAL: 'terminal'
};
export class Layer {
constructor(type, parent = null) {
this.type = type;
this.parent = null;
this.child = null; // Only one child allowed
this.entities = [];
this.visible = true;
this.inputEnabled = true;
this.zIndex = 0;
if (parent) {
this.setParent(parent);
}
}
setParent(parent) {
if (parent.child) {
console.warn('Parent already has a child, removing existing child');
parent.child.parent = null;
}
this.parent = parent;
parent.child = this;
this.zIndex = parent.zIndex + 1;
}
removeParent() {
if (this.parent) {
this.parent.child = null;
this.parent = null;
}
}
getRoot() {
return this.parent ? this.parent.getRoot() : this;
}
addEntity(entity) {
if (this.type === 'root') {
console.warn('Cannot add entities to root layer');
return;
}
this.entities.push(entity);
}
draw(ctx, camera) {
if (!this.visible) return;
// Draw this layer's entities
this.entities.forEach(entity => {
if (typeof entity.draw === 'function') {
entity.draw(ctx, camera);
}
});
// Draw child layer if it exists
if (this.child) {
this.child.draw(ctx, camera);
}
}
enableInput() {
this.inputEnabled = true;
// Don't propagate enable up the chain
// Each layer's input state is managed independently
}
disableInput() {
this.inputEnabled = false;
// Don't propagate disable up the chain
// Each layer's input state is managed independently
}
clear() {
this.entities = [];
}
toggle() {
this.visible = !this.visible;
}
// Base input handling methods
handleKeyDown(event) { }
handleMouseMove(x, y) { }
handleClick(x, y) { }
handleWheel(event) { }
}
export class GameLayer extends Layer {
constructor(parent = null) {
super(LayerType.GAME, parent);
}
handleKeyDown(event) {
if (!this.inputEnabled) return;
this.entities.forEach(entity => {
if (entity.handleGameInput) entity.handleGameInput(event);
});
}
}
export class GUILayer extends Layer {
constructor(parent = null) {
super(LayerType.GUI, parent);
}
handleClick(x, y) {
if (!this.inputEnabled) return;
this.entities.forEach(entity => {
if (entity.handleClick) entity.handleClick(x, y);
});
}
handleMouseMove(x, y) {
if (!this.inputEnabled) return;
this.entities.forEach(entity => {
if (entity.handleMouseMove) entity.handleMouseMove(x, y);
});
}
}
export class DebugLayer extends Layer {
constructor(parent = null) {
super(LayerType.DEBUG, parent);
}
handleMouseMove(x, y) {
if (!this.inputEnabled) return;
this.entities.forEach(entity => {
if (entity.handleMouseMove) entity.handleMouseMove(x, y);
});
}
handleClick(x, y) {
if (!this.inputEnabled) return;
this.entities.forEach(entity => {
if (entity.handleClick) entity.handleClick(x, y);
});
}
handleWheel(event) {
if (!this.inputEnabled) return;
this.entities.forEach(entity => {
if (entity.handleWheel) entity.handleWheel(event);
});
}
}
export class TerminalLayer extends Layer {
constructor(parent = null) {
super(LayerType.TERMINAL, parent);
}
handleKeyDown(event) {
if (!this.inputEnabled) return;
this.entities.forEach(entity => {
if (entity.handleKeyInput) entity.handleKeyInput(event.key);
});
}
}