Browse Source

Associated with #6012

David Catuhe 6 years ago
parent
commit
cb84e388c9

+ 3 - 0
nodeEditor/src/components/diagram/defaultNodeModel.ts

@@ -77,6 +77,9 @@ export class DefaultNodeModel extends NodeModel {
                 } else if (connection.type & NodeMaterialBlockConnectionPointTypes.Vector3OrColor3OrVector4OrColor4) {
                     type = "Vector4"
                 }
+                else if (connection.type & NodeMaterialBlockConnectionPointTypes.Float) {
+                    type = "Float"
+                }
 
                 // Create links
                 var localNode = graphEditor.addValueNode(type, options.column + 1, connection);

+ 8 - 0
nodeEditor/src/components/diagram/input/inputNodePropertyComponent.tsx

@@ -11,6 +11,7 @@ import { NodeMaterialWellKnownValues } from 'babylonjs/Materials/Node/nodeMateri
 import { Vector2, Vector3, Matrix } from 'babylonjs/Maths/math';
 import { TextLineComponent } from '../../../sharedComponents/textLineComponent';
 import { Color3PropertyTabComponent } from '../../propertyTab/properties/color3PropertyTabComponent';
+import { FloatPropertyTabComponent } from '../../propertyTab/properties/floatPropertyTabComponent';
 
 interface IInputPropertyTabComponentProps {
     globalState: GlobalState;
@@ -26,6 +27,10 @@ export class InputPropertyTabComponentProps extends React.Component<IInputProper
     renderValue(globalState: GlobalState) {
         let connection = this.props.inputNode.connection!;
         switch (connection.type) {
+            case NodeMaterialBlockConnectionPointTypes.Float:
+                return (
+                    <FloatPropertyTabComponent globalState={globalState} connection={connection} />
+                );
             case NodeMaterialBlockConnectionPointTypes.Vector2:
                 return (
                     <Vector2PropertyTabComponent globalState={globalState} connection={connection} />
@@ -48,6 +53,9 @@ export class InputPropertyTabComponentProps extends React.Component<IInputProper
     setDefaultValue() {
         let connection = this.props.inputNode.connection!;
         switch (connection.type) {
+            case NodeMaterialBlockConnectionPointTypes.Float:
+                connection.value = 0;
+                break;
             case NodeMaterialBlockConnectionPointTypes.Vector2:
                 connection.value = Vector2.Zero();
                 break;

+ 2 - 1
nodeEditor/src/components/nodeList/nodeListComponent.tsx

@@ -22,6 +22,7 @@ import { Vector2TransformBlock } from 'babylonjs/Materials/Node/Blocks/vector2Tr
 import { Vector3TransformBlock } from 'babylonjs/Materials/Node/Blocks/vector3TransformBlock';
 import { Vector4TransformBlock } from 'babylonjs/Materials/Node/Blocks/vector4TransformBlock';
 import { NodeMaterialBlock } from 'babylonjs/Materials/Node/nodeMaterialBlock';
+import { ScaleBlock } from 'babylonjs/Materials/Node/Blocks/scaleBlock';
 
 require("./nodeList.scss");
 
@@ -39,7 +40,7 @@ export class NodeListComponent extends React.Component<INodeListComponentProps>
             Fragment: [AlphaTestBlock, , ImageProcessingBlock, RGBAMergerBlock, RGBASplitterBlock, TextureBlock],
             Outputs: [VertexOutputBlock, FragmentOutputBlock],
             Dual: [FogBlock],
-            Math: [AddBlock, ClampBlock, MatrixMultiplicationBlock, MultiplyBlock, Vector2TransformBlock, Vector3TransformBlock, Vector4TransformBlock],
+            Math: [AddBlock, ClampBlock, MatrixMultiplicationBlock, MultiplyBlock, ScaleBlock, Vector2TransformBlock, Vector3TransformBlock, Vector4TransformBlock],
             Inputs: ["Vector2", "Vector3", "Vector4", "Color3", "Color4", "Matrix"],
         }
 

+ 19 - 0
nodeEditor/src/components/propertyTab/properties/floatPropertyTabComponent.tsx

@@ -0,0 +1,19 @@
+
+import * as React from "react";
+import { GlobalState } from '../../../globalState';
+import { NodeMaterialConnectionPoint } from 'babylonjs/Materials/Node/nodeMaterialBlockConnectionPoint';
+import { FloatLineComponent } from '../../../sharedComponents/floatLineComponent';
+
+interface IFloatPropertyTabComponentProps {
+    globalState: GlobalState;
+    connection: NodeMaterialConnectionPoint;
+}
+
+export class FloatPropertyTabComponent extends React.Component<IFloatPropertyTabComponentProps> {
+
+    render() {
+        return (
+            <FloatLineComponent label="Value" target={this.props.connection} propertyName="value"></FloatLineComponent>
+        );
+    }
+}

+ 106 - 0
nodeEditor/src/components/propertyTab/propertyTab.scss

@@ -35,6 +35,112 @@
         }
     }
 
+    
+    .paneContainer {
+        margin-top: 3px;
+        display:grid;
+        grid-template-rows: 100%;
+        grid-template-columns: 100%;
+        
+        .paneList {
+            border-left: 3px solid transparent;
+        }
+
+        &:hover {  
+            .paneList {                      
+                border-left: 3px solid rgba(51, 122, 183, 0.8);
+            }
+
+            .paneContainer-content {
+                .header {
+                    .title {   
+                        border-left: 3px solid rgb(51, 122, 183);
+                    }
+                }
+            }
+        }
+        
+        .paneContainer-highlight-border {
+            grid-row: 1;
+            grid-column: 1;
+            opacity: 1;
+            border: 3px solid red;
+            transition: opacity 250ms;
+            pointer-events: none;
+            
+            &.transparent {
+                opacity: 0;
+            }
+        }
+
+        .paneContainer-content {
+            grid-row: 1;
+            grid-column: 1;
+
+            .header {
+                display: grid;
+                grid-template-columns: 1fr auto;
+                background: #555555;    
+                height: 30px;   
+                padding-right: 5px;                        
+                cursor: pointer;
+                
+                .title {                                
+                    border-left: 3px solid transparent;
+                    padding-left: 5px;
+                    grid-column: 1;
+                    display: flex;
+                    align-items: center;
+                }
+
+                .collapse {
+                    grid-column: 2;
+                    display: flex;
+                    align-items: center;  
+                    justify-items: center;
+                    transform-origin: center;
+
+                    &.closed {
+                        transform: rotate(180deg);
+                    }
+                }                        
+            }
+
+            .paneList > div:not(:last-child) {
+                border-bottom: 0.5px solid rgba(255, 255, 255, 0.1);
+            }
+
+            .fragment > div:not(:last-child)  {
+                border-bottom: 0.5px solid rgba(255, 255, 255, 0.1);
+            }
+        }
+    }
+
+    .floatLine {
+        padding-left: $line-padding-left;
+        height: 30px;
+        display: grid;
+        grid-template-columns: 1fr 120px;
+
+
+        .label {
+            grid-column: 1;
+            display: flex;
+            align-items: center;
+        }
+
+        .value {
+            grid-column: 2;
+            
+            display: flex;
+            align-items: center;
+            
+            input {
+                width: 110px;
+            }
+        }
+    }
+
     .vector3Line {
         padding-left:$line-padding-left;                    
         display: grid;

+ 9 - 4
nodeEditor/src/components/propertyTab/propertyTabComponent.tsx

@@ -4,6 +4,7 @@ import { GlobalState } from '../../globalState';
 import { Nullable } from 'babylonjs/types';
 import { DefaultNodeModel } from '../../components/diagram/defaultNodeModel';
 import { ButtonLineComponent } from '../../sharedComponents/buttonLineComponent';
+import { LineContainerComponent } from '../../sharedComponents/lineContainerComponent';
 require("./propertyTab.scss");
 
 interface IPropertyTabComponentProps {
@@ -48,10 +49,14 @@ export class PropertyTabComponent extends React.Component<IPropertyTabComponentP
                     </div>
                 </div>
                 <div>
-                    <ButtonLineComponent label="Reset to default" onClick={() => {
-                        this.props.globalState.nodeMaterial!.setToDefault();
-                        this.props.globalState.onResetRequiredObservable.notifyObservers();
-                    }} />
+                    <LineContainerComponent title="PROPERTIES">
+                    </LineContainerComponent>
+                    <LineContainerComponent title="GENERAL">
+                        <ButtonLineComponent label="Reset to default" onClick={() => {
+                            this.props.globalState.nodeMaterial!.setToDefault();
+                            this.props.globalState.onResetRequiredObservable.notifyObservers();
+                        }} />
+                    </LineContainerComponent>
                 </div>
             </div>
         );

+ 1 - 1
nodeEditor/src/graphEditor.tsx

@@ -227,7 +227,7 @@ export class GraphEditor extends React.Component<IGraphEditorProps> {
             this._toAdd = null;
             this._engine.setDiagramModel(this._model);
             this.forceUpdate();
-        }, 15);
+        }, 250);
     }
 
     addNodeFromClass(ObjectClass: typeof NodeMaterialBlock) {

+ 105 - 0
nodeEditor/src/sharedComponents/floatLineComponent.tsx

@@ -0,0 +1,105 @@
+import * as React from "react";
+
+import { Observable } from "babylonjs/Misc/observable";
+import { PropertyChangedEvent } from "./propertyChangedEvent";
+
+interface IFloatLineComponentProps {
+    label: string;
+    target: any;
+    propertyName: string;
+    onChange?: (newValue: number) => void;
+    isInteger?: boolean;
+    onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
+    additionalClass?: string;
+    step?: string,
+    digits?: number;
+}
+
+export class FloatLineComponent extends React.Component<IFloatLineComponentProps, { value: string }> {
+    private _localChange = false;
+    private _store: number;
+
+    constructor(props: IFloatLineComponentProps) {
+        super(props);
+
+        let currentValue = this.props.target[this.props.propertyName];
+        this.state = { value: currentValue ? (this.props.isInteger ? currentValue.toFixed(0) : currentValue.toFixed(this.props.digits || 3)) : "0" };
+        this._store = currentValue;
+    }
+
+    shouldComponentUpdate(nextProps: IFloatLineComponentProps, nextState: { value: string }) {
+        if (this._localChange) {
+            this._localChange = false;
+            return true;
+        }
+
+        const newValue = nextProps.target[nextProps.propertyName];
+        const newValueString = newValue ? this.props.isInteger ? newValue.toFixed(0) : newValue.toFixed(this.props.digits || 3) : "0";
+
+        if (newValueString !== nextState.value) {
+            nextState.value = newValueString;
+            return true;
+        }
+        return false;
+    }
+
+    raiseOnPropertyChanged(newValue: number, previousValue: number) {
+        if (this.props.onChange) {
+            this.props.onChange(newValue);
+        }
+
+        if (!this.props.onPropertyChangedObservable) {
+            return;
+        }
+        this.props.onPropertyChangedObservable.notifyObservers({
+            object: this.props.target,
+            property: this.props.propertyName,
+            value: newValue,
+            initialValue: previousValue
+        });
+    }
+
+    updateValue(valueString: string) {
+
+        if (/[^0-9\.\-]/g.test(valueString)) {
+            return;
+        }
+
+        let valueAsNumber: number;
+
+        if (this.props.isInteger) {
+            valueAsNumber = parseInt(valueString);
+        } else {
+            valueAsNumber = parseFloat(valueString);
+        }
+
+        this._localChange = true;
+        this.setState({ value: valueString });
+
+        if (isNaN(valueAsNumber)) {
+            return;
+        }
+
+        this.raiseOnPropertyChanged(valueAsNumber, this._store);
+        this.props.target[this.props.propertyName] = valueAsNumber;
+
+        this._store = valueAsNumber;
+    }
+
+    render() {
+        return (
+            <div>
+                {
+                    <div className={this.props.additionalClass ? this.props.additionalClass + " floatLine" : "floatLine"}>
+                        <div className="label">
+                            {this.props.label}
+                        </div>
+                        <div className="value">
+                            <input type="number" step={this.props.step || "0.01"} className="numeric-input" value={this.state.value} onChange={evt => this.updateValue(evt.target.value)} />
+                        </div>
+                    </div>
+                }
+            </div>
+        );
+    }
+}

+ 2 - 7
src/Materials/Node/Blocks/scaleBlock.ts

@@ -18,6 +18,8 @@ export class ScaleBlock extends NodeMaterialBlock {
         this.registerOutput("output", NodeMaterialBlockConnectionPointTypes.BasedOnInput);
 
         this._outputs[0]._typeConnectionSource = this._inputs[0];
+
+        this.scale.value = 1;
     }
 
     /**
@@ -42,13 +44,6 @@ export class ScaleBlock extends NodeMaterialBlock {
         return this._inputs[1];
     }
 
-    /**
-     * Gets the right operand input component
-     */
-    public get right(): NodeMaterialConnectionPoint {
-        return this._inputs[1];
-    }
-
     protected _buildBlock(state: NodeMaterialBuildState) {
         super._buildBlock(state);