It would be useful to be able to add utility functions for components or entities. For example, suppose we want to create a utility function to duplicate an entity into a grid pattern. We could create a custom function to do this. This custom function could be linked to a particular component type, and could have arguments/parameters that can be configured through the UI. Creating such a custom function could be as simple as:
export class GridDuplicator extends EntityCustomFunction {
public distance: number = 2.0;
public rows: number = 1;
public columns: number = 1;
@Action
public duplicate(entity: Entity) {
const clipboard = new Clipboard(entity.world);
clipboard.copy(entity);
for (let z = 0; z < this.rows; ++z) {
for (let x = 0; x < this.columns; ++x) {
const pastedEntities = clipboard.paste();
pastedEntities[0].translate(new Vec3(x * distance, 0, z * distance));
}
}
}
}
This custom function can then be run through the UI (e.g. by right-clicking on an entity). This would bring up a dialog window, which would allow the user to configure the properties.
This feature was added to v0.25. Some examples are provided below:
@Name("Move To Floor")
@Icon("mdi:format-vertical-align-bottom")
export class MoveToFloorTool extends Tool<Entity> {
override valid(object: Entity): boolean {
return true;
}
override execute(object: Entity): void {
const bbox = object.worldBoundingBox;
const offset = new Vec3(0, bbox.min.y, 0);
object.worldPosition = Vec3.subtract(object.worldPosition, offset);
}
}
@Name("Purge Custom Materials")
@Icon("mdi:hammer-screwdriver")
export class PurgeUnusedMaterials extends Tool<World> {
override valid(object: World): boolean {
return true;
}
override execute(world: World): void {
const library = world.materials.custom;
const materials = new Set<CustomMaterial>(library.materials);
for (const entity of world.descendants) {
const graphics = entity.findComponent(GraphicsComponent);
if (graphics !== null) {
const material = graphics.material;
if (material !== null) {
materials.delete(material);
}
}
}
for (const material of materials) {
console.log("Removed: " + material.name);
library.remove(material.name);
}
}
}
@Name("Component Tool")
@Icon("mdi:hammer-screwdriver")
export class MyComponentTool extends Tool<Component> {
override valid(object: Component): boolean {
return true;
}
override execute(object: Component): void {
throw new Error("Method not implemented.");
}
}