scene.ts
import type { Engine } from "@babylonjs/core/Engines/engine";
import { ArcRotateCamera } from "@babylonjs/core/Cameras/arcRotateCamera";
import { PointLight } from "@babylonjs/core/Lights/pointLight";
import { StandardMaterial } from "@babylonjs/core/Materials/standardMaterial";
import { Color3 } from "@babylonjs/core/Maths/math.color";
import { Vector3 } from "@babylonjs/core/Maths/math.vector";
import { CreateGround } from "@babylonjs/core/Meshes/Builders/groundBuilder";
import { CreateBox } from "@babylonjs/core/Meshes/Builders/boxBuilder";
import { CreateSphere } from "@babylonjs/core/Meshes/Builders/sphereBuilder";
import { CreateTorus } from "@babylonjs/core/Meshes/Builders/torusBuilder";
import { ActionManager } from "@babylonjs/core/Actions/actionManager";
import { InterpolateValueAction } from "@babylonjs/core/Actions/interpolateValueAction";
import {
CombineAction,
DoNothingAction,
ExecuteCodeAction,
IncrementValueAction,
SetStateAction,
SetValueAction,
} from "@babylonjs/core/Actions/directActions";
import { StateCondition } from "@babylonjs/core/Actions/condition";
import { Scene } from "@babylonjs/core/scene";
import type { AbstractMesh } from "@babylonjs/core/Meshes/abstractMesh";
import type { Light } from "@babylonjs/core/Lights/light";
export function createActionsScene(engine: Engine, canvas: HTMLCanvasElement): Scene {
const scene = new Scene(engine);
const camera = new ArcRotateCamera("Camera", 0, 0, 10, new Vector3(0, 0, 0), scene);
camera.setPosition(new Vector3(20, 200, 400));
camera.attachControl(canvas, true);
camera.lowerBetaLimit = 0.1;
camera.upperBetaLimit = (Math.PI / 2) * 0.99;
camera.lowerRadiusLimit = 150;
scene.clearColor = new Color3(0, 0, 0).toColor4(1);
const light1 = new PointLight("omni", new Vector3(0, 50, 0), scene);
const light2 = new PointLight("omni", new Vector3(0, 50, 0), scene);
const light3 = new PointLight("omni", new Vector3(0, 50, 0), scene);
light1.diffuse = Color3.Red();
light2.diffuse = Color3.Green();
light3.diffuse = Color3.Blue();
light1.state = "on";
light2.state = "on";
light3.state = "on";
const ground = CreateGround("ground", { width: 1000, height: 1000, subdivisions: 1 }, scene);
const groundMaterial = new StandardMaterial("ground", scene);
groundMaterial.specularColor = Color3.Black();
ground.material = groundMaterial;
const redBox = CreateBox("red", { size: 20 }, scene);
const redMat = new StandardMaterial("ground", scene);
redMat.diffuseColor = new Color3(0.4, 0.4, 0.4);
redMat.specularColor = new Color3(0.4, 0.4, 0.4);
redMat.emissiveColor = Color3.Red();
redBox.material = redMat;
redBox.position.x -= 100;
const greenBox = CreateBox("green", { size: 20 }, scene);
const greenMat = new StandardMaterial("ground", scene);
greenMat.diffuseColor = new Color3(0.4, 0.4, 0.4);
greenMat.specularColor = new Color3(0.4, 0.4, 0.4);
greenMat.emissiveColor = Color3.Green();
greenBox.material = greenMat;
greenBox.position.z -= 100;
const blueBox = CreateBox("blue", { size: 20 }, scene);
const blueMat = new StandardMaterial("ground", scene);
blueMat.diffuseColor = new Color3(0.4, 0.4, 0.4);
blueMat.specularColor = new Color3(0.4, 0.4, 0.4);
blueMat.emissiveColor = Color3.Blue();
blueBox.material = blueMat;
blueBox.position.x += 100;
const sphere = CreateSphere("sphere", { segments: 16, diameter: 20 }, scene);
const sphereMat = new StandardMaterial("ground", scene);
sphereMat.diffuseColor = new Color3(0.4, 0.4, 0.4);
sphereMat.specularColor = new Color3(0.4, 0.4, 0.4);
sphereMat.emissiveColor = Color3.Purple();
sphere.material = sphereMat;
sphere.position.z += 100;
const donut = CreateTorus("donut", { diameter: 20, thickness: 8, tessellation: 16 }, scene);
const prepareButton = (mesh: AbstractMesh, color: Color3, light: Light) => {
const goToColorAction = new InterpolateValueAction(
ActionManager.OnPickTrigger,
light,
"diffuse",
color,
1000,
undefined,
true
);
mesh.actionManager = new ActionManager(scene);
mesh.actionManager
.registerAction(
new InterpolateValueAction(ActionManager.OnPickTrigger, light, "diffuse", Color3.Black(), 1000)
)!
.then(
new CombineAction(ActionManager.NothingTrigger, [
goToColorAction,
new SetValueAction(ActionManager.NothingTrigger, mesh.material, "wireframe", false),
])
);
mesh.actionManager
.registerAction(new SetValueAction(ActionManager.OnPickTrigger, mesh.material, "wireframe", true))!
.then(new DoNothingAction());
mesh.actionManager
.registerAction(new SetStateAction(ActionManager.OnPickTrigger, light, "off"))!
.then(new SetStateAction(ActionManager.OnPickTrigger, light, "on"));
};
prepareButton(redBox, Color3.Red(), light1);
prepareButton(greenBox, Color3.Green(), light2);
prepareButton(blueBox, Color3.Blue(), light3);
sphere.actionManager = new ActionManager(scene);
const sphereActionManager = sphere.actionManager as ActionManager;
const condition1 = new StateCondition(sphereActionManager, light1, "off");
const condition2 = new StateCondition(sphereActionManager, light1, "on");
sphere.actionManager.registerAction(
new InterpolateValueAction(ActionManager.OnLeftPickTrigger, camera, "alpha", 0, 500, condition1)
);
sphere.actionManager.registerAction(
new InterpolateValueAction(ActionManager.OnLeftPickTrigger, camera, "alpha", Math.PI, 500, condition2)
);
const makeOverOut = (mesh: AbstractMesh) => {
mesh.actionManager!.registerAction(
new SetValueAction(
ActionManager.OnPointerOutTrigger,
mesh.material,
"emissiveColor",
(mesh.material as StandardMaterial).emissiveColor
)
);
mesh.actionManager!.registerAction(
new SetValueAction(ActionManager.OnPointerOverTrigger, mesh.material, "emissiveColor", Color3.White())
);
mesh.actionManager!.registerAction(
new InterpolateValueAction(ActionManager.OnPointerOutTrigger, mesh, "scaling", new Vector3(1, 1, 1), 150)
);
mesh.actionManager!.registerAction(
new InterpolateValueAction(
ActionManager.OnPointerOverTrigger,
mesh,
"scaling",
new Vector3(1.1, 1.1, 1.1),
150
)
);
};
makeOverOut(redBox);
makeOverOut(greenBox);
makeOverOut(blueBox);
makeOverOut(sphere);
scene.actionManager = new ActionManager(scene);
const rotate = (mesh: AbstractMesh) => {
scene.actionManager!.registerAction(
new IncrementValueAction(ActionManager.OnEveryFrameTrigger, mesh, "rotation.y", 0.01)
);
};
rotate(redBox);
rotate(greenBox);
rotate(blueBox);
donut.actionManager = new ActionManager(scene);
donut.actionManager.registerAction(
new SetValueAction(
{ trigger: ActionManager.OnIntersectionEnterTrigger, parameter: sphere },
donut,
"scaling",
new Vector3(1.2, 1.2, 1.2)
)
);
donut.actionManager.registerAction(
new SetValueAction(
{ trigger: ActionManager.OnIntersectionExitTrigger, parameter: sphere },
donut,
"scaling",
new Vector3(1, 1, 1)
)
);
scene.actionManager.registerAction(
new ExecuteCodeAction({ trigger: ActionManager.OnKeyUpTrigger, parameter: "r" }, () => {
camera.setPosition(new Vector3(20, 200, 400));
})
);
let alpha = 0;
scene.registerBeforeRender(() => {
donut.position.x = 100 * Math.cos(alpha);
donut.position.y = 5;
donut.position.z = 100 * Math.sin(alpha);
alpha += 0.01;
});
return scene;
}