inputBlock.ts 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697
  1. import { NodeMaterialBlock } from '../../nodeMaterialBlock';
  2. import { NodeMaterialBlockConnectionPointTypes } from '../../Enums/nodeMaterialBlockConnectionPointTypes';
  3. import { NodeMaterialBlockConnectionPointMode } from '../../Enums/nodeMaterialBlockConnectionPointMode';
  4. import { NodeMaterialSystemValues } from '../../Enums/nodeMaterialSystemValues';
  5. import { Nullable } from '../../../../types';
  6. import { Effect } from '../../../../Materials/effect';
  7. import { Matrix, Vector2, Vector3, Vector4 } from '../../../../Maths/math.vector';
  8. import { Scene } from '../../../../scene';
  9. import { NodeMaterialConnectionPoint } from '../../nodeMaterialBlockConnectionPoint';
  10. import { NodeMaterialBuildState } from '../../nodeMaterialBuildState';
  11. import { NodeMaterialBlockTargets } from '../../Enums/nodeMaterialBlockTargets';
  12. import { _TypeStore } from '../../../../Misc/typeStore';
  13. import { Color3, Color4 } from '../../../../Maths/math';
  14. import { AnimatedInputBlockTypes } from './animatedInputBlockTypes';
  15. import { Observable } from '../../../../Misc/observable';
  16. import { MaterialHelper } from '../../../../Materials/materialHelper';
  17. /**
  18. * Block used to expose an input value
  19. */
  20. export class InputBlock extends NodeMaterialBlock {
  21. private _mode = NodeMaterialBlockConnectionPointMode.Undefined;
  22. private _associatedVariableName: string;
  23. private _storedValue: any;
  24. private _valueCallback: () => any;
  25. private _type: NodeMaterialBlockConnectionPointTypes;
  26. private _animationType = AnimatedInputBlockTypes.None;
  27. /** Gets or set a value used to limit the range of float values */
  28. public min: number = 0;
  29. /** Gets or set a value used to limit the range of float values */
  30. public max: number = 0;
  31. /** Gets or set a value indicating that this input can only get 0 and 1 values */
  32. public isBoolean: boolean = false;
  33. /** Gets or sets a value used by the Node Material editor to determine how to configure the current value if it is a matrix */
  34. public matrixMode: number = 0;
  35. /** @hidden */
  36. public _systemValue: Nullable<NodeMaterialSystemValues> = null;
  37. /** Gets or sets a boolean indicating that this input can be edited in the Inspector (false by default) */
  38. public visibleInInspector = false;
  39. /** Gets or sets a boolean indicating that the value of this input will not change after a build */
  40. public isConstant = false;
  41. /** Gets or sets the group to use to display this block in the Inspector */
  42. public groupInInspector = "";
  43. /** Gets an observable raised when the value is changed */
  44. public onValueChangedObservable = new Observable<InputBlock>();
  45. /**
  46. * Gets or sets the connection point type (default is float)
  47. */
  48. public get type(): NodeMaterialBlockConnectionPointTypes {
  49. if (this._type === NodeMaterialBlockConnectionPointTypes.AutoDetect) {
  50. if (this.isUniform && this.value != null) {
  51. if (!isNaN(this.value)) {
  52. this._type = NodeMaterialBlockConnectionPointTypes.Float;
  53. return this._type;
  54. }
  55. switch (this.value.getClassName()) {
  56. case "Vector2":
  57. this._type = NodeMaterialBlockConnectionPointTypes.Vector2;
  58. return this._type;
  59. case "Vector3":
  60. this._type = NodeMaterialBlockConnectionPointTypes.Vector3;
  61. return this._type;
  62. case "Vector4":
  63. this._type = NodeMaterialBlockConnectionPointTypes.Vector4;
  64. return this._type;
  65. case "Color3":
  66. this._type = NodeMaterialBlockConnectionPointTypes.Color3;
  67. return this._type;
  68. case "Color4":
  69. this._type = NodeMaterialBlockConnectionPointTypes.Color4;
  70. return this._type;
  71. case "Matrix":
  72. this._type = NodeMaterialBlockConnectionPointTypes.Matrix;
  73. return this._type;
  74. }
  75. }
  76. if (this.isAttribute) {
  77. switch (this.name) {
  78. case "position":
  79. case "normal":
  80. case "tangent":
  81. this._type = NodeMaterialBlockConnectionPointTypes.Vector3;
  82. return this._type;
  83. case "uv":
  84. case "uv2":
  85. case "position2d":
  86. this._type = NodeMaterialBlockConnectionPointTypes.Vector2;
  87. return this._type;
  88. case "matricesIndices":
  89. case "matricesWeights":
  90. case "world0":
  91. case "world1":
  92. case "world2":
  93. case "world3":
  94. this._type = NodeMaterialBlockConnectionPointTypes.Vector4;
  95. return this._type;
  96. case "color":
  97. this._type = NodeMaterialBlockConnectionPointTypes.Color4;
  98. return this._type;
  99. }
  100. }
  101. if (this.isSystemValue) {
  102. switch (this._systemValue) {
  103. case NodeMaterialSystemValues.World:
  104. case NodeMaterialSystemValues.WorldView:
  105. case NodeMaterialSystemValues.WorldViewProjection:
  106. case NodeMaterialSystemValues.View:
  107. case NodeMaterialSystemValues.ViewProjection:
  108. case NodeMaterialSystemValues.Projection:
  109. this._type = NodeMaterialBlockConnectionPointTypes.Matrix;
  110. return this._type;
  111. case NodeMaterialSystemValues.CameraPosition:
  112. this._type = NodeMaterialBlockConnectionPointTypes.Vector3;
  113. return this._type;
  114. case NodeMaterialSystemValues.FogColor:
  115. this._type = NodeMaterialBlockConnectionPointTypes.Color3;
  116. return this._type;
  117. case NodeMaterialSystemValues.DeltaTime:
  118. this._type = NodeMaterialBlockConnectionPointTypes.Float;
  119. return this._type;
  120. }
  121. }
  122. }
  123. return this._type;
  124. }
  125. /**
  126. * Creates a new InputBlock
  127. * @param name defines the block name
  128. * @param target defines the target of that block (Vertex by default)
  129. * @param type defines the type of the input (can be set to NodeMaterialBlockConnectionPointTypes.AutoDetect)
  130. */
  131. public constructor(name: string, target = NodeMaterialBlockTargets.Vertex, type: NodeMaterialBlockConnectionPointTypes = NodeMaterialBlockConnectionPointTypes.AutoDetect) {
  132. super(name, target, false, true);
  133. this._type = type;
  134. this.setDefaultValue();
  135. this.registerOutput("output", type);
  136. }
  137. /**
  138. * Gets the output component
  139. */
  140. public get output(): NodeMaterialConnectionPoint {
  141. return this._outputs[0];
  142. }
  143. /**
  144. * Set the source of this connection point to a vertex attribute
  145. * @param attributeName defines the attribute name (position, uv, normal, etc...). If not specified it will take the connection point name
  146. * @returns the current connection point
  147. */
  148. public setAsAttribute(attributeName?: string): InputBlock {
  149. if (attributeName) {
  150. this.name = attributeName;
  151. }
  152. this._mode = NodeMaterialBlockConnectionPointMode.Attribute;
  153. return this;
  154. }
  155. /**
  156. * Set the source of this connection point to a system value
  157. * @param value define the system value to use (world, view, etc...) or null to switch to manual value
  158. * @returns the current connection point
  159. */
  160. public setAsSystemValue(value: Nullable<NodeMaterialSystemValues>): InputBlock {
  161. this.systemValue = value;
  162. return this;
  163. }
  164. /**
  165. * Gets or sets the value of that point.
  166. * Please note that this value will be ignored if valueCallback is defined
  167. */
  168. public get value(): any {
  169. return this._storedValue;
  170. }
  171. public set value(value: any) {
  172. if (this.type === NodeMaterialBlockConnectionPointTypes.Float) {
  173. if (this.isBoolean) {
  174. value = value ? 1 : 0;
  175. }
  176. else if (this.min !== this.max) {
  177. value = Math.max(this.min, value);
  178. value = Math.min(this.max, value);
  179. }
  180. }
  181. this._storedValue = value;
  182. this._mode = NodeMaterialBlockConnectionPointMode.Uniform;
  183. this.onValueChangedObservable.notifyObservers(this);
  184. }
  185. /**
  186. * Gets or sets a callback used to get the value of that point.
  187. * Please note that setting this value will force the connection point to ignore the value property
  188. */
  189. public get valueCallback(): () => any {
  190. return this._valueCallback;
  191. }
  192. public set valueCallback(value: () => any) {
  193. this._valueCallback = value;
  194. this._mode = NodeMaterialBlockConnectionPointMode.Uniform;
  195. }
  196. /**
  197. * Gets or sets the associated variable name in the shader
  198. */
  199. public get associatedVariableName(): string {
  200. return this._associatedVariableName;
  201. }
  202. public set associatedVariableName(value: string) {
  203. this._associatedVariableName = value;
  204. }
  205. /** Gets or sets the type of animation applied to the input */
  206. public get animationType() {
  207. return this._animationType;
  208. }
  209. public set animationType(value: AnimatedInputBlockTypes) {
  210. this._animationType = value;
  211. }
  212. /**
  213. * Gets a boolean indicating that this connection point not defined yet
  214. */
  215. public get isUndefined(): boolean {
  216. return this._mode === NodeMaterialBlockConnectionPointMode.Undefined;
  217. }
  218. /**
  219. * Gets or sets a boolean indicating that this connection point is coming from an uniform.
  220. * In this case the connection point name must be the name of the uniform to use.
  221. * Can only be set on inputs
  222. */
  223. public get isUniform(): boolean {
  224. return this._mode === NodeMaterialBlockConnectionPointMode.Uniform;
  225. }
  226. public set isUniform(value: boolean) {
  227. this._mode = value ? NodeMaterialBlockConnectionPointMode.Uniform : NodeMaterialBlockConnectionPointMode.Undefined;
  228. this.associatedVariableName = "";
  229. }
  230. /**
  231. * Gets or sets a boolean indicating that this connection point is coming from an attribute.
  232. * In this case the connection point name must be the name of the attribute to use
  233. * Can only be set on inputs
  234. */
  235. public get isAttribute(): boolean {
  236. return this._mode === NodeMaterialBlockConnectionPointMode.Attribute;
  237. }
  238. public set isAttribute(value: boolean) {
  239. this._mode = value ? NodeMaterialBlockConnectionPointMode.Attribute : NodeMaterialBlockConnectionPointMode.Undefined;
  240. this.associatedVariableName = "";
  241. }
  242. /**
  243. * Gets or sets a boolean indicating that this connection point is generating a varying variable.
  244. * Can only be set on exit points
  245. */
  246. public get isVarying(): boolean {
  247. return this._mode === NodeMaterialBlockConnectionPointMode.Varying;
  248. }
  249. public set isVarying(value: boolean) {
  250. this._mode = value ? NodeMaterialBlockConnectionPointMode.Varying : NodeMaterialBlockConnectionPointMode.Undefined;
  251. this.associatedVariableName = "";
  252. }
  253. /**
  254. * Gets a boolean indicating that the current connection point is a system value
  255. */
  256. public get isSystemValue(): boolean {
  257. return this._systemValue != null;
  258. }
  259. /**
  260. * Gets or sets the current well known value or null if not defined as a system value
  261. */
  262. public get systemValue(): Nullable<NodeMaterialSystemValues> {
  263. return this._systemValue;
  264. }
  265. public set systemValue(value: Nullable<NodeMaterialSystemValues>) {
  266. this._mode = NodeMaterialBlockConnectionPointMode.Uniform;
  267. this.associatedVariableName = "";
  268. this._systemValue = value;
  269. }
  270. /**
  271. * Gets the current class name
  272. * @returns the class name
  273. */
  274. public getClassName() {
  275. return "InputBlock";
  276. }
  277. /**
  278. * Animate the input if animationType !== None
  279. * @param scene defines the rendering scene
  280. */
  281. public animate(scene: Scene) {
  282. switch (this._animationType) {
  283. case AnimatedInputBlockTypes.Time: {
  284. if (this.type === NodeMaterialBlockConnectionPointTypes.Float) {
  285. this.value += scene.getAnimationRatio() * 0.01;
  286. }
  287. break;
  288. }
  289. }
  290. }
  291. private _emitDefine(define: string): string {
  292. if (define[0] === "!") {
  293. return `#ifndef ${define.substring(1)}\r\n`;
  294. }
  295. return `#ifdef ${define}\r\n`;
  296. }
  297. public initialize(state: NodeMaterialBuildState) {
  298. this.associatedVariableName = "";
  299. }
  300. /**
  301. * Set the input block to its default value (based on its type)
  302. */
  303. public setDefaultValue() {
  304. switch (this.type) {
  305. case NodeMaterialBlockConnectionPointTypes.Float:
  306. this.value = 0;
  307. break;
  308. case NodeMaterialBlockConnectionPointTypes.Vector2:
  309. this.value = Vector2.Zero();
  310. break;
  311. case NodeMaterialBlockConnectionPointTypes.Vector3:
  312. this.value = Vector3.Zero();
  313. break;
  314. case NodeMaterialBlockConnectionPointTypes.Vector4:
  315. this.value = Vector4.Zero();
  316. break;
  317. case NodeMaterialBlockConnectionPointTypes.Color3:
  318. this.value = Color3.White();
  319. break;
  320. case NodeMaterialBlockConnectionPointTypes.Color4:
  321. this.value = new Color4(1, 1, 1, 1);
  322. break;
  323. case NodeMaterialBlockConnectionPointTypes.Matrix:
  324. this.value = Matrix.Identity();
  325. break;
  326. }
  327. }
  328. private _emitConstant(state: NodeMaterialBuildState) {
  329. switch (this.type) {
  330. case NodeMaterialBlockConnectionPointTypes.Float:
  331. return `${state._emitFloat(this.value)}`;
  332. case NodeMaterialBlockConnectionPointTypes.Vector2:
  333. return `vec2(${this.value.x}, ${this.value.y})`;
  334. case NodeMaterialBlockConnectionPointTypes.Vector3:
  335. return `vec3(${this.value.x}, ${this.value.y}, ${this.value.z})`;
  336. case NodeMaterialBlockConnectionPointTypes.Vector4:
  337. return `vec4(${this.value.x}, ${this.value.y}, ${this.value.z}, ${this.value.w})`;
  338. case NodeMaterialBlockConnectionPointTypes.Color3:
  339. return `vec3(${this.value.r}, ${this.value.g}, ${this.value.b})`;
  340. case NodeMaterialBlockConnectionPointTypes.Color4:
  341. return `vec4(${this.value.r}, ${this.value.g}, ${this.value.b}, ${this.value.a})`;
  342. }
  343. return "";
  344. }
  345. private _emit(state: NodeMaterialBuildState, define?: string) {
  346. // Uniforms
  347. if (this.isUniform) {
  348. if (!this.associatedVariableName) {
  349. this.associatedVariableName = state._getFreeVariableName("u_" + this.name);
  350. }
  351. if (this.isConstant) {
  352. if (state.constants.indexOf(this.associatedVariableName) !== -1) {
  353. return;
  354. }
  355. state.constants.push(this.associatedVariableName);
  356. state._constantDeclaration += this._declareOutput(this.output, state) + ` = ${this._emitConstant(state)};\r\n`;
  357. return;
  358. }
  359. if (state.uniforms.indexOf(this.associatedVariableName) !== -1) {
  360. return;
  361. }
  362. state.uniforms.push(this.associatedVariableName);
  363. if (define) {
  364. state._uniformDeclaration += this._emitDefine(define);
  365. }
  366. state._uniformDeclaration += `uniform ${state._getGLType(this.type)} ${this.associatedVariableName};\r\n`;
  367. if (define) {
  368. state._uniformDeclaration += `#endif\r\n`;
  369. }
  370. // well known
  371. let hints = state.sharedData.hints;
  372. if (this._systemValue !== null && this._systemValue !== undefined) {
  373. switch (this._systemValue) {
  374. case NodeMaterialSystemValues.WorldView:
  375. hints.needWorldViewMatrix = true;
  376. break;
  377. case NodeMaterialSystemValues.WorldViewProjection:
  378. hints.needWorldViewProjectionMatrix = true;
  379. break;
  380. }
  381. } else {
  382. if (this._animationType !== AnimatedInputBlockTypes.None) {
  383. state.sharedData.animatedInputs.push(this);
  384. }
  385. }
  386. return;
  387. }
  388. // Attribute
  389. if (this.isAttribute) {
  390. this.associatedVariableName = this.name === 'position2d' ? 'position' : this.name;
  391. if (this.target === NodeMaterialBlockTargets.Vertex && state._vertexState) { // Attribute for fragment need to be carried over by varyings
  392. this._emit(state._vertexState, define);
  393. return;
  394. }
  395. if (state.attributes.indexOf(this.associatedVariableName) !== -1) {
  396. return;
  397. }
  398. state.attributes.push(this.associatedVariableName);
  399. if (define) {
  400. state._attributeDeclaration += this._emitDefine(define);
  401. }
  402. state._attributeDeclaration += `attribute ${state._getGLType(this.type)} ${this.associatedVariableName};\r\n`;
  403. if (define) {
  404. state._attributeDeclaration += `#endif\r\n`;
  405. }
  406. }
  407. }
  408. /** @hidden */
  409. public _transmitWorld(effect: Effect, world: Matrix, worldView: Matrix, worldViewProjection: Matrix) {
  410. if (!this._systemValue) {
  411. return;
  412. }
  413. let variableName = this.associatedVariableName;
  414. switch (this._systemValue) {
  415. case NodeMaterialSystemValues.World:
  416. effect.setMatrix(variableName, world);
  417. break;
  418. case NodeMaterialSystemValues.WorldView:
  419. effect.setMatrix(variableName, worldView);
  420. break;
  421. case NodeMaterialSystemValues.WorldViewProjection:
  422. effect.setMatrix(variableName, worldViewProjection);
  423. break;
  424. }
  425. }
  426. /** @hidden */
  427. public _transmit(effect: Effect, scene: Scene) {
  428. if (this.isAttribute) {
  429. return;
  430. }
  431. let variableName = this.associatedVariableName;
  432. if (this._systemValue) {
  433. switch (this._systemValue) {
  434. case NodeMaterialSystemValues.World:
  435. case NodeMaterialSystemValues.WorldView:
  436. case NodeMaterialSystemValues.WorldViewProjection:
  437. return;
  438. case NodeMaterialSystemValues.View:
  439. effect.setMatrix(variableName, scene.getViewMatrix());
  440. break;
  441. case NodeMaterialSystemValues.Projection:
  442. effect.setMatrix(variableName, scene.getProjectionMatrix());
  443. break;
  444. case NodeMaterialSystemValues.ViewProjection:
  445. effect.setMatrix(variableName, scene.getTransformMatrix());
  446. break;
  447. case NodeMaterialSystemValues.CameraPosition:
  448. MaterialHelper.BindEyePosition(effect, scene, variableName);
  449. break;
  450. case NodeMaterialSystemValues.FogColor:
  451. effect.setColor3(variableName, scene.fogColor);
  452. break;
  453. case NodeMaterialSystemValues.DeltaTime:
  454. effect.setFloat(variableName, scene.deltaTime / 1000.0);
  455. }
  456. return;
  457. }
  458. let value = this._valueCallback ? this._valueCallback() : this._storedValue;
  459. if (value === null) {
  460. return;
  461. }
  462. switch (this.type) {
  463. case NodeMaterialBlockConnectionPointTypes.Float:
  464. effect.setFloat(variableName, value);
  465. break;
  466. case NodeMaterialBlockConnectionPointTypes.Int:
  467. effect.setInt(variableName, value);
  468. break;
  469. case NodeMaterialBlockConnectionPointTypes.Color3:
  470. effect.setColor3(variableName, value);
  471. break;
  472. case NodeMaterialBlockConnectionPointTypes.Color4:
  473. effect.setDirectColor4(variableName, value);
  474. break;
  475. case NodeMaterialBlockConnectionPointTypes.Vector2:
  476. effect.setVector2(variableName, value);
  477. break;
  478. case NodeMaterialBlockConnectionPointTypes.Vector3:
  479. effect.setVector3(variableName, value);
  480. break;
  481. case NodeMaterialBlockConnectionPointTypes.Vector4:
  482. effect.setVector4(variableName, value);
  483. break;
  484. case NodeMaterialBlockConnectionPointTypes.Matrix:
  485. effect.setMatrix(variableName, value);
  486. break;
  487. }
  488. }
  489. protected _buildBlock(state: NodeMaterialBuildState) {
  490. super._buildBlock(state);
  491. if (this.isUniform || this.isSystemValue) {
  492. state.sharedData.inputBlocks.push(this);
  493. }
  494. this._emit(state);
  495. }
  496. protected _dumpPropertiesCode() {
  497. let variableName = this._codeVariableName;
  498. if (this.isAttribute) {
  499. return `${variableName}.setAsAttribute("${this.name}");\r\n`;
  500. }
  501. if (this.isSystemValue) {
  502. return `${variableName}.setAsSystemValue(BABYLON.NodeMaterialSystemValues.${NodeMaterialSystemValues[this._systemValue!]});\r\n`;
  503. }
  504. if (this.isUniform) {
  505. const codes: string[] = [];
  506. let valueString = "";
  507. switch (this.type) {
  508. case NodeMaterialBlockConnectionPointTypes.Float:
  509. valueString = `${this.value}`;
  510. break;
  511. case NodeMaterialBlockConnectionPointTypes.Vector2:
  512. valueString = `new BABYLON.Vector2(${this.value.x}, ${this.value.y})`;
  513. break;
  514. case NodeMaterialBlockConnectionPointTypes.Vector3:
  515. valueString = `new BABYLON.Vector3(${this.value.x}, ${this.value.y}, ${this.value.z})`;
  516. break;
  517. case NodeMaterialBlockConnectionPointTypes.Vector4:
  518. valueString = `new BABYLON.Vector4(${this.value.x}, ${this.value.y}, ${this.value.z}, ${this.value.w})`;
  519. break;
  520. case NodeMaterialBlockConnectionPointTypes.Color3:
  521. valueString = `new BABYLON.Color3(${this.value.r}, ${this.value.g}, ${this.value.b})`;
  522. break;
  523. case NodeMaterialBlockConnectionPointTypes.Color4:
  524. valueString = `new BABYLON.Color4(${this.value.r}, ${this.value.g}, ${this.value.b}, ${this.value.a})`;
  525. break;
  526. case NodeMaterialBlockConnectionPointTypes.Matrix:
  527. valueString = `BABYLON.Matrix.FromArray([${(this.value as Matrix).m}])`;
  528. break;
  529. }
  530. // Common Property "Value"
  531. codes.push(`${variableName}.value = ${valueString}`);
  532. // Float-Value-Specific Properties
  533. if (this.type === NodeMaterialBlockConnectionPointTypes.Float) {
  534. codes.push(
  535. `${variableName}.min = ${this.min}`,
  536. `${variableName}.max = ${this.max}`,
  537. `${variableName}.isBoolean = ${this.isBoolean}`,
  538. `${variableName}.matrixMode = ${this.matrixMode}`,
  539. `${variableName}.animationType = BABYLON.AnimatedInputBlockTypes.${AnimatedInputBlockTypes[this.animationType]}`
  540. );
  541. }
  542. // Common Property "Type"
  543. codes.push(
  544. `${variableName}.isConstant = ${this.isConstant}`,
  545. `${variableName}.visibleInInspector = ${this.visibleInInspector}`
  546. );
  547. codes.push('');
  548. return codes.join(';\r\n');
  549. }
  550. return "";
  551. }
  552. public dispose() {
  553. this.onValueChangedObservable.clear();
  554. super.dispose();
  555. }
  556. public serialize(): any {
  557. let serializationObject = super.serialize();
  558. serializationObject.type = this.type;
  559. serializationObject.mode = this._mode;
  560. serializationObject.systemValue = this._systemValue;
  561. serializationObject.animationType = this._animationType;
  562. serializationObject.visibleInInspector = this.visibleInInspector;
  563. serializationObject.min = this.min;
  564. serializationObject.max = this.max;
  565. serializationObject.isBoolean = this.isBoolean;
  566. serializationObject.matrixMode = this.matrixMode;
  567. serializationObject.isConstant = this.isConstant;
  568. serializationObject.groupInInspector = this.groupInInspector;
  569. if (this._storedValue != null && this._mode === NodeMaterialBlockConnectionPointMode.Uniform) {
  570. if (this._storedValue.asArray) {
  571. serializationObject.valueType = "BABYLON." + this._storedValue.getClassName();
  572. serializationObject.value = this._storedValue.asArray();
  573. } else {
  574. serializationObject.valueType = "number";
  575. serializationObject.value = this._storedValue;
  576. }
  577. }
  578. return serializationObject;
  579. }
  580. public _deserialize(serializationObject: any, scene: Scene, rootUrl: string) {
  581. super._deserialize(serializationObject, scene, rootUrl);
  582. this._type = serializationObject.type;
  583. this._mode = serializationObject.mode;
  584. this._systemValue = serializationObject.systemValue || serializationObject.wellKnownValue;
  585. this._animationType = serializationObject.animationType;
  586. this.visibleInInspector = serializationObject.visibleInInspector;
  587. this.min = serializationObject.min || 0;
  588. this.max = serializationObject.max || 0;
  589. this.isBoolean = !!serializationObject.isBoolean;
  590. this.matrixMode = serializationObject.matrixMode || 0;
  591. this.isConstant = !!serializationObject.isConstant;
  592. this.groupInInspector = serializationObject.groupInInspector || "";
  593. if (!serializationObject.valueType) {
  594. return;
  595. }
  596. if (serializationObject.valueType === "number") {
  597. this._storedValue = serializationObject.value;
  598. } else {
  599. let valueType = _TypeStore.GetClass(serializationObject.valueType);
  600. if (valueType) {
  601. this._storedValue = valueType.FromArray(serializationObject.value);
  602. }
  603. }
  604. }
  605. }
  606. _TypeStore.RegisteredTypes["BABYLON.InputBlock"] = InputBlock;