freeblox/packages/engine/src/types/game-object.ts

109 lines
3.1 KiB
TypeScript

import { Color, Euler, Object3D, Vector3 } from 'three';
import { Property } from './property';
export type EditorProperties = { [x: string]: Property };
export const gameObjectEditorProperties: EditorProperties = {
name: new Property({ name: 'name', type: String, exposed: true }),
visible: new Property({ name: 'visible', type: Boolean, exposed: true }),
};
export const gameObject3DEditorProperties: EditorProperties = {
...gameObjectEditorProperties,
locked: new Property({ name: 'locked', type: Boolean, exposed: true }),
position: new Property({ name: 'position', type: Vector3, exposed: true }),
scale: new Property({ name: 'scale', type: Vector3, exposed: true }),
rotation: new Property({ name: 'rotation', type: Euler, exposed: true }),
};
export class GameObject extends Object3D {
public objectType = 'GameObject';
public virtual = false;
constructor(
public editorProperties: EditorProperties = gameObjectEditorProperties
) {
super();
this.name = this.objectType;
}
/**
* Serialize GameObject for exporting
*/
serialize() {
const object: SerializedObject = {
name: this.name,
objectType: this.objectType,
children: this.children
.filter((entry) => entry instanceof GameObject)
.map((entry) => (entry as GameObject).serialize()),
visible: this.visible,
};
const keys = Object.keys(this.editorProperties);
Object.assign(
object,
keys.reduce<{ [x: string]: unknown }>((obj, key) => {
const indexable = this as Record<string, unknown>;
const value = (indexable[key] as any)?.toArray
? (indexable[key] as any).toArray()
: indexable[key];
return {
...obj,
[key]: value,
};
}, {})
);
return object;
}
override copy(object: Object3D, recursive = true) {
super.copy(object as any, recursive);
Object.keys(this.editorProperties)
.filter((key) => !['position', 'rotation', 'scale'].includes(key))
.forEach((key) => {
(this as any)[key] = (object as any)[key];
});
return this;
}
/**
* Deserialize a serialized object into properties on this object.
* @param input Serialized information
*/
deserialize(input: SerializedObject) {
Object.keys(input)
.filter((key) => !['children', 'objectType'].includes(key))
.forEach((key) => {
const indexable = this as any;
if (indexable[key]?.fromArray && Array.isArray(input[key])) {
indexable[key].fromArray(input[key]);
} else if (indexable[key].isColor) {
indexable[key] = new Color(input[key] as string);
} else if (indexable[key].copy) {
indexable[key].copy(input[key]);
} else {
indexable[key] = input[key];
}
});
}
}
export class GameObject3D extends GameObject {
public objectType = 'GameObject3D';
public locked = false;
constructor(public editorProperties = gameObject3DEditorProperties) {
super(editorProperties);
}
}
export interface SerializedObject {
[x: string]: unknown;
name: string;
objectType: string;
children: SerializedObject[];
visible: boolean;
}