stuff
This commit is contained in:
parent
65f84c4d6c
commit
068f7ec2cc
|
@ -83,7 +83,6 @@ const changed = ($event: Event) => {
|
|||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
appearance: none;
|
||||
padding: 4px;
|
||||
cursor: pointer;
|
||||
border: 0;
|
||||
width: 100%;
|
||||
|
@ -99,15 +98,15 @@ const changed = ($event: Event) => {
|
|||
border-radius: 100%;
|
||||
border: 1px solid #ddd;
|
||||
margin-right: 4px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
&-field {
|
||||
font-family: monospace;
|
||||
width: 5rem;
|
||||
width: 100%;
|
||||
border: 0;
|
||||
background-color: #ffffff;
|
||||
padding: 8px;
|
||||
margin: 2px 0;
|
||||
font-size: 0.75rem;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
|
|
@ -61,42 +61,56 @@ const formFields = computed(() => {
|
|||
const fields: FormItem[] = [];
|
||||
|
||||
Object.values(object.editorProperties)
|
||||
.filter((item) => item.exposed)
|
||||
.filter((item) => item.definition.exposed)
|
||||
.forEach((property) => {
|
||||
if (property.type === String || property.type === Number) {
|
||||
if (
|
||||
property.definition.type === String ||
|
||||
property.definition.type === Number
|
||||
) {
|
||||
fields.push({
|
||||
name: property.name,
|
||||
label: toCapitalizedWords(property.name),
|
||||
value: (object as unknown as Record<string, unknown>)[property.name],
|
||||
type: property.type === String ? 'string' : 'number',
|
||||
name: property.definition.name,
|
||||
label: toCapitalizedWords(property.definition.name),
|
||||
value: (object as unknown as Record<string, unknown>)[
|
||||
property.definition.name
|
||||
],
|
||||
type: property.definition.type === String ? 'string' : 'number',
|
||||
component: Field,
|
||||
});
|
||||
}
|
||||
|
||||
if (property.type === Vector3 || property.type === Euler) {
|
||||
if (
|
||||
property.definition.type === Vector3 ||
|
||||
property.definition.type === Euler
|
||||
) {
|
||||
fields.push({
|
||||
name: property.name,
|
||||
label: toCapitalizedWords(property.name),
|
||||
value: (object as unknown as Record<string, unknown>)[property.name],
|
||||
type: property.type === Vector3 ? 'vector' : 'euler',
|
||||
name: property.definition.name,
|
||||
label: toCapitalizedWords(property.definition.name),
|
||||
value: (object as unknown as Record<string, unknown>)[
|
||||
property.definition.name
|
||||
],
|
||||
type: property.definition.type === Vector3 ? 'vector' : 'euler',
|
||||
component: Vector3Field,
|
||||
});
|
||||
}
|
||||
|
||||
if (property.type === Color) {
|
||||
if (property.definition.type === Color) {
|
||||
fields.push({
|
||||
name: property.name,
|
||||
label: toCapitalizedWords(property.name),
|
||||
value: (object as unknown as Record<string, unknown>)[property.name],
|
||||
name: property.definition.name,
|
||||
label: toCapitalizedWords(property.definition.name),
|
||||
value: (object as unknown as Record<string, unknown>)[
|
||||
property.definition.name
|
||||
],
|
||||
component: ColorPicker,
|
||||
});
|
||||
}
|
||||
|
||||
if (property.type === Boolean) {
|
||||
if (property.definition.type === Boolean) {
|
||||
fields.push({
|
||||
name: property.name,
|
||||
label: toCapitalizedWords(property.name),
|
||||
value: (object as unknown as Record<string, unknown>)[property.name],
|
||||
name: property.definition.name,
|
||||
label: toCapitalizedWords(property.definition.name),
|
||||
value: (object as unknown as Record<string, unknown>)[
|
||||
property.definition.name
|
||||
],
|
||||
component: Checkbox,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
// Contains highly modified code from
|
||||
// https://github.com/mrdoob/three.js/blob/master/examples/jsm/controls/FirstPersonControls.js
|
||||
// https://github.com/mrdoob/three.js/blob/master/examples/jsm/controls/OrbitControls.js
|
||||
// MIT Copyright © 2010-2023 three.js authors
|
||||
|
||||
import { Euler, EventDispatcher, Object3D, Vector3 } from 'three';
|
||||
|
||||
const _changeEvent = { type: 'change' };
|
File diff suppressed because it is too large
Load Diff
|
@ -6,6 +6,7 @@ import {
|
|||
Environment,
|
||||
EventEmitter,
|
||||
GameObject,
|
||||
GameObject3D,
|
||||
MouseButtonEvent,
|
||||
Renderer,
|
||||
Sphere,
|
||||
|
@ -30,9 +31,9 @@ import {
|
|||
SelectionEvent,
|
||||
TransformModeEvent,
|
||||
} from '../types/events';
|
||||
import { TransformControls } from 'three/addons/controls/TransformControls.js';
|
||||
import { ViewHelper } from 'three/addons/helpers/ViewHelper.js';
|
||||
import { CameraControls } from './controls';
|
||||
import { CameraControls } from './controls/camera-controls';
|
||||
import { TransformControls } from './controls/transform-controls';
|
||||
|
||||
/**
|
||||
* This component does most of the work related to editing the level.
|
||||
|
@ -145,6 +146,9 @@ export class WorkspaceComponent extends EngineComponent {
|
|||
object = object.parent;
|
||||
}
|
||||
|
||||
// Locked is for preventing mouse picking
|
||||
if ((object as GameObject3D)?.locked) return;
|
||||
|
||||
this.events.emit('select', {
|
||||
object: object as GameObject,
|
||||
multi: event.control,
|
||||
|
|
|
@ -98,37 +98,17 @@ export class LevelComponent extends EngineComponent {
|
|||
await assetManager.loadAll(save.assets);
|
||||
|
||||
// Load environment
|
||||
this.applyProperties(save.environment, this.environment);
|
||||
this.environment.deserialize(save.environment);
|
||||
this.events.emit('setEnvironment', this.environment);
|
||||
|
||||
// Load world
|
||||
this.deserializeObject(save.world);
|
||||
}
|
||||
|
||||
private applyProperties(
|
||||
properties: Record<string, unknown>,
|
||||
object: Object3D
|
||||
) {
|
||||
Object.keys(properties)
|
||||
.filter((key) => !['children', 'objectType'].includes(key))
|
||||
.forEach((key) => {
|
||||
const indexable = object as any;
|
||||
if (indexable[key]?.fromArray && Array.isArray(properties[key])) {
|
||||
indexable[key].fromArray(properties[key]);
|
||||
} else if (indexable[key].isColor) {
|
||||
indexable[key] = new Color(properties[key] as string);
|
||||
} else if (indexable[key].copy) {
|
||||
indexable[key].copy(properties[key]);
|
||||
} else {
|
||||
indexable[key] = properties[key];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private recursiveCreate(entry: SerializedObject, setParent?: Object3D) {
|
||||
const parent = setParent || this.world;
|
||||
const newObject = this.createObject(entry.objectType, parent);
|
||||
this.applyProperties(entry, newObject!);
|
||||
newObject?.deserialize(entry);
|
||||
entry.children.forEach((child) => this.recursiveCreate(child, newObject));
|
||||
return newObject;
|
||||
}
|
||||
|
|
|
@ -17,9 +17,12 @@ import { AssetInfo } from '../types/asset';
|
|||
|
||||
export const brickEditorProperties: EditorProperties = {
|
||||
...gameObject3DEditorProperties,
|
||||
color: new Property('color', Color, true, []),
|
||||
transparency: new Property('transparency', Number, true, []),
|
||||
texture: new Property('texture', AssetInfo, true, []),
|
||||
color: new Property({ name: 'color', type: Color }),
|
||||
transparency: new Property({ name: 'transparency', type: Number }),
|
||||
texture: new Property({ name: 'texture', type: AssetInfo }),
|
||||
canCollide: new Property({ name: 'canCollide', type: Boolean }),
|
||||
anchored: new Property({ name: 'anchored', type: Boolean }),
|
||||
mass: new Property({ name: 'mass', type: Number }),
|
||||
};
|
||||
|
||||
export class Brick extends GameObject3D {
|
||||
|
@ -28,6 +31,10 @@ export class Brick extends GameObject3D {
|
|||
protected material = new MeshPhongMaterial();
|
||||
protected mesh: Mesh = new Mesh(this.geometry, this.material);
|
||||
|
||||
public canCollide = true;
|
||||
public anchored = true;
|
||||
public mass = 1;
|
||||
|
||||
constructor(
|
||||
protected geometry: BufferGeometry = gameObjectGeometries.boxGeometry,
|
||||
public editorProperties: EditorProperties = brickEditorProperties
|
||||
|
|
|
@ -8,12 +8,12 @@ import { Property } from '../types/property';
|
|||
import { environmentDefaults } from '../defaults/environment';
|
||||
|
||||
export const environmentEditorProperties: EditorProperties = {
|
||||
sunColor: new Property('sunColor', Color, true, []),
|
||||
sunPosition: new Property('sunPosition', Vector3, true, []),
|
||||
sunStrength: new Property('sunStrength', Number, true, []),
|
||||
ambientColor: new Property('ambientColor', Color, true, []),
|
||||
ambientStrength: new Property('ambientStrength', Number, true, []),
|
||||
clearColor: new Property('clearColor', Color, true, []),
|
||||
sunColor: new Property({ name: 'sunColor', type: Color }),
|
||||
sunPosition: new Property({ name: 'sunPosition', type: Vector3 }),
|
||||
sunStrength: new Property({ name: 'sunStrength', type: Number }),
|
||||
ambientColor: new Property({ name: 'ambientColor', type: Color }),
|
||||
ambientStrength: new Property({ name: 'ambientStrength', type: Number }),
|
||||
clearColor: new Property({ name: 'clearColor', type: Color }),
|
||||
};
|
||||
|
||||
export class Environment extends GameObject {
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
import { Euler, Object3D, Vector3 } from 'three';
|
||||
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', String, true, []),
|
||||
visible: new Property('visible', Boolean, true, []),
|
||||
name: new Property({ name: 'name', type: String, exposed: true }),
|
||||
visible: new Property({ name: 'visible', type: Boolean, exposed: true }),
|
||||
};
|
||||
|
||||
export const gameObject3DEditorProperties: EditorProperties = {
|
||||
...gameObjectEditorProperties,
|
||||
position: new Property('position', Vector3, true, []),
|
||||
scale: new Property('scale', Vector3, true, []),
|
||||
rotation: new Property('rotation', Euler, true, []),
|
||||
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 {
|
||||
|
@ -68,17 +69,31 @@ export class GameObject extends Object3D {
|
|||
return this;
|
||||
}
|
||||
|
||||
parse(input: SerializedObject) {
|
||||
/**
|
||||
* Deserialize a serialized object into properties on this object.
|
||||
* @param input Serialized information
|
||||
*/
|
||||
deserialize(input: SerializedObject) {
|
||||
Object.keys(input)
|
||||
.filter((key) => key !== 'children')
|
||||
.filter((key) => !['children', 'objectType'].includes(key))
|
||||
.forEach((key) => {
|
||||
(this as Record<string, unknown>)[key] = input[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);
|
||||
}
|
||||
|
|
|
@ -1,11 +1,23 @@
|
|||
import { Material, Object3D } from 'three';
|
||||
|
||||
export class Property {
|
||||
constructor(
|
||||
public name: string,
|
||||
public type: any,
|
||||
public exposed = true,
|
||||
public validators: Function[] = [],
|
||||
public postChange?: (obj: Object3D | Material) => void
|
||||
) {}
|
||||
export interface PropertyDefinition {
|
||||
name: string;
|
||||
type: any;
|
||||
description?: string;
|
||||
exposed?: boolean;
|
||||
validators?: Function[];
|
||||
postChange?(obj: Object3D | Material): void;
|
||||
}
|
||||
|
||||
export class Property {
|
||||
public definition!: PropertyDefinition;
|
||||
constructor(definition: PropertyDefinition) {
|
||||
this.definition = Object.assign(
|
||||
{
|
||||
exposed: true,
|
||||
validators: [],
|
||||
},
|
||||
definition
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue