Skip to content

Commit fadc758

Browse files
committed
draggable value can be setted by clicking on it + bugfix on scroll on it + Math node with some basic operations
1 parent 29c705a commit fadc758

File tree

11 files changed

+205
-17
lines changed

11 files changed

+205
-17
lines changed

src/EditorNodes.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { FillStyle, Theme } from "./colors/Theme";
22
import { UVNode } from "./nodes/attribute/UVNode";
3+
import { MathNode } from "./nodes/operators/MathNode";
34
import { MeshStandardNode } from "./nodes/shader/MeshStandardNode";
45
import { ImageTextureNode } from "./nodes/texture/ImageTextureNode";
56
import { WinNode } from "./nodes/WinNode";
@@ -22,6 +23,13 @@ export const NodeTypes : NodeGroupType[] = [
2223
{ TypeClass:UVNode, name:"UV", id:"uv" }
2324
]
2425
},
26+
{
27+
group:"Math",
28+
color:Theme.config.groupMath as string,
29+
nodes:[
30+
{ TypeClass:MathNode, name:"Operation", id:"math-operation"}
31+
]
32+
},
2533
{
2634
group:"Shader",
2735
color:Theme.config.groupShader as string,

src/colors/Theme.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,7 @@ export class Theme {
5151
readonly comboboxOptionsBgColor : FillStyle = "#181818"
5252
readonly comboSelectedItemBgColor : FillStyle = "#4772b3"
5353
readonly comboSelectedItemTextColor : FillStyle = "white"
54+
55+
readonly inputTextBg :FillStyle = "#545454";
56+
readonly inputTextColor :FillStyle = "white";
5457
}

src/components/DraggableValue.ts

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export class DraggableValue extends InteractiveLayoutElement {
88
protected _percent = 0;
99
private dragOriginX = 0;
1010
private size = 0;
11+
private promptValueOnMouseUp = false;
1112

1213
constructor( readonly name:string, readonly usesBar:boolean, readonly min:number, readonly max:number, protected step:number, protected onChange?:( value:number, percent:number )=>void )
1314
{
@@ -20,7 +21,7 @@ export class DraggableValue extends InteractiveLayoutElement {
2021
let v = this.value;
2122

2223

23-
return Math.round(this.step)==this.step? v.toString() : v.toFixed(2) ;
24+
return Math.round(v)==v? v.toString() : v.toFixed(2) ;
2425
}
2526

2627
/**
@@ -72,17 +73,36 @@ export class DraggableValue extends InteractiveLayoutElement {
7273
override onMouseMove(deltaX: number, deltaY: number): void {
7374
this.dragOriginX += deltaX;
7475

75-
this.value = this.min + (this.dragOriginX / this.hitArea.w) * this.size ;
76-
76+
if( this.usesBar )
77+
{
78+
this.value = this.min + (this.dragOriginX / this.hitArea.w) * this.size ;
79+
}
80+
else
81+
{
82+
this.value += this.step * deltaX>0? 1 : -1
83+
}
7784

85+
this.promptValueOnMouseUp = false;
7886
}
79-
override onMouseDown(cursorX: number, cursorY: number): void {
80-
//this.isDragging = true;
87+
88+
override onMouseDown(cursorX: number, cursorY: number): void {
8189
this.dragOriginX = cursorX;
90+
this.promptValueOnMouseUp = true;
8291
}
83-
// override onMouseUp(): void {
84-
// this.isDragging = false;
85-
// }
92+
93+
override onMouseUp(): void {
94+
if( this.promptValueOnMouseUp )
95+
{
96+
97+
const val = prompt("Enter the new value...", this._value.toString() );
98+
if( val && !isNaN( Number(val) ) )
99+
{
100+
this.value = Number(val) ;
101+
}
102+
103+
}
104+
}
105+
86106
override onMouseWheel(deltaY: number): void {
87107

88108
const inc = this.step;

src/components/Header.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,10 @@ import { FillStyle, Theme } from "../colors/Theme";
22
import { LayoutElement } from "../layout/LayoutElement";
33

44
export class HeaderElement extends LayoutElement {
5-
constructor( protected title:string, protected bgColor:FillStyle )
5+
constructor( public title:string, protected bgColor:FillStyle )
66
{
77
super();
88
}
9-
109

1110
override renderContents(ctx: CanvasRenderingContext2D, maxWidth: number, maxHeight: number): void {
1211

src/core/IOutlet.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { IScript } from "../export/IScript";
33
import { Script } from "../export/Script";
44
import { Node } from "../nodes/Node"
55

6-
export type OutletSize = 1|2|3|4|5;
6+
export type OutletSize = 0|1|2|3|4|5; //<---- 0=any type except type 5...
77

88
export interface IOutlet extends IScript {
99
isInput:boolean

src/core/isOutlet.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { Node } from "../nodes/Node";
22
import { IOutlet, OutletSize } from "./IOutlet";
33

44
function isOutletSize(value: unknown): value is OutletSize {
5-
return typeof value === 'number' && [1, 2, 3, 4, 5].includes(value);
5+
return typeof value === 'number' && [0, 1, 2, 3, 4, 5].includes(value);
66
}
77

88

src/nodes/WinNode.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,15 @@ const nameCount :Record<string, number> = {};
1212

1313
export class WinNode extends Node {
1414
private _nodeName:string;
15+
protected header:HeaderElement;
1516

1617
constructor(protected title:string, groupColor:FillStyle, protected childs:LayoutElement[] )
1718
{
19+
const header = new HeaderElement(title, groupColor);
20+
1821
super(new Layout( [
1922

20-
new HeaderElement(title, groupColor),
21-
23+
header,
2224
new Layout( childs, {
2325
direction:"column",
2426
gap: 5,
@@ -43,11 +45,17 @@ export class WinNode extends Node {
4345
}
4446

4547
this._nodeName = name;
48+
this.header = header;
4649
//#endregion
4750
}
4851

49-
protected getChildOfType<T>(constructor: new (...args: any[]) => T): T | undefined {
50-
return this.childs.find((child) => child instanceof constructor) as T | undefined;
52+
protected setTitle( newTitle:string ){
53+
this.header.title = newTitle;
54+
}
55+
56+
protected getChildOfType<T>( constructor: new (...args: any[]) => T, pos=0 ): T | undefined {
57+
const matches = this.childs.filter((child) => child instanceof constructor);
58+
return matches[pos] as T | undefined;
5159
}
5260

5361
override get nodeName(): string {

src/nodes/operators/MathNode.ts

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
2+
import { Theme } from "../../colors/Theme";
3+
import { ComboBox } from "../../components/ComboBox";
4+
import { Script } from "../../export/Script";
5+
import { InputOrValue } from "../../properties/InputOrValue";
6+
import { Output } from "../../properties/Output";
7+
import { WinNode } from "../WinNode";
8+
9+
type Operator = [ symbol:string, tslMethod:string ];
10+
11+
export class MathNode extends WinNode {
12+
protected operators: Operator[];
13+
protected A:InputOrValue;
14+
protected B:InputOrValue;
15+
protected combo:ComboBox;
16+
17+
constructor() {
18+
19+
const operators : Operator[] = [
20+
["+","add"],
21+
["-","sub"],
22+
["*","mul"],
23+
["/","div"],
24+
["%","mod"],
25+
["==","equal"],
26+
["!=","notEqual"]
27+
// TODO: Add more....
28+
]
29+
30+
super("Math Operator", Theme.config.groupMath, [
31+
new Output("Result", 0),
32+
new InputOrValue(0, "A", ()=>this.update()),
33+
new ComboBox("Operator", operators.map(o=>o[0]), i=>this.onComboChange(i)),
34+
new InputOrValue(0, "B", ()=>this.update()),
35+
]);
36+
37+
this.A = this.getChildOfType(InputOrValue,0)!;
38+
this.B = this.getChildOfType(InputOrValue,1)!;
39+
this.combo = this.getChildOfType(ComboBox)!;
40+
41+
this.operators = operators;
42+
43+
this.onComboChange(0)
44+
}
45+
46+
protected onComboChange( newIndex:number )
47+
{
48+
const op = this.operators[newIndex];
49+
50+
this.setTitle( `.${op[1]} A ${op[0]} B` );
51+
52+
this.update();
53+
}
54+
55+
override writeScript(script: Script): string {
56+
57+
const a = this.A.writeScript(script);
58+
const b = this.B.writeScript(script);
59+
60+
const op = this.operators[this.combo.index][1];
61+
62+
console.log( `${a}.${op}(${b})`)
63+
64+
return script.define( this.nodeName, `${a}.${op}(${b})`);
65+
}
66+
67+
override serialize(): Record<string, any> {
68+
return {
69+
...super.serialize(),
70+
a: this.A.value,
71+
b: this.B.value,
72+
op: this.combo.index
73+
}
74+
}
75+
76+
override unserialize(data: Record<string, any>): void {
77+
super.unserialize(data);
78+
79+
this.A.value = data.a ?? 0;
80+
this.B.value = data.b ?? 0;
81+
this.combo.index = data.op ?? 0;
82+
}
83+
}

src/properties/BasicInputProperty.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export class BasicInputProperty extends Input {
1717
}
1818

1919
override renderContents(ctx: CanvasRenderingContext2D, maxWidth: number, maxHeight: number): void {
20+
if( this.layout ) return super.renderContents( ctx, maxWidth, maxHeight);
2021
this.writeText(ctx, this.label, this.fontSize, 0, maxHeight, this.fontColor);
2122
}
2223

src/properties/InputOrValue.ts

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import { DraggableValue } from "../components/DraggableValue";
2+
import { IOutlet, OutletSize } from "../core/IOutlet";
3+
import { Script } from "../export/Script";
4+
import { Layout, Row } from "../layout/Layout";
5+
import { BasicInputProperty } from "./BasicInputProperty";
6+
import { Input } from "./Input";
7+
8+
export class InputOrValue extends BasicInputProperty
9+
{
10+
protected notConnectedContent:Layout;
11+
protected valueSlider:DraggableValue;
12+
13+
constructor( size:OutletSize, label:string, protected onChange?:(v?:number)=>void ) {
14+
super( size, label );
15+
16+
this.valueSlider = new DraggableValue( label, false, Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER, 0.1, value => this.onChange?.(value) );
17+
18+
this.notConnectedContent = new Row([
19+
this.valueSlider
20+
]);
21+
22+
//this.notConnectedContent.parent = this;
23+
this.layout = this.notConnectedContent;
24+
25+
}
26+
27+
get value() {
28+
return this.valueSlider.value;
29+
}
30+
31+
set value( newValue:number ) {
32+
const changed = this.valueSlider.value!=newValue;
33+
34+
if( changed )
35+
{
36+
this.valueSlider.value = newValue;
37+
this.onChange?.(newValue);
38+
}
39+
40+
}
41+
42+
override width(ctx: CanvasRenderingContext2D): number {
43+
if( this.connectedTo ) return super.width(ctx);
44+
return this.notConnectedContent.width(ctx)
45+
}
46+
47+
protected override onConnected(to: IOutlet): void {
48+
this.layout = undefined;
49+
this.onChange?.();
50+
}
51+
52+
protected override onDisconnected(from: IOutlet): void {
53+
this.layout = this.notConnectedContent;
54+
this.onChange?.( this.valueSlider.value );
55+
}
56+
57+
override writeScript(script: Script): string {
58+
if( this.connectedTo )
59+
{
60+
return this.connectedTo.writeScript( script );
61+
}
62+
63+
script.importModule("float");
64+
return `float(${ this.valueSlider.stringValue })`
65+
}
66+
}

0 commit comments

Comments
 (0)