texture-cube.js 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. 'use strict';
  2. const { updateElementReadonly, updateElementInvalid } = require('../utils/assets');
  3. const { injectionStyle } = require('../utils/prop');
  4. const path = require('path');
  5. const Direction = {
  6. left: 'left ( -X )',
  7. right: 'right ( +X )',
  8. top: 'top ( +Y )',
  9. bottom: 'bottom ( -Y )',
  10. front: 'front ( +Z )',
  11. back: 'back ( -Z )',
  12. };
  13. exports.template = /* html */`
  14. <section class="asset-texture-cube">
  15. <div class="assets"></div>
  16. <div class="preview">
  17. <div class="images"></div>
  18. </div>
  19. <ui-panel class="panel"></ui-panel>
  20. </section>
  21. `;
  22. exports.style = /* css */`
  23. .asset-texture-cube > .assets {
  24. padding-right: 4px;
  25. }
  26. .asset-texture-cube > .preview {
  27. padding: 20px;
  28. }
  29. .asset-texture-cube > .preview > .images {
  30. position: relative;
  31. width: calc(var(--size) * 4);
  32. height: calc(var(--size) * 3);
  33. }
  34. .asset-texture-cube > .preview > .images > ui-drag-item > ui-image {
  35. position: absolute;
  36. line-height: var(--size);
  37. width: var(--size);
  38. height: var(--size);
  39. background-color: var(--color-normal-fill-emphasis);
  40. text-align: center;
  41. }
  42. .asset-texture-cube > .preview > .images > ui-drag-item > .top {
  43. top: 0;
  44. left: calc(var(--size) * 2);
  45. }
  46. .asset-texture-cube > .preview > .images > ui-drag-item > .bottom {
  47. top: calc(var(--size) * 2);
  48. left: calc(var(--size) * 2);
  49. }
  50. .asset-texture-cube > .preview > .images > ui-drag-item > .front {
  51. top: var(--size);
  52. left: calc(var(--size) * 2);
  53. }
  54. .asset-texture-cube > .preview > .images > ui-drag-item > .back {
  55. top: var(--size);
  56. left: 0;
  57. }
  58. .asset-texture-cube > .preview > .images > ui-drag-item > .left {
  59. top: var(--size);
  60. left: var(--size);
  61. }
  62. .asset-texture-cube > .preview > .images > ui-drag-item > .right {
  63. top: var(--size);
  64. left: calc(var(--size) * 3);
  65. }
  66. .asset-texture-cube > .panel {
  67. display: block;
  68. margin-top: 10px;
  69. }
  70. `;
  71. exports.$ = {
  72. container: '.asset-texture-cube',
  73. assets: '.assets',
  74. images: '.images',
  75. panel: '.panel',
  76. };
  77. const Elements = {
  78. assets: {
  79. ready() {
  80. const panel = this;
  81. for (const key in Direction) {
  82. const prop = document.createElement('ui-prop');
  83. panel.$.assets.appendChild(prop);
  84. prop.setAttribute('ui', 'asset');
  85. const label = document.createElement('ui-label');
  86. prop.appendChild(label);
  87. label.setAttribute('slot', 'label');
  88. label.setAttribute('value', Direction[key]);
  89. const asset = document.createElement('ui-asset');
  90. prop.appendChild(asset);
  91. asset.setAttribute('slot', 'content');
  92. asset.setAttribute('droppable', 'cc.ImageAsset');
  93. asset.addEventListener('confirm', panel.change.bind(panel, key));
  94. panel.$[`${key}-asset`] = asset;
  95. }
  96. },
  97. update() {
  98. const panel = this;
  99. for (const key in Direction) {
  100. panel.$[`${key}-asset`].value = panel.meta.userData[key] || '';
  101. updateElementInvalid.call(panel, panel.$[`${key}-asset`], key);
  102. updateElementReadonly.call(panel, panel.$[`${key}-asset`]);
  103. }
  104. },
  105. },
  106. images: {
  107. ready() {
  108. const panel = this;
  109. for (const key in Direction) {
  110. const dragItem = document.createElement('ui-drag-item');
  111. dragItem.setAttribute('type', 'cc.ImageAsset');
  112. dragItem.addEventListener('dragstart', panel.dragStart.bind(panel, key));
  113. const image = document.createElement('ui-image');
  114. dragItem.appendChild(image);
  115. panel.$.images.appendChild(dragItem);
  116. image.setAttribute('class', key);
  117. image.setAttribute('droppable', 'cc.ImageAsset');
  118. image.setAttribute('class', key);
  119. image.setAttribute('placeholder', key);
  120. image.setAttribute('show-alpha', '');
  121. image.setAttribute('fill', '');
  122. image.addEventListener('confirm', panel.change.bind(panel, key));
  123. panel.$[`${key}-drag-item`] = dragItem;
  124. panel.$[`${key}-image`] = image;
  125. }
  126. function observer() {
  127. cancelAnimationFrame(panel.animationFrameId);
  128. panel.animationFrameId = window.requestAnimationFrame(() => {
  129. const { clientWidth } = panel.$.container;
  130. const size = Math.round((clientWidth - 40) / 4);
  131. // 16 is fault tolerance to avoid page scrollbar flickering
  132. if (Math.abs((panel.cachePrevWidth || 0) - clientWidth) > 16) {
  133. panel.cachePrevWidth = clientWidth;
  134. panel.$.container.style.setProperty('--size', `${size}px`);
  135. }
  136. });
  137. }
  138. panel.resizeObserver = new window.ResizeObserver(observer);
  139. panel.resizeObserver.observe(panel.$.container);
  140. observer();
  141. },
  142. update() {
  143. const panel = this;
  144. for (const key in Direction) {
  145. const value = panel.meta.userData[key] || '';
  146. panel.$[`${key}-drag-item`].setAttribute(
  147. 'additional',
  148. JSON.stringify([
  149. {
  150. type: 'cc.ImageAsset',
  151. value,
  152. },
  153. ]),
  154. );
  155. updateElementInvalid.call(panel, panel.$[`${key}-drag-item`], key);
  156. updateElementReadonly.call(panel, panel.$[`${key}-drag-item`]);
  157. panel.$[`${key}-image`].value = value;
  158. updateElementInvalid.call(panel, panel.$[`${key}-image`], key);
  159. updateElementReadonly.call(panel, panel.$[`${key}-image`]);
  160. }
  161. },
  162. close() {
  163. const panel = this;
  164. panel.resizeObserver.unobserve(panel.$.container);
  165. },
  166. },
  167. panel: {
  168. ready() {
  169. this.$.panel.setAttribute('src', path.join(__dirname, './erp-texture-cube.js'));
  170. this.$.panel.injectionStyle(injectionStyle);
  171. this.$.panel.addEventListener('change', () => {
  172. this.dispatch('change');
  173. });
  174. this.$.panel.addEventListener('snapshot', () => {
  175. this.dispatch('snapshot');
  176. });
  177. },
  178. update() {
  179. this.$.panel.update(this.assetList, this.metaList);
  180. },
  181. },
  182. };
  183. exports.methods = {
  184. change(key, event) {
  185. this.metaList.forEach((meta) => {
  186. if (this.dragStart.exchange && this.dragStart.exchange.value) {
  187. const exchangeValue = meta.userData[key] || '';
  188. meta.userData[this.dragStart.exchange.key] = exchangeValue;
  189. }
  190. meta.userData[key] = event.target.value || undefined;
  191. });
  192. this.dispatch('change');
  193. this.dispatch('snapshot');
  194. Elements.assets.update.call(this);
  195. Elements.images.update.call(this);
  196. },
  197. dragStart(key, event) {
  198. const additional = JSON.parse(event.currentTarget.getAttribute('additional'));
  199. this.dragStart.exchange = additional[0];
  200. this.dragStart.exchange.key = key;
  201. },
  202. };
  203. exports.ready = function() {
  204. for (const prop in Elements) {
  205. const element = Elements[prop];
  206. if (element.ready) {
  207. element.ready.call(this);
  208. }
  209. }
  210. };
  211. exports.update = function(assetList, metaList) {
  212. this.assetList = assetList;
  213. this.metaList = metaList;
  214. this.asset = assetList[0];
  215. this.meta = metaList[0];
  216. for (const prop in Elements) {
  217. const element = Elements[prop];
  218. if (element.update) {
  219. element.update.call(this);
  220. }
  221. }
  222. };
  223. exports.close = function() {
  224. for (const prop in Elements) {
  225. const element = Elements[prop];
  226. if (element.close) {
  227. element.close.call(this);
  228. }
  229. }
  230. };