Browse Source

adding gradient to the inspector from NME

Pamela Wolf 5 years ago
parent
commit
d27037160b

+ 114 - 1
inspector/src/components/actionTabs/actionTabs.scss

@@ -127,7 +127,6 @@ $line-padding-left: 2px;
 
         .panes {
             grid-row: 2;
-
             display: grid;
             grid-template-rows: 100%;
 
@@ -140,6 +139,120 @@ $line-padding-left: 2px;
                                 
             }
 
+            .gradient-step {
+                display: grid;
+                grid-template-rows: 100%;
+                grid-template-columns: 25px 50px 55px 40px auto 20px 5px;
+                padding-top: 5px;
+                padding-left: 5px;
+                padding-bottom: 5px;    
+                align-items: center;
+        
+                .step {
+                    grid-row: 1;
+                    grid-column: 1;
+                }
+
+                .color1 {
+                    height: 100%;
+                }
+
+                .color2{
+                    height: 100%;
+                    padding-left: 5px;
+                }
+                    
+                .factor1 {
+                    grid-row: 1;
+                    grid-column: 2;
+                    cursor: pointer;
+                }
+
+                .factor2 {
+                    padding-left: 5px;
+                    grid-row: 1;
+                    grid-column: 3;
+                    cursor: pointer;
+
+                    .grayed {
+                        background: gray;
+                        border-color: gray;
+                    }
+                }
+
+                .numeric-input {
+                    width: calc(100% - 5px);
+                }
+
+                .icon{
+                    cursor: pointer;
+                }
+        
+                .step-value {       
+                    margin-left: 5px;     
+                    grid-row: 1;
+                    grid-column: 4;
+                    text-align: right;
+                    margin-right: 5px;
+                }
+        
+                .step-slider {            
+                    grid-row: 1;
+                    grid-column: 5;
+                    display: grid;
+                    justify-content: stretch;
+                    align-content: center;
+                    margin-right: 12px;
+        
+                    input {
+                        width: 100%;
+                    }
+                    .range:hover {
+                        opacity: 1;
+                    }
+
+                    .range {
+                        -webkit-appearance: none;
+                        height: 6px;
+                        background: #d3d3d3;
+                        border-radius: 5px;
+                        outline: none;
+                        opacity: 0.7;
+                        -webkit-transition: .2s;
+                        transition: opacity .2s;
+                    }
+                    .range::-webkit-slider-thumb {
+                        -webkit-appearance: none;
+                        appearance: none;
+                        width: 14px;
+                        height: 14px;
+                        border-radius: 50%;
+                        background: rgb(51, 122, 183);
+                        cursor: pointer;
+                    }
+                    
+                    .range::-moz-range-thumb {
+                        width: 14px;
+                        height: 14px;
+                        border-radius: 50%;
+                        background: rgb(51, 122, 183);
+                        cursor: pointer;
+                    }
+
+                  
+
+                }
+               
+        
+                .gradient-delete {            
+                    grid-row: 1;
+                    grid-column: 6;
+                    display: grid;
+                    align-content: center;
+                    justify-content: center;
+                }
+            }
+
             .pane {
                 color: white;
 

+ 84 - 0
inspector/src/components/actionTabs/tabs/gradientNodePropertyComponent.tsx

@@ -0,0 +1,84 @@
+
+import * as React from "react";
+import { GradientBlockColorStep, GradientBlock } from 'babylonjs/Materials/Node/Blocks/gradientBlock';
+import { GradientStepComponent } from './gradientStepComponent';
+import { Color3 } from 'babylonjs/Maths/math.color';
+import { ButtonLineComponent } from '../lines/buttonLineComponent';
+import { IPropertyComponentProps } from './propertyComponentProps';
+
+
+
+export class GradientPropertyTabComponent extends React.Component<IPropertyComponentProps> {
+
+    constructor(props: IPropertyComponentProps) {
+        super(props)
+    }
+
+    forceRebuild() {
+        //this.props.globalState.onUpdateRequiredObservable.notifyObservers();
+        //this.props.globalState.onRebuildRequiredObservable.notifyObservers();
+
+        this.forceUpdate();
+    }
+
+    deleteStep(step: GradientBlockColorStep) {
+        let gradientBlock = this.props.block as GradientBlock;
+
+        let index = gradientBlock.colorSteps.indexOf(step);
+
+        if (index > -1) {
+            gradientBlock.colorSteps.splice(index, 1);
+            this.forceRebuild();
+            this.forceUpdate();
+        }
+    }
+
+    addNewStep() {
+        let gradientBlock = this.props.block as GradientBlock;
+
+        let newStep = new GradientBlockColorStep(1.0, Color3.White());
+        gradientBlock.colorSteps.push(newStep);
+
+        this.forceRebuild();
+        this.forceUpdate();
+    }
+
+    checkForReOrder() {
+        let gradientBlock = this.props.block as GradientBlock;
+        gradientBlock.colorSteps.sort((a, b) => {
+            if (a.step === b.step) {
+                return 0;
+            }
+
+            if (a.step > b.step) {
+                return 1;
+            }
+
+            return -1;
+        });
+
+        //this.props.globalState.onUpdateRequiredObservable.notifyObservers();
+        this.forceUpdate();
+    }
+
+    render() {
+        let gradientBlock = this.props.block as GradientBlock;
+
+        return (
+            <div>
+               
+                <ButtonLineComponent label="Add new step" onClick={() => this.addNewStep()} />
+                {
+                    gradientBlock.colorSteps.map((c, i) => {
+                        return (
+                            <GradientStepComponent globalState={this.props.globalState} 
+                            onCheckForReOrder={() => this.checkForReOrder()}
+                            onUpdateStep={() => this.forceRebuild()}
+                            key={"step-" + i} lineIndex={i} step={c} onDelete={() => this.deleteStep(c)}/>
+                        )
+                    })
+                    }
+            </div>
+        );
+    }
+}

+ 75 - 0
inspector/src/components/actionTabs/tabs/gradientStepComponent.tsx

@@ -0,0 +1,75 @@
+import * as React from 'react';
+import { GlobalState } from '../../globalState';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { faTrash } from '@fortawesome/free-solid-svg-icons';
+import { Color3 } from 'babylonjs/Maths/math.color';
+import { GradientBlockColorStep } from 'babylonjs/Materials/Node/Blocks/gradientBlock';
+import { ColorPickerLineComponent } from '../lines/colorPickerComponent';
+
+
+interface IGradientStepComponentProps {
+    globalState: GlobalState;
+    step: GradientBlockColorStep;
+    lineIndex: number;
+    onDelete: () => void;
+    onUpdateStep: () => void;
+    onCheckForReOrder: () => void;
+}
+
+export class GradientStepComponent extends React.Component<IGradientStepComponentProps, {gradient: number}> {
+
+    constructor(props: IGradientStepComponentProps) {
+        super(props);
+
+        this.state={gradient: props.step.step};
+    }
+
+    updateColor(color: string) {
+        this.props.step.color = Color3.FromHexString(color);
+
+        this.props.onUpdateStep();
+        this.forceUpdate();
+    }    
+    
+    updateStep(gradient: number) {
+        this.props.step.step = gradient;
+
+        this.setState({gradient: gradient});
+
+        this.props.onUpdateStep();
+    }
+
+    onPointerUp() {
+        this.props.onCheckForReOrder();
+    }
+
+    render() {
+        let step = this.props.step;
+
+        return (
+            <div className="gradient-step">
+                <div className="step">
+                    {`#${this.props.lineIndex}`}
+                </div>
+                <div className="color">
+                    <ColorPickerLineComponent value={step.color} disableAlpha={true} //globalState={this.props.globalState} 
+                            onColorChanged={color => {
+                                    this.updateColor(color);
+                            }} 
+                    />  
+                </div>
+                <div className="step-value">
+                    {step.step.toFixed(2)}
+                </div>
+                <div className="step-slider slider">
+                    <input className="range" type="range" step={0.01} min={0} max={1.0} value={step.step}
+                        onPointerUp={evt => this.onPointerUp()}
+                        onChange={evt => this.updateStep(parseFloat(evt.target.value))} />
+                </div>
+                <div className="gradient-delete" onClick={() => this.props.onDelete()}>
+                    <FontAwesomeIcon icon={faTrash} />
+                </div>
+            </div>
+        )
+    }
+}

+ 7 - 0
inspector/src/components/actionTabs/tabs/propertyComponentProps.ts

@@ -0,0 +1,7 @@
+import { GlobalState } from "../../globalState";
+import { NodeMaterialBlock } from 'babylonjs/Materials/Node/nodeMaterialBlock';
+
+export interface IPropertyComponentProps {
+    globalState: GlobalState;
+    block: NodeMaterialBlock;
+}

+ 30 - 14
inspector/src/components/actionTabs/tabs/propertyGrids/materials/nodeMaterialPropertyGridComponent.tsx

@@ -20,6 +20,7 @@ import { SliderLineComponent } from '../../../lines/sliderLineComponent';
 import { NodeMaterialBlockConnectionPointTypes } from 'babylonjs/Materials/Node/Enums/nodeMaterialBlockConnectionPointTypes';
 import { InputBlock } from 'babylonjs/Materials/Node/Blocks/Input/inputBlock';
 import { Color4LineComponent } from '../../../lines/color4LineComponent';
+import { GradientPropertyTabComponent } from '../../gradientNodePropertyComponent';
 
 interface INodeMaterialPropertyGridComponentProps {
     globalState: GlobalState;
@@ -118,6 +119,7 @@ export class NodeMaterialPropertyGridComponent extends React.Component<INodeMate
                         onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                 )
             }
+            
         return null;
     }
 
@@ -128,12 +130,7 @@ export class NodeMaterialPropertyGridComponent extends React.Component<INodeMate
             return a.name.localeCompare(b.name);
         });
 
-        if (configurableInputBlocks.length === 0) {
-            return null;
-        }
-
         let namedGroups: string[] = [];
-
         configurableInputBlocks.forEach(block => {
             if (!block.groupInInspector) {
                 return;
@@ -143,18 +140,26 @@ export class NodeMaterialPropertyGridComponent extends React.Component<INodeMate
                 namedGroups.push(block.groupInInspector);
             }
         });
-
         namedGroups.sort();
+        
+
+        let gradiantNodeMaterialBlocks = this.props.material.attachedBlocks.filter(block => {
+            return block.visibleInInspector && block.getClassName() === 'GradientBlock'
+        }).sort( (a, b) => {
+            return a.name.localeCompare(b.name);
+        });
+
+        let inputBlockContainer = configurableInputBlocks.length > 0 ?
+            <LineContainerComponent globalState={this.props.globalState} title="INPUTS"> {
+                configurableInputBlocks.filter(block => !block.groupInInspector).map(block => {
+                    return this.renderInputBlock(block);
+                })
+            }
+            </LineContainerComponent> : null;
 
         return (           
             <>
-                <LineContainerComponent globalState={this.props.globalState} title="INPUTS">
-                    {
-                        configurableInputBlocks.filter(block => !block.groupInInspector).map(block => {
-                            return this.renderInputBlock(block);
-                        })
-                    }           
-                </LineContainerComponent>
+                {inputBlockContainer}
                 {
                     namedGroups.map((name, i) => {
                         return (
@@ -166,7 +171,18 @@ export class NodeMaterialPropertyGridComponent extends React.Component<INodeMate
                             }
                             </LineContainerComponent>
                         )
-                    })
+                    })   
+                }
+                {
+                    gradiantNodeMaterialBlocks.map((block,i) => {
+                        return (
+                            <LineContainerComponent key={block.name +i} globalState={this.props.globalState} title={block.name.toUpperCase()}>
+                            {
+                                <GradientPropertyTabComponent globalState={this.props.globalState} block={block}/>
+                            }
+                            </LineContainerComponent>
+                        )
+                    })   
                 }
           </>
         );

+ 34 - 0
nodeEditor/src/diagram/properties/gradientNodePropertyComponent.tsx

@@ -7,6 +7,7 @@ import { ButtonLineComponent } from '../../sharedComponents/buttonLineComponent'
 import { Color3 } from 'babylonjs/Maths/math.color';
 import { IPropertyComponentProps } from './propertyComponentProps';
 import { GeneralPropertyTabComponent } from './genericNodePropertyComponent';
+import { OptionsLineComponent } from '../../sharedComponents/optionsLineComponent';
 
 export class GradientPropertyTabComponent extends React.Component<IPropertyComponentProps> {
 
@@ -62,9 +63,42 @@ export class GradientPropertyTabComponent extends React.Component<IPropertyCompo
     render() {
         let gradientBlock = this.props.block as GradientBlock;
       
+        var typeOptions = [
+            { label: "None", value: 0 },
+            { label: "Visible in the inspector", value: 1 },
+        ];
+
         return (
             <div>
                 <GeneralPropertyTabComponent globalState={this.props.globalState} block={this.props.block}/>
+                <LineContainerComponent title="PROPERTIES">
+                <OptionsLineComponent label="Type" options={typeOptions} target={this.props.block} 
+                            noDirectUpdate={true}
+                            getSelection={(block) => {
+                                if (block.visibleInInspector) {
+                                    return 1;
+                                }
+
+                                if (block.isConstant) {
+                                    return 2;
+                                }
+
+                                return 0;
+                            }}
+                            onSelect={(value: any) => {
+                                switch (value) {
+                                    case 0:
+                                        this.props.block.visibleInInspector = false;
+                                        break;
+                                    case 1:
+                                        this.props.block.visibleInInspector = true;
+                                        break;
+                                }
+                                this.forceUpdate();
+                                this.props.globalState.onUpdateRequiredObservable.notifyObservers();
+                                this.props.globalState.onRebuildRequiredObservable.notifyObservers();
+                            }} />                        
+                </LineContainerComponent>
                 <LineContainerComponent title="STEPS">
                     <ButtonLineComponent label="Add new step" onClick={() => this.addNewStep()} />
                     {

+ 1 - 4
src/Materials/Node/Blocks/Input/inputBlock.ts

@@ -60,12 +60,9 @@ export class InputBlock extends NodeMaterialBlock {
     /** @hidden */
     public _systemValue: Nullable<NodeMaterialSystemValues> = null;
 
-    /** Gets or sets a boolean indicating that this input can be edited in the Inspector (false by default) */
-    public visibleInInspector = false;
-
     /** Gets or sets a boolean indicating that the value of this input will not change after a build */
     public isConstant = false;
-
+    
     /** Gets or sets the group to use to display this block in the Inspector */
     public groupInInspector = "";
 

+ 3 - 0
src/Materials/Node/nodeMaterialBlock.ts

@@ -156,6 +156,9 @@ export class NodeMaterialBlock {
         return null;
     }
 
+     /** Gets or sets a boolean indicating that this input can be edited in the Inspector (false by default) */
+     public visibleInInspector = false;
+     
     /**
      * Creates a new NodeMaterialBlock
      * @param name defines the block name