genericNodePropertyComponent.tsx 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. import * as React from "react";
  2. import { LineContainerComponent } from '../../sharedComponents/lineContainerComponent';
  3. import { IPropertyComponentProps } from './propertyComponentProps';
  4. import { TextInputLineComponent } from '../../sharedComponents/textInputLineComponent';
  5. import { TextLineComponent } from '../../sharedComponents/textLineComponent';
  6. import { CheckBoxLineComponent } from '../../sharedComponents/checkBoxLineComponent';
  7. import { FloatLineComponent } from '../../sharedComponents/floatLineComponent';
  8. import { SliderLineComponent } from '../../sharedComponents/sliderLineComponent';
  9. import { Vector2LineComponent } from '../../sharedComponents/vector2LineComponent';
  10. import { OptionsLineComponent } from '../../sharedComponents/optionsLineComponent';
  11. import { InputBlock } from 'babylonjs/Materials/Node/Blocks/Input/inputBlock';
  12. import { PropertyTypeForEdition, IPropertyDescriptionForEdition, IEditablePropertyListOption } from 'babylonjs/Materials/Node/nodeMaterialDecorator';
  13. import { NodeMaterialBlockTargets } from "babylonjs/Materials/Node/Enums/nodeMaterialBlockTargets";
  14. export class GenericPropertyComponent extends React.Component<IPropertyComponentProps> {
  15. constructor(props: IPropertyComponentProps) {
  16. super(props);
  17. }
  18. render() {
  19. return (
  20. <>
  21. <GeneralPropertyTabComponent globalState={this.props.globalState} block={this.props.block}/>
  22. <GenericPropertyTabComponent globalState={this.props.globalState} block={this.props.block}/>
  23. </>
  24. );
  25. }
  26. }
  27. export class GeneralPropertyTabComponent extends React.Component<IPropertyComponentProps> {
  28. constructor(props: IPropertyComponentProps) {
  29. super(props);
  30. }
  31. render() {
  32. var targetOptions = [
  33. { label: "Neutral", value: NodeMaterialBlockTargets.Neutral },
  34. { label: "Vertex", value: NodeMaterialBlockTargets.Vertex },
  35. { label: "Fragment", value: NodeMaterialBlockTargets.Fragment },
  36. ];
  37. return (
  38. <>
  39. <LineContainerComponent title="GENERAL">
  40. {
  41. (!this.props.block.isInput || !(this.props.block as InputBlock).isAttribute) &&
  42. <TextInputLineComponent globalState={this.props.globalState} label="Name" propertyName="name" target={this.props.block}
  43. onChange={() => this.props.globalState.onUpdateRequiredObservable.notifyObservers()}
  44. validator={ newName =>
  45. {if(!this.props.block.validateBlockName(newName)){
  46. this.props.globalState.onErrorMessageDialogRequiredObservable.notifyObservers(`"${newName}" is a reserved name, please choose another`);
  47. return false;
  48. }
  49. return true;
  50. }} />
  51. }
  52. {
  53. (this.props.block.target === NodeMaterialBlockTargets.Neutral || (this.props.block as any)._modifiedTarget) &&
  54. <OptionsLineComponent label="Target" options={targetOptions} target={this.props.block} propertyName="target" onSelect={(value: any) => {
  55. (this.props.block as any)._modifiedTarget = true;
  56. this.forceUpdate();
  57. this.props.globalState.onUpdateRequiredObservable.notifyObservers();
  58. this.props.globalState.onRebuildRequiredObservable.notifyObservers();
  59. }} />
  60. }
  61. {
  62. (this.props.block.target !== NodeMaterialBlockTargets.Neutral && !(this.props.block as any)._modifiedTarget) &&
  63. <TextLineComponent label="Type" value={NodeMaterialBlockTargets[this.props.block.target]} />
  64. }
  65. <TextLineComponent label="Type" value={this.props.block.getClassName()} />
  66. <TextInputLineComponent globalState={this.props.globalState} label="Comments" propertyName="comments" target={this.props.block}
  67. onChange={() => this.props.globalState.onUpdateRequiredObservable.notifyObservers()} />
  68. </LineContainerComponent>
  69. </>
  70. );
  71. }
  72. }
  73. export class GenericPropertyTabComponent extends React.Component<IPropertyComponentProps> {
  74. constructor(props: IPropertyComponentProps) {
  75. super(props);
  76. }
  77. forceRebuild(notifiers?: { "rebuild"?: boolean; "update"?: boolean; }) {
  78. if (!notifiers || notifiers.update) {
  79. this.props.globalState.onUpdateRequiredObservable.notifyObservers();
  80. }
  81. if (!notifiers || notifiers.rebuild) {
  82. this.props.globalState.onRebuildRequiredObservable.notifyObservers();
  83. }
  84. }
  85. render() {
  86. const block = this.props.block,
  87. propStore: IPropertyDescriptionForEdition[] = (block as any)._propStore;
  88. if (!propStore) {
  89. return (
  90. <>
  91. </>
  92. );
  93. }
  94. const componentList: { [groupName: string]: JSX.Element[]} = {},
  95. groups: string[] = [];
  96. for (const { propertyName, displayName, type, groupName, options } of propStore) {
  97. let components = componentList[groupName];
  98. if (!components) {
  99. components = [];
  100. componentList[groupName] = components;
  101. groups.push(groupName);
  102. }
  103. switch (type) {
  104. case PropertyTypeForEdition.Boolean: {
  105. components.push(
  106. <CheckBoxLineComponent label={displayName} target={this.props.block} propertyName={propertyName} onValueChanged={() => this.forceRebuild(options.notifiers)} />
  107. );
  108. break;
  109. }
  110. case PropertyTypeForEdition.Float: {
  111. let cantDisplaySlider = (isNaN(options.min as number) || isNaN(options.max as number) || options.min === options.max);
  112. if (cantDisplaySlider) {
  113. components.push(
  114. <FloatLineComponent globalState={this.props.globalState} label={displayName} propertyName={propertyName} target={this.props.block} onChange={() => this.forceRebuild(options.notifiers)} />
  115. );
  116. } else {
  117. components.push(
  118. <SliderLineComponent label={displayName} target={this.props.block} globalState={this.props.globalState} propertyName={propertyName} step={Math.abs((options.max as number) - (options.min as number)) / 100.0} minimum={Math.min(options.min as number, options.max as number)} maximum={options.max as number} onChange={() => this.forceRebuild(options.notifiers)}/>
  119. );
  120. }
  121. break;
  122. }
  123. case PropertyTypeForEdition.Vector2: {
  124. components.push(
  125. <Vector2LineComponent globalState={this.props.globalState} label={displayName} propertyName={propertyName} target={this.props.block} onChange={() => this.forceRebuild(options.notifiers)} />
  126. );
  127. break;
  128. }
  129. case PropertyTypeForEdition.List: {
  130. components.push(
  131. <OptionsLineComponent label={displayName} options={options.options as IEditablePropertyListOption[]} target={this.props.block} propertyName={propertyName} onSelect={() => this.forceRebuild(options.notifiers)} />
  132. );
  133. break;
  134. }
  135. }
  136. }
  137. return (
  138. <>
  139. {
  140. groups.map((group) =>
  141. <LineContainerComponent title={group}>
  142. {componentList[group]}
  143. </LineContainerComponent>
  144. )
  145. }
  146. </>
  147. );
  148. }
  149. }