Skip to content

Commit 98c1a7f

Browse files
committed
preview node to modify the background's scene + nodes checks compatibility before connecting + setting up background scene to expose modifiable properties
1 parent 029b7e7 commit 98c1a7f

File tree

9 files changed

+118
-13
lines changed

9 files changed

+118
-13
lines changed

src/Editor.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,8 @@ export class Editor {
282282
this.availableOutlets = outlets.filter( outlet=>{
283283

284284
return (outlet.isInput!=this.selectedOutlet!.isInput )
285-
&& !outlet.connectedTo
285+
//&& !outlet.connectedTo
286+
&& this.selectedOutlet!.isCompatible( outlet )
286287
&& ( outlet.owner !== this.selectedOutlet!.owner )
287288
; // TODO: check for outlet TYPE compatibility
288289
});

src/ThreeScene.ts

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ export class ThreeScene {
66
readonly renderer:THREE.WebGLRenderer;
77
readonly objHolder:THREE.Object3D;
88
private clock:THREE.Clock;
9+
readonly ambientLight:THREE.AmbientLight;
10+
private objs:THREE.Mesh[]=[]
11+
readonly pointLight:THREE.PointLight;
12+
private mouse:THREE.Vector2 = new THREE.Vector2();
13+
rotationSpeed = 1;
914

1015
constructor() {
1116
this.scene = new THREE.Scene();
@@ -18,26 +23,70 @@ export class ThreeScene {
1823
this.objHolder = new THREE.Object3D();
1924
this.clock = new THREE.Clock();
2025

26+
this.ambientLight = new THREE.AmbientLight(0xffffff,0.1);
27+
this.pointLight = new THREE.PointLight(0xffffff,5,15);
28+
29+
window.addEventListener('mousemove', (event) => {
30+
// Normalize mouse coordinates to [-1, 1]
31+
this.mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
32+
this.mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
33+
});
34+
2135
this.buildScene()
2236
}
2337

2438
protected buildScene() {
2539
const geometry = new THREE.BoxGeometry( 1, 1, 1 );
26-
const material = new THREE.MeshBasicMaterial( { color: 0x000000 } );
40+
const material = new THREE.MeshStandardMaterial( { color: 0xcccccc } );
2741
const cube = new THREE.Mesh( geometry, material );
2842

2943
this.objHolder.add(cube);
3044
this.scene.add( this.objHolder )
3145

32-
this.camera.position.z = 5;
46+
this.camera.position.z = 4;
3347
this.camera.position.x = -4;
48+
49+
this.scene.add( this.ambientLight );
50+
this.objs.push( cube );
51+
52+
const dirLight = new THREE.DirectionalLight()
53+
this.scene.add( dirLight );
54+
55+
this.scene.add( this.pointLight );
56+
57+
this.pointLight.intensity = 3
58+
this.pointLight.position.z = 3
59+
}
60+
61+
private updateLightPosition() {
62+
// Create a Vector3 with normalized mouse coordinates
63+
const vector = new THREE.Vector3(this.mouse.x, this.mouse.y, 0.5); // Z = 0.5 in NDC (midway in the frustum)
64+
65+
// Unproject the vector to world space using the camera
66+
vector.unproject(this.camera);
67+
68+
// Calculate the direction from the camera to the unprojected point
69+
const dir = vector.sub(this.camera.position).normalize();
70+
71+
// We want the light to be at a fixed Z in world space (e.g., Z = 2)
72+
const fixedZ = 2;
73+
74+
// Calculate the distance from the camera to the plane at fixedZ
75+
const distance = (fixedZ - this.camera.position.z) / dir.z;
76+
77+
// Calculate the world position at the fixed Z plane
78+
const pos = this.camera.position.clone().add(dir.multiplyScalar(distance));
79+
80+
// Update the light's position
81+
this.pointLight.position.set(pos.x, pos.y, fixedZ);
3482
}
3583

3684
render() {
3785

3886
const delta = this.clock.getDelta()
39-
this.objHolder.rotateY(delta)
40-
this.objHolder.rotateX(delta)
87+
this.updateLightPosition();
88+
this.objHolder.rotateY(delta*this.rotationSpeed)
89+
this.objHolder.rotateX(delta*this.rotationSpeed)
4190
this.renderer.render( this.scene, this.camera );
4291
}
4392
}

src/core/IOutlet.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,6 @@ export interface IOutlet {
1313
get owner():Node
1414
get size():OutletSize; // the output will be vec1 to 4 always... or in case of materials, we can say 5.
1515
get color():FillStyle
16+
17+
isCompatible( other:IOutlet ):boolean
1618
}

src/core/isOutlet.ts

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,19 @@
1-
import { IOutlet } from "./IOutlet";
1+
import { Node } from "../nodes/Node";
2+
import { IOutlet, OutletSize } from "./IOutlet";
23

3-
export function isOutlet( obj:any ): obj is IOutlet {
4-
return (
5-
typeof obj === 'object' &&
6-
obj !== null &&
7-
'isInput' in obj &&
8-
typeof obj.isInput === 'boolean'
9-
);
4+
function isOutletSize(value: unknown): value is OutletSize {
5+
return typeof value === 'number' && [1, 2, 3, 4, 5].includes(value);
6+
}
7+
8+
9+
// Type guard for IOutlet
10+
export function isOutlet(obj: unknown): obj is IOutlet {
11+
return typeof obj === 'object' && obj !== null &&
12+
'isInput' in obj && typeof obj.isInput === 'boolean' &&
13+
'globalX' in obj && typeof obj.globalX === 'number' &&
14+
'globalY' in obj && typeof obj.globalY === 'number' &&
15+
'owner' in obj && obj.owner instanceof Node &&
16+
'size' in obj && isOutletSize(obj.size) &&
17+
'color' in obj
18+
&& 'isCompatible' in obj && typeof obj.isCompatible == 'function'
1019
}

src/main.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11

22
import { Editor } from './Editor';
33
import { UVNode } from './nodes/attribute/UVNode';
4+
import { ScenePreviewNode } from './nodes/preview/ScenePreview';
45
import { MeshStandardNode } from './nodes/shader/MeshStandardNode';
56
import { ImageTextureNode } from './nodes/texture/ImageTextureNode';
67
import './style.css'
@@ -27,6 +28,11 @@ win4.x =500;
2728
win4.y = 200;
2829
editor.add( win4 );
2930

31+
let win5 = new ScenePreviewNode( editor.scene );
32+
win5.x =600;
33+
win5.y = 200;
34+
editor.add( win5 );
35+
3036
editor.start();
3137

3238

src/nodes/Node.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { LayoutElement } from "../layout/LayoutElement";
99
export class Node extends LayoutElement {
1010

1111
editor!:Editor;
12+
canBeDeleted = true;
1213

1314
x = 0
1415
y = 0

src/nodes/preview/ScenePreview.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
2+
import { Theme } from "../../colors/Theme";
3+
import { DraggableValue } from "../../components/DraggableValue";
4+
import { MaterialProperty } from "../../properties/MaterialProperty";
5+
import { WinNode } from "../WinNode";
6+
import { ThreeScene } from "../../ThreeScene";
7+
8+
export class ScenePreviewNode extends WinNode {
9+
constructor( protected scene:ThreeScene ) {
10+
11+
super("Scene Preview", Theme.config.groupOutput, [
12+
new DraggableValue("Ambient light", true, 0, 10, 0.1),
13+
new DraggableValue("Rotation speed", true, 0, 2, 0.1),
14+
new MaterialProperty(".material [ 0 ] ")
15+
]);
16+
17+
this.canBeDeleted = false;
18+
}
19+
}

src/properties/MaterialProperty.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { TextLabel } from "../components/TextLabel";
2+
import { Row } from "../layout/Layout";
3+
import { Input } from "./Input";
4+
5+
export class MaterialProperty extends Input {
6+
constructor( name:string ) {
7+
super(5);
8+
9+
this.layout = new Row([
10+
new TextLabel( name ),
11+
] );
12+
this.xPadding = 10
13+
}
14+
}

src/properties/OutletProperty.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ export class OutletProperty extends LayoutElement implements IOutlet
3434
][ size ]
3535
}
3636

37+
isCompatible(other: IOutlet): boolean {
38+
return this.size == 5 || other.size==5? this.size==other.size : true
39+
}
40+
3741
connectedTo?: IOutlet | undefined;
3842

3943
get owner(): Node {

0 commit comments

Comments
 (0)