ScriptableValueNode.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. import Node, { addNodeClass } from '../core/Node.js';
  2. import { arrayBufferToBase64, base64ToArrayBuffer } from '../core/NodeUtils.js';
  3. import { addNodeElement, nodeProxy, float } from '../shadernode/ShaderNode.js';
  4. import { EventDispatcher } from 'three';
  5. class ScriptableValueNode extends Node {
  6. constructor( value = null ) {
  7. super();
  8. this._value = value;
  9. this._cache = null;
  10. this.inputType = null;
  11. this.outpuType = null;
  12. this.events = new EventDispatcher();
  13. this.isScriptableValueNode = true;
  14. }
  15. get isScriptableOutputNode() {
  16. return this.outputType !== null;
  17. }
  18. set value( val ) {
  19. if ( this._value === val ) return;
  20. if ( this._cache && this.inputType === 'URL' && this.value.value instanceof ArrayBuffer ) {
  21. URL.revokeObjectURL( this._cache );
  22. this._cache = null;
  23. }
  24. this._value = val;
  25. this.events.dispatchEvent( { type: 'change' } );
  26. this.refresh();
  27. }
  28. get value() {
  29. return this._value;
  30. }
  31. refresh() {
  32. this.events.dispatchEvent( { type: 'refresh' } );
  33. }
  34. getValue() {
  35. const value = this.value;
  36. if ( value && this._cache === null && this.inputType === 'URL' && value.value instanceof ArrayBuffer ) {
  37. this._cache = URL.createObjectURL( new Blob( [ value.value ] ) );
  38. } else if ( value && value.value !== null && value.value !== undefined && (
  39. ( ( this.inputType === 'URL' || this.inputType === 'String' ) && typeof value.value === 'string' ) ||
  40. ( this.inputType === 'Number' && typeof value.value === 'number' ) ||
  41. ( this.inputType === 'Vector2' && value.value.isVector2 ) ||
  42. ( this.inputType === 'Vector3' && value.value.isVector3 ) ||
  43. ( this.inputType === 'Vector4' && value.value.isVector4 ) ||
  44. ( this.inputType === 'Color' && value.value.isColor ) ||
  45. ( this.inputType === 'Matrix3' && value.value.isMatrix3 ) ||
  46. ( this.inputType === 'Matrix4' && value.value.isMatrix4 )
  47. ) ) {
  48. return value.value;
  49. }
  50. return this._cache || value;
  51. }
  52. getNodeType( builder ) {
  53. return this.value && this.value.isNode ? this.value.getNodeType( builder ) : 'float';
  54. }
  55. setup() {
  56. return this.value && this.value.isNode ? this.value : float();
  57. }
  58. serialize( data ) {
  59. super.serialize( data );
  60. if ( this.value !== null ) {
  61. if ( this.inputType === 'ArrayBuffer' ) {
  62. data.value = arrayBufferToBase64( this.value );
  63. } else {
  64. data.value = this.value ? this.value.toJSON( data.meta ).uuid : null;
  65. }
  66. } else {
  67. data.value = null;
  68. }
  69. data.inputType = this.inputType;
  70. data.outputType = this.outputType;
  71. }
  72. deserialize( data ) {
  73. super.deserialize( data );
  74. let value = null;
  75. if ( data.value !== null ) {
  76. if ( data.inputType === 'ArrayBuffer' ) {
  77. value = base64ToArrayBuffer( data.value );
  78. } else if ( data.inputType === 'Texture' ) {
  79. value = data.meta.textures[ data.value ];
  80. } else {
  81. value = data.meta.nodes[ data.value ] || null;
  82. }
  83. }
  84. this.value = value;
  85. this.inputType = data.inputType;
  86. this.outputType = data.outputType;
  87. }
  88. }
  89. export default ScriptableValueNode;
  90. export const scriptableValue = nodeProxy( ScriptableValueNode );
  91. addNodeElement( 'scriptableValue', scriptableValue );
  92. addNodeClass( ScriptableValueNode );