particle-system-2d.js 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. const { template, $, update, close } = require('./base');
  2. const { getMessageProtocolScene } = require('../utils/prop');
  3. // 排列时,相邻元素的间隔间距
  4. const MARGIN = '4px';
  5. exports.template = template;
  6. exports.$ = $;
  7. exports.update = update;
  8. exports.close = close;
  9. const { setHidden, setDisabled, isMultipleInvalid } = require('../utils/prop');
  10. exports.ready = function() {
  11. // Handling in-line displayed attributes
  12. const needToInlines = [
  13. 'life',
  14. 'startColor',
  15. 'endColor',
  16. 'angle',
  17. 'startSize',
  18. 'endSize',
  19. 'startSpin',
  20. 'endSpin',
  21. 'speed',
  22. 'tangentialAccel',
  23. 'radialAccel',
  24. 'startRadius',
  25. 'endRadius',
  26. 'rotatePerS',
  27. ];
  28. this.elements = {
  29. file: {
  30. update(element, dump) {
  31. setDisabled(!dump.file.value.uuid, this.$.syncButton);
  32. },
  33. },
  34. custom: {
  35. ready(element) {
  36. const $checkbox = element.querySelector('ui-checkbox[slot="content"]');
  37. const $sync = document.createElement('ui-button');
  38. $sync.setAttribute('style', `margin-right: ${MARGIN}`);
  39. $sync.setAttribute('slot', 'content');
  40. $sync.setAttribute('class', 'blue');
  41. $sync.setAttribute('tooltip', 'i18n:ENGINE.components.particle_system_2d.sync_tips');
  42. const $syncLabel = document.createElement('ui-label');
  43. $syncLabel.setAttribute('value', 'i18n:ENGINE.components.particle_system_2d.sync');
  44. $sync.appendChild($syncLabel);
  45. $checkbox.after($sync);
  46. // Hack: ui-button has extra events that are passed up to ui-prop ;
  47. $sync.addEventListener('change', (event) => {
  48. event.stopPropagation();
  49. });
  50. $sync.addEventListener('confirm', async (event) => {
  51. event.stopPropagation();
  52. const fileUuid = this.dump.value.file.value.uuid;
  53. const fileInfo = await Editor.Message.request('asset-db', 'query-asset-meta', fileUuid);
  54. if (fileInfo) {
  55. let values = [this.$this.dump.value];
  56. if (this.$this.dump.values) {
  57. values = this.$this.dump.values;
  58. }
  59. for (const item of values) {
  60. item.file.value.uuid = fileUuid;
  61. item.custom.value = true;
  62. /**
  63. * TODO Hack: a serious problem
  64. * The data with underscores is also involved in setting in the engine.
  65. * but it's visible = false, and it's impossible to assert the file and _file association from the name.
  66. * easily ignored when data changes
  67. * There is a place under the same
  68. */
  69. item._file.value.uuid = fileUuid;
  70. item._custom.value = true;
  71. for (const key in fileInfo.userData) {
  72. const value = fileInfo.userData[key];
  73. if (key === 'spriteFrameUuid') {
  74. item.spriteFrame.value.uuid = value;
  75. } else if (item[key] !== undefined) {
  76. item[key].value = value;
  77. }
  78. }
  79. }
  80. this.$this.dispatch('change-dump');
  81. this.$this.dispatch('confirm-dump');
  82. }
  83. });
  84. const $export = document.createElement('ui-button');
  85. $export.setAttribute('slot', 'content');
  86. $export.setAttribute('class', 'blue');
  87. $export.setAttribute('tooltip', 'i18n:ENGINE.components.particle_system_2d.export_tips');
  88. const $exportLabel = document.createElement('ui-label');
  89. $exportLabel.setAttribute('value', 'i18n:ENGINE.components.particle_system_2d.export');
  90. $export.appendChild($exportLabel);
  91. $sync.after($export);
  92. $export.addEventListener('change', (event) => {
  93. event.stopPropagation();
  94. });
  95. $export.addEventListener('confirm', async (event) => {
  96. event.stopPropagation();
  97. let assetInfo = await Editor.Message.request(getMessageProtocolScene(this.$this), 'export-particle-plist', this.dump.value.uuid.value);
  98. if (assetInfo) {
  99. let values = [this.$this.dump.value];
  100. if (this.$this.dump.values) {
  101. values = this.$this.dump.values;
  102. }
  103. for (const item of values) {
  104. item.file.value.uuid = assetInfo.uuid;
  105. item.custom.value = false;
  106. // Same instructions as above
  107. item._file.value.uuid = assetInfo.uuid;
  108. item._custom.value = false;
  109. }
  110. this.$this.dispatch('change-dump');
  111. this.$this.dispatch('confirm-dump');
  112. }
  113. });
  114. this.$.syncButton = $sync;
  115. this.$.exportButton = $export;
  116. },
  117. update(element, dump) {
  118. const existKeys = ['customMaterial', 'color', 'preview', 'playOnLoad', 'autoRemoveOnFinish', 'file', 'custom'];
  119. const toggleProps = [];
  120. for (const name in this.dump.value) {
  121. if (this.dump.value[name].visible && !existKeys.includes(name)) {
  122. toggleProps.push(name);
  123. }
  124. }
  125. const toggleElements = ['syncButton', 'exportButton'];
  126. const toggleKeys = toggleProps.concat(toggleElements);
  127. const isMultiple = dump.custom && !!dump.custom.values;
  128. setDisabled(isMultiple, this.$.exportButton);
  129. const hidden = isMultipleInvalid(dump.custom) || !dump.custom.value;
  130. toggleKeys.forEach((key) => {
  131. setHidden(hidden, this.$[key]);
  132. });
  133. needToInlines.forEach((key) => {
  134. const $left = this.$[key];
  135. const $right = this.$[`${key}Var`];
  136. if ($right && $right.parentNode === $left) {
  137. return;
  138. }
  139. $right.setAttribute('no-label', '');
  140. $right.setAttribute('slot', 'content');
  141. $right.setAttribute('style', `margin-left: ${MARGIN}`);
  142. $left.appendChild($right);
  143. });
  144. },
  145. },
  146. emitterMode: {
  147. update(element, dump) {
  148. if (isMultipleInvalid(dump.custom) || !dump.custom.value) {
  149. return;
  150. }
  151. // when dump.emitterMode.value === 0
  152. let shows = ['gravity', 'speed', 'tangentialAccel', 'radialAccel', 'rotationIsDir'];
  153. let hiddens = ['startRadius', 'endRadius', 'rotatePerS'];
  154. if (dump.emitterMode.value === 1) {
  155. const temp = hiddens;
  156. hiddens = shows;
  157. shows = temp;
  158. }
  159. shows.forEach((key) => setHidden(false, this.$[key]));
  160. hiddens.forEach((key) => setHidden(true, this.$[key]));
  161. },
  162. },
  163. };
  164. needToInlines.forEach((key) => {
  165. const rightKey = `${key}Var`;
  166. this.elements[rightKey] = {
  167. isAppendToParent() {
  168. const $left = this.$[key];
  169. const $right = this.$[`${key}Var`];
  170. if ($left && $right && $right.parentNode === $left) {
  171. return false;
  172. }
  173. return true;
  174. },
  175. };
  176. });
  177. };