propertyTabComponent.tsx 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. import * as React from "react";
  2. import { GlobalState } from '../../globalState';
  3. import { Nullable } from 'babylonjs/types';
  4. import { DefaultNodeModel } from '../../components/diagram/defaultNodeModel';
  5. import { ButtonLineComponent } from '../../sharedComponents/buttonLineComponent';
  6. import { LineContainerComponent } from '../../sharedComponents/lineContainerComponent';
  7. import { StringTools } from '../../stringTools';
  8. import { FileButtonLineComponent } from '../../sharedComponents/fileButtonLineComponent';
  9. import { Tools } from 'babylonjs/Misc/tools';
  10. import { INodeLocationInfo } from '../../nodeLocationInfo';
  11. require("./propertyTab.scss");
  12. interface IPropertyTabComponentProps {
  13. globalState: GlobalState;
  14. }
  15. export class PropertyTabComponent extends React.Component<IPropertyTabComponentProps, { currentNode: Nullable<DefaultNodeModel> }> {
  16. constructor(props: IPropertyTabComponentProps) {
  17. super(props)
  18. this.state = { currentNode: null };
  19. }
  20. componentWillMount() {
  21. this.props.globalState.onSelectionChangedObservable.add(block => {
  22. this.setState({ currentNode: block });
  23. });
  24. }
  25. load(file: File) {
  26. Tools.ReadFile(file, (data) => {
  27. let decoder = new TextDecoder("utf-8");
  28. let serializationObject = JSON.parse(decoder.decode(data));
  29. this.props.globalState.nodeMaterial!.loadFromSerialization(serializationObject, "");
  30. // Check for id mapping
  31. if (serializationObject.locations && serializationObject.map) {
  32. let map: {[key: number]: number} = serializationObject.map;
  33. let locations: INodeLocationInfo[] = serializationObject.locations;
  34. for (var location of locations) {
  35. location.blockId = map[location.blockId];
  36. }
  37. }
  38. this.props.globalState.onResetRequiredObservable.notifyObservers(serializationObject.locations);
  39. }, undefined, true);
  40. }
  41. save() {
  42. let material = this.props.globalState.nodeMaterial;
  43. let serializationObject = material.serialize();
  44. // Store node locations
  45. for (var block of material.attachedBlocks) {
  46. let node = this.props.globalState.onGetNodeFromBlock(block);
  47. if (!serializationObject.locations) {
  48. serializationObject.locations = [];
  49. }
  50. serializationObject.locations.push({
  51. blockId: block.uniqueId,
  52. x: node ? node.x : 0,
  53. y: node ? node.y : 0
  54. });
  55. }
  56. // Output
  57. let json = JSON.stringify(serializationObject, undefined, 2);
  58. StringTools.DownloadAsFile(this.props.globalState.hostDocument, json, "nodeMaterial.json");
  59. }
  60. render() {
  61. if (this.state.currentNode) {
  62. return (
  63. <div id="propertyTab">
  64. <div id="header">
  65. <img id="logo" src="https://www.babylonjs.com/Assets/logo-babylonjs-social-twitter.png" />
  66. <div id="title">
  67. NODE MATERIAL EDITOR
  68. </div>
  69. </div>
  70. {this.state.currentNode.renderProperties(this.props.globalState)}
  71. </div>
  72. );
  73. }
  74. return (
  75. <div id="propertyTab">
  76. <div id="header">
  77. <img id="logo" src="https://www.babylonjs.com/Assets/logo-babylonjs-social-twitter.png" />
  78. <div id="title">
  79. NODE MATERIAL EDITOR
  80. </div>
  81. </div>
  82. <div>
  83. <LineContainerComponent title="GENERAL">
  84. <ButtonLineComponent label="Reset to default" onClick={() => {
  85. this.props.globalState.nodeMaterial!.setToDefault();
  86. this.props.globalState.onResetRequiredObservable.notifyObservers(null);
  87. }} />
  88. </LineContainerComponent>
  89. <LineContainerComponent title="UI">
  90. <ButtonLineComponent label="Zoom to fit" onClick={() => {
  91. this.props.globalState.onZoomToFitRequiredObservable.notifyObservers();
  92. }} />
  93. <ButtonLineComponent label="Reorganize" onClick={() => {
  94. this.props.globalState.onReOrganizedRequiredObservable.notifyObservers();
  95. }} />
  96. </LineContainerComponent>
  97. <LineContainerComponent title="FILE">
  98. <FileButtonLineComponent label="Load" onClick={(file) => this.load(file)} accept=".json" />
  99. <ButtonLineComponent label="Save" onClick={() => {
  100. this.save();
  101. }} />
  102. <ButtonLineComponent label="Generate code" onClick={() => {
  103. StringTools.DownloadAsFile(this.props.globalState.hostDocument, this.props.globalState.nodeMaterial!.generateCode(), "code.txt");
  104. }} />
  105. <ButtonLineComponent label="Export shaders" onClick={() => {
  106. StringTools.DownloadAsFile(this.props.globalState.hostDocument, this.props.globalState.nodeMaterial!.compiledShaders, "shaders.txt");
  107. }} />
  108. </LineContainerComponent>
  109. </div>
  110. </div>
  111. );
  112. }
  113. }