@pixi-ui-editor/runtime-pixi 0.14.0 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/README.md +27 -6
  2. package/dist/SceneViewport.d.ts +5 -1
  3. package/dist/SceneViewport.d.ts.map +1 -1
  4. package/dist/SceneViewport.js +13 -3
  5. package/dist/SceneViewport.js.map +1 -1
  6. package/dist/assets/bitmapFonts.d.ts +2 -0
  7. package/dist/assets/bitmapFonts.d.ts.map +1 -1
  8. package/dist/assets/bitmapFonts.js +3 -1
  9. package/dist/assets/bitmapFonts.js.map +1 -1
  10. package/dist/assets/sounds.d.ts +1 -7
  11. package/dist/assets/sounds.d.ts.map +1 -1
  12. package/dist/assets/sounds.js +7 -90
  13. package/dist/assets/sounds.js.map +1 -1
  14. package/dist/assets/textures.d.ts +10 -0
  15. package/dist/assets/textures.d.ts.map +1 -1
  16. package/dist/assets/textures.js +10 -2
  17. package/dist/assets/textures.js.map +1 -1
  18. package/dist/audio/bus.d.ts +60 -0
  19. package/dist/audio/bus.d.ts.map +1 -0
  20. package/dist/audio/bus.js +38 -0
  21. package/dist/audio/bus.js.map +1 -0
  22. package/dist/audio/director.d.ts +35 -0
  23. package/dist/audio/director.d.ts.map +1 -0
  24. package/dist/audio/director.js +137 -0
  25. package/dist/audio/director.js.map +1 -0
  26. package/dist/controls.js.map +1 -1
  27. package/dist/index.d.ts +4 -1
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +4 -1
  30. package/dist/index.js.map +1 -1
  31. package/dist/layout.d.ts +19 -3
  32. package/dist/layout.d.ts.map +1 -1
  33. package/dist/layout.js +34 -4
  34. package/dist/layout.js.map +1 -1
  35. package/dist/particles.js.map +1 -1
  36. package/dist/scene.d.ts +13 -2
  37. package/dist/scene.d.ts.map +1 -1
  38. package/dist/scene.js +79 -3
  39. package/dist/scene.js.map +1 -1
  40. package/dist/transformSpace.d.ts +119 -0
  41. package/dist/transformSpace.d.ts.map +1 -0
  42. package/dist/transformSpace.js +487 -0
  43. package/dist/transformSpace.js.map +1 -0
  44. package/dist/views/ButtonNodeView.d.ts +4 -3
  45. package/dist/views/ButtonNodeView.d.ts.map +1 -1
  46. package/dist/views/ButtonNodeView.js +9 -8
  47. package/dist/views/ButtonNodeView.js.map +1 -1
  48. package/dist/views/CheckboxNodeView.d.ts +4 -3
  49. package/dist/views/CheckboxNodeView.d.ts.map +1 -1
  50. package/dist/views/CheckboxNodeView.js +7 -7
  51. package/dist/views/CheckboxNodeView.js.map +1 -1
  52. package/dist/views/ItemTableNodeView.js.map +1 -1
  53. package/dist/views/PaginationNodeView.js.map +1 -1
  54. package/dist/views/ParticleEmitterNodeView.js.map +1 -1
  55. package/dist/views/StagedButtonNodeView.d.ts +4 -3
  56. package/dist/views/StagedButtonNodeView.d.ts.map +1 -1
  57. package/dist/views/StagedButtonNodeView.js +7 -9
  58. package/dist/views/StagedButtonNodeView.js.map +1 -1
  59. package/dist/views/basic.js.map +1 -1
  60. package/dist/views/createNodeView.d.ts +2 -2
  61. package/dist/views/createNodeView.d.ts.map +1 -1
  62. package/dist/views/createNodeView.js +4 -4
  63. package/dist/views/createNodeView.js.map +1 -1
  64. package/package.json +2 -2
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transformSpace.js","sourceRoot":"","sources":["../src/transformSpace.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,0BAA0B,GAK3B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,wBAAwB,EAAE,uBAAuB,EAAmB,MAAM,aAAa,CAAC;AACvI,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AA0BpD,wFAAwF;AACxF,MAAM,CAAC,MAAM,qBAAqB,GAAe,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;AAEzE,MAAM,CAAC,MAAM,kBAAkB,GAAoB,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC;AAE5F,MAAM,OAAO,GAAG,IAAI,CAAC;AAErB,qCAAqC;AACrC,MAAM,UAAU,cAAc,CAAC,KAAwB;IACrD,OAAO,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;AACvD,CAAC;AAED,sGAAsG;AACtG,MAAM,UAAU,UAAU,CAAC,KAAmF;IAC5G,OAAO,KAAK,CAAC,MAAM,KAAK,SAAS;QAC/B,CAAC,CAAC,EAAE,SAAS,EAAE,cAAc,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE;QAC5C,CAAC,CAAC,EAAE,SAAS,EAAE,cAAc,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC;AACvE,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,IAAqB,EAAE,KAAsB;IAC1E,OAAO;QACL,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC;QACtC,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC;QACtC,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC;QACtC,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC;QACtC,EAAE,EAAE,IAAI,CAAC,CAAC,GAAG,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC,GAAG,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE;QACnD,EAAE,EAAE,IAAI,CAAC,CAAC,GAAG,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC,GAAG,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE;KACpD,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,MAAuB;IAClD,MAAM,WAAW,GAAG,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC;IAC9D,IAAI,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,GAAG,OAAO;QAAE,OAAO,SAAS,CAAC;IAEtD,OAAO;QACL,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,WAAW;QACzB,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,GAAG,WAAW;QAC1B,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,GAAG,WAAW;QAC1B,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,WAAW;QACzB,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,EAAE,GAAG,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC,GAAG,WAAW;QAC/D,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,EAAE,GAAG,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC,GAAG,WAAW;KAChE,CAAC;AACJ,CAAC;AAED,qGAAqG;AACrG,MAAM,UAAU,oBAAoB,CAAC,SAA8B;IACjE,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IAC5C,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IAC1C,MAAM,CAAC,GAAG,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC;IACpC,MAAM,CAAC,GAAG,IAAI,GAAG,SAAS,CAAC,MAAM,CAAC;IAClC,MAAM,CAAC,GAAG,CAAC,IAAI,GAAG,SAAS,CAAC,MAAM,CAAC;IACnC,MAAM,CAAC,GAAG,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC;IACpC,MAAM,MAAM,GAAG,CAAC,SAAS,CAAC,MAAM,IAAI,CAAC,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC;IACzD,MAAM,MAAM,GAAG,CAAC,SAAS,CAAC,MAAM,IAAI,CAAC,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC;IAE1D,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,SAAS,CAAC,CAAC,GAAG,CAAC,GAAG,MAAM,GAAG,CAAC,GAAG,MAAM,EAAE,EAAE,EAAE,SAAS,CAAC,CAAC,GAAG,CAAC,GAAG,MAAM,GAAG,CAAC,GAAG,MAAM,EAAE,CAAC;AAC9G,CAAC;AAED,+FAA+F;AAC/F,MAAM,UAAU,iBAAiB,CAC/B,iBAA8C,EAC9C,KAA+B;IAE/B,MAAM,aAAa,GAAG,iBAAiB,KAAK,SAAS,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,YAAY,CAAC,iBAAiB,CAAC,CAAC;IAC7G,IAAI,aAAa,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAClD,OAAO;QACL,CAAC,EAAE,aAAa,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,aAAa,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,aAAa,CAAC,EAAE;QAC3E,CAAC,EAAE,aAAa,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,aAAa,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,aAAa,CAAC,EAAE;KAC5E,CAAC;AACJ,CAAC;AAED,SAAS,WAAW,CAAC,IAAY,EAAE,KAAa;IAC9C,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;AACvF,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,yBAAyB,CACvC,WAA4B,EAC5B,iBAA8C,EAC9C,MAA2B;IAE3B,MAAM,aAAa,GAAG,iBAAiB,KAAK,SAAS,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,YAAY,CAAC,iBAAiB,CAAC,CAAC;IAC7G,IAAI,aAAa,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAClD,MAAM,KAAK,GAAG,cAAc,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;IACzD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IAC5C,IAAI,MAAM,GAAG,OAAO;QAAE,OAAO,SAAS,CAAC;IACvC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IAC9C,MAAM,MAAM,GAAG,CAAC,KAAK,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC;IAChE,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAClC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAChC,MAAM,aAAa,GAAG;QACpB,CAAC,EAAE,MAAM,GAAG,MAAM;QAClB,CAAC,EAAE,IAAI,GAAG,MAAM;QAChB,CAAC,EAAE,CAAC,IAAI,GAAG,MAAM;QACjB,CAAC,EAAE,MAAM,GAAG,MAAM;KACnB,CAAC;IACF,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC;WAC/E,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC;QAAE,OAAO,SAAS,CAAC;IAExG,MAAM,MAAM,GAAG,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC;IACnD,MAAM,MAAM,GAAG,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC;IACpD,OAAO;QACL,GAAG,MAAM;QACT,CAAC,EAAE,KAAK,CAAC,EAAE,GAAG,KAAK,CAAC,CAAC,GAAG,MAAM,GAAG,KAAK,CAAC,CAAC,GAAG,MAAM;QACjD,CAAC,EAAE,KAAK,CAAC,EAAE,GAAG,KAAK,CAAC,CAAC,GAAG,MAAM,GAAG,KAAK,CAAC,CAAC,GAAG,MAAM;QACjD,MAAM;QACN,MAAM;QACN,QAAQ;KACT,CAAC;AACJ,CAAC;AAED,qFAAqF;AACrF,SAAS,iBAAiB,CAAC,SAAiB,EAAE,IAA+B;IAC3E,IAAI,IAAI,KAAK,YAAY;QAAE,OAAO,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3G,OAAO,SAAS,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AACtF,CAAC;AAED,SAAS,eAAe,CAAC,SAAiB,EAAE,SAAiB,EAAE,IAA+B;IAC5F,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,CAAC,GAAG,iBAAiB,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AACrE,CAAC;AAED;;;;;GAKG;AACH,SAAS,UAAU,CAAC,SAAiB,EAAE,IAA+B,EAAE,QAAiB,EAAE,KAAa,EAAE,KAAa,EAAE,IAAY,EAAE,OAAe;IACpJ,MAAM,IAAI,GAAG,KAAK,GAAG,CAAC,KAAK,GAAG,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC;IACvE,MAAM,MAAM,GAAG,IAAI,GAAG,iBAAiB,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IACzD,OAAO,QAAQ,CAAC,CAAC,CAAC,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;AAC3C,CAAC;AAID;;;;;GAKG;AACH,SAAS,SAAS,CAAC,UAAkB,EAAE,OAAwH;IAC7J,MAAM,KAAK,GAAe,EAAE,CAAC;IAC7B,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,WAAW,GAAG,CAAC,CAAC;IACpB,OAAO,KAAK,GAAG,UAAU,EAAE,CAAC;QAC1B,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,OAAO,KAAK,GAAG,OAAO,CAAC,QAAQ,IAAI,KAAK,GAAG,KAAK,GAAG,UAAU,EAAE,CAAC;YAC9D,KAAK,IAAI,CAAC,CAAC;YACX,IAAI,OAAO,CAAC,cAAc,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,GAAG,OAAO,CAAC,eAAe,KAAK,CAAC;gBAAE,MAAM;QACvF,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC;QAC1C,KAAK,IAAI,KAAK,CAAC;QACf,WAAW,IAAI,OAAO,CAAC,SAAS,CAAC;QACjC,MAAM,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,KAAK,GAAG,OAAO,CAAC,eAAe,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACrF,IAAI,KAAK,GAAG,UAAU,IAAI,MAAM;YAAE,WAAW,IAAI,OAAO,CAAC,YAAY,CAAC;IACxE,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC,CAAC;IAC3E,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,2BAA2B,CACzC,IAAY,EACZ,MAAgD,EAChD,OAAwB,EACxB,UAAsB;IAEtB,MAAM,QAAQ,GAAG,0BAA0B,CAAqB,MAAM,EAAE,OAAO,CAAC,CAAC;IACjF,MAAM,IAAI,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;IACvC,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;IACjE,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACvD,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,CAAC,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAClG,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,CAAC,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACpG,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,UAAU,GAAG,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,SAAS,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IAC5H,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,WAAW,GAAG,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,UAAU,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IAC3H,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC;IAC5E,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC;IAC5E,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC;IAC7E,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC;IAC7E,MAAM,KAAK,GAAG,SAAS,CAAC,UAAU,EAAE;QAClC,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,WAAW,CAAC;QACrE,eAAe,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,eAAe,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,iBAAiB;QAC5G,cAAc,EAAE,IAAI,CAAC,cAAc;QACnC,SAAS;QACT,YAAY;KACb,CAAC,CAAC;IACH,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,UAAU,GAAG,SAAS,CAAC,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC;IACnH,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC;IAC/B,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,GAAG,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;IACvE,MAAM,UAAU,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,WAAW,GAAG,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC;IACnF,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC;IAC9D,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC;IAC1E,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC;IACjF,MAAM,SAAS,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC,WAAW,GAAG,SAAS,CAAC,CAAC;IACpH,MAAM,UAAU,GAAG,SAAS,GAAG,iBAAiB,CAAC,QAAQ,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC;IACrF,MAAM,YAAY,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC;UACjF,UAAU,CAAC,QAAQ,CAAC,cAAc,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,UAAU,EAAE,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,WAAW,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,CAAC;UACnL,UAAU,GAAG,CAAC,QAAQ,GAAG,WAAW,CAAC,CAAC;IAC1C,yFAAyF;IACzF,iGAAiG;IACjG,sEAAsE;IACtE,MAAM,aAAa,GAAG,IAAI,CAAC,aAAa;QACtC,CAAC,CAAC,UAAU,GAAG,SAAS,GAAG,SAAS,GAAG,UAAU,GAAG,IAAI,CAAC,WAAW;QACpE,CAAC,CAAC,SAAS,GAAG,UAAU,GAAG,IAAI,CAAC,WAAW,CAAC;IAE9C,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,aAAa,CAAC;IAC7D,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,YAAY,CAAC;IAC7D,gGAAgG;IAChG,wFAAwF;IACxF,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC5B,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC5B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IACzD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;IAC3D,MAAM,QAAQ,GAAG,uBAAuB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,SAAS,CAAC;IAClE,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,CAAC;IACpC,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,CAAC;IACpC,OAAO,EAAE,GAAG,QAAQ,EAAE,CAAC,EAAE,CAAC,GAAG,MAAM,GAAG,KAAK,EAAE,CAAC,EAAE,CAAC,GAAG,MAAM,GAAG,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;AACvF,CAAC;AAED;;;;GAIG;AACH,SAAS,8BAA8B,CACrC,MAA0E,EAC1E,OAAwB,EACxB,UAAsB,EACtB,SAAsC;IAEtC,MAAM,QAAQ,GAAG,0BAA0B,CAAuB,MAAM,EAAE,OAAO,CAAC,CAAC;IACnF,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,KAAK,mBAAmB,CAAC;IACvD,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAAmB,EAAE,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC;IACxH,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC;UAC7E,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;IACpH,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC;UAC9E,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;IACpH,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QACnC,MAAM,QAAQ,GAAG,uBAAuB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,SAAS,CAAC;QACnE,MAAM,OAAO,GAAG,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC;QAC9D,MAAM,QAAQ,GAAG,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;QAC/D,MAAM,WAAW,GAAG,UAAU;YAC5B,CAAC,CAAC,QAAQ,CAAC,iBAAiB,IAAI,QAAQ,CAAC,gBAAgB;YACzD,CAAC,CAAC,QAAQ,CAAC,kBAAkB,IAAI,QAAQ,CAAC,iBAAiB,CAAC;QAC9D,MAAM,YAAY,GAAG,UAAU;YAC7B,CAAC,CAAC,QAAQ,CAAC,kBAAkB,IAAI,QAAQ,CAAC,iBAAiB;YAC3D,CAAC,CAAC,QAAQ,CAAC,iBAAiB,IAAI,QAAQ,CAAC,gBAAgB,CAAC;QAC5D,MAAM,SAAS,GAAG,KAAK,CAAC,UAAU,EAAE,SAAS,CAAC;QAC9C,OAAO;YACL,KAAK;YACL,QAAQ;YACR,IAAI,EAAE,KAAK,CAAC,UAAU,EAAE,SAAS,IAAI,OAAO;YAC5C,KAAK,EAAE,YAAY,IAAI,CAAC,SAAS,KAAK,SAAS,IAAI,SAAS,KAAK,MAAM,IAAI,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ;YAC3H,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,UAAU,EAAE,QAAQ,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,UAAU,EAAE,QAAQ,IAAI,CAAC;YAClG,MAAM,EAAE,KAAK,CAAC,UAAU,EAAE,UAAU,IAAI,CAAC;YACzC,SAAS;SACV,CAAC;IACJ,CAAC,CAAC,CAAC;IACH,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC,OAAO,CAAC;IAClE,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACpE,MAAM,QAAQ,GAAG,SAAS,GAAG,QAAQ,GAAG,WAAW,CAAC;IACpD,IAAI,QAAQ,GAAG,CAAC,EAAE,CAAC;QACjB,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QAClE,IAAI,SAAS,GAAG,CAAC;YAAE,KAAK,MAAM,IAAI,IAAI,KAAK;gBAAE,IAAI,CAAC,IAAI,IAAI,QAAQ,GAAG,IAAI,CAAC,IAAI,GAAG,SAAS,CAAC;IAC7F,CAAC;SAAM,IAAI,QAAQ,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,iBAAiB,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QACxF,IAAI,iBAAiB,GAAG,CAAC,EAAE,CAAC;YAC1B,KAAK,MAAM,IAAI,IAAI,KAAK;gBAAE,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,GAAG,QAAQ,GAAG,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC,CAAC;QACxH,CAAC;IACH,CAAC;IAED,MAAM,YAAY,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,QAAQ,CAAC;IAChF,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,GAAG,YAAY,CAAC,CAAC;IAC5D,MAAM,kBAAkB,GAAG,eAAe,CAAC,QAAQ,CAAC,cAAc,EAAE,aAAa,EAAE,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;IAC3H,MAAM,WAAW,GAAG,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,aAAa,GAAG,kBAAkB,CAAC,CAAC,CAAC,kBAAkB,CAAC;IACpG,MAAM,YAAY,GAAG,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;IAC1E,MAAM,SAAS,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC5C,IAAI,MAAM,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,WAAW,CAAC;IACvF,KAAK,MAAM,IAAI,IAAI,YAAY,EAAE,CAAC;QAChC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;QACrC,MAAM,IAAI,IAAI,CAAC,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC;IACzC,CAAC;IAED,MAAM,SAAS,GAAG,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC;IAC5E,MAAM,UAAU,GAAG,IAAI,GAAG,EAA+B,CAAC;IAC1D,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,gBAAgB,GAAG,eAAe,CAAC,QAAQ,CAAC,cAAc,EAAE,UAAU,GAAG,IAAI,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;QACnI,MAAM,eAAe,GAAG,IAAI,CAAC,SAAS,KAAK,QAAQ;YACjD,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC;YAC1C,CAAC,CAAC,IAAI,CAAC,SAAS,KAAK,UAAU;gBAC7B,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC;gBACtC,CAAC,CAAC,IAAI,CAAC,SAAS,KAAK,YAAY,IAAI,IAAI,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC;QAC7F,MAAM,YAAY,GAAG,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;QACvD,MAAM,aAAa,GAAG,SAAS,GAAG,eAAe,CAAC;QAClD,MAAM,KAAK,GAAG,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC;QAClD,MAAM,MAAM,GAAG,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;QACnD,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,aAAa,CAAC;QACpD,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,YAAY,CAAC;QACpD,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,IAAI,CAAC,CAAC;QACzC,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,IAAI,CAAC,CAAC;QACzC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC,EAAE,CAAC,GAAG,MAAM,GAAG,KAAK,EAAE,CAAC,EAAE,CAAC,GAAG,MAAM,GAAG,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;IACpH,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AAWD;;;;;;;GAOG;AACH,MAAM,OAAO,kBAAkB;IACpB,UAAU,CAAgB;IAC1B,QAAQ,CAAkB;IAC1B,WAAW,CAAyB;IACpC,aAAa,CAAkB;IAC/B,SAAS,GAAG,IAAI,GAAG,EAAoC,CAAC;IACxD,YAAY,GAAG,IAAI,GAAG,EAAyC,CAAC;IAChE,cAAc,GAAG,IAAI,GAAG,EAA4C,CAAC;IACrE,SAAS,GAAG,IAAI,GAAG,EAAU,CAAC;IAEvC,YAAY,SAAwB,EAAE,OAAwB;QAC5D,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;QAC5B,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;QACxB,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC;QAChC,MAAM,KAAK,GAAG,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,MAAM,CAAC,kBAAkB,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC;QAChI,IAAI,CAAC,WAAW,GAAG,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,oBAAoB,CAAC,MAAM,CAAC,kBAAkB,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC;QACnJ,IAAI,CAAC,aAAa,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC;IACxE,CAAC;IAED,8FAA8F;IAC9F,MAAM,CAAC,QAAQ,CAAC,KAAmF,EAAE,OAAwB;QAC3H,OAAO,IAAI,kBAAkB,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,CAAC;IAC5D,CAAC;IAED,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAED,gGAAgG;IAChG,IAAI,UAAU;QACZ,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAED,wEAAwE;IACxE,mBAAmB;QACjB,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC;IAC/E,CAAC;IAED,sGAAsG;IACtG,oBAAoB,CAAC,MAAc;QACjC,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,CAAC;IAC1C,CAAC;IAED,kFAAkF;IAClF,cAAc,CAAC,MAAc;QAC3B,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACvC,CAAC;IAED,iFAAiF;IACjF,iBAAiB,CAAC,QAAuB,EAAE,KAA+B;QACxE,OAAO,iBAAiB,CAAC,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,mBAAmB,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,KAAK,CAAC,CAAC;IAClH,CAAC;IAED;;;;;;OAMG;IACH,mBAAmB,CAAC,IAAY;QAC9B,OAAO,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAC;IACpG,CAAC;IAED;;;;OAIG;IACH,kBAAkB,CAAC,QAAuB;QACxC,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC/C,IAAI,MAAM,KAAK,SAAS,IAAI,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC;YAAE,OAAO,MAAM,CAAC;QAC3E,MAAM,IAAI,GAAG,IAAI,CAAC,uBAAuB,CAAC,QAAQ,CAAC,CAAC;QACpD,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QACtC,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;OAIG;IACH,sBAAsB,CAAC,MAAc,EAAE,WAA0B;QAC/D,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACnD,IAAI,IAAI,KAAK,SAAS;YAAE,OAAO,SAAS,CAAC;QACzC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACvC,IAAI,QAAQ,KAAK,SAAS;YAAE,OAAO,SAAS,CAAC;QAC7C,MAAM,iBAAiB,GAAG,WAAW,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,mBAAmB,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;QAC/G,MAAM,SAAS,GAAG,yBAAyB,CAAC,QAAQ,CAAC,MAAM,EAAE,iBAAiB,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC;QACpG,IAAI,SAAS,KAAK,SAAS;YAAE,OAAO,SAAS,CAAC;QAE9C,4FAA4F;QAC5F,6FAA6F;QAC7F,yBAAyB;QACzB,MAAM,eAAe,GAAG,IAAI,CAAC,kBAAkB,CAAC,WAAW,CAAC,IAAI,qBAAqB,CAAC;QACtF,MAAM,QAAQ,GAAG,uBAAuB,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC;QACxE,MAAM,UAAU,GAAG,QAAQ,CAAC,UAAU,IAAI,CAAC,CAAC;QAC5C,MAAM,UAAU,GAAG,QAAQ,CAAC,UAAU,IAAI,CAAC,CAAC;QAC5C,MAAM,UAAU,GAAG,QAAQ,CAAC,UAAU,IAAI,UAAU,CAAC;QACrD,MAAM,UAAU,GAAG,QAAQ,CAAC,UAAU,IAAI,UAAU,CAAC;QACrD,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,CAAC;QACpC,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,CAAC;QACpC,MAAM,KAAK,GAAG,UAAU,GAAG,UAAU,CAAC;QACtC,MAAM,KAAK,GAAG,UAAU,GAAG,UAAU,CAAC;QACtC,OAAO;YACL,GAAG,SAAS;YACZ,CAAC,EAAE,SAAS,CAAC,CAAC,GAAG,CAAC,UAAU,GAAG,KAAK,GAAG,MAAM,CAAC,GAAG,eAAe,CAAC,KAAK;YACtE,CAAC,EAAE,SAAS,CAAC,CAAC,GAAG,CAAC,UAAU,GAAG,KAAK,GAAG,MAAM,CAAC,GAAG,eAAe,CAAC,MAAM;YACvE,KAAK,EAAE,SAAS,CAAC,KAAK,GAAG,KAAK,GAAG,eAAe,CAAC,KAAK;YACtD,MAAM,EAAE,SAAS,CAAC,MAAM,GAAG,KAAK,GAAG,eAAe,CAAC,MAAM;SAC1D,CAAC;IACJ,CAAC;IAED,uBAAuB,CAAC,QAAuB;QAC7C,IAAI,QAAQ,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC,WAAW,CAAC;QAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACvD,IAAI,MAAM,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC,WAAW,CAAC;QAClD,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,QAAQ,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC,WAAW,CAAC;QAC9F,gGAAgG;QAChG,8FAA8F;QAC9F,gGAAgG;QAChG,gFAAgF;QAChF,MAAM,WAAW,GAAG,MAAM,CAAC,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC1G,IAAI,WAAW,KAAK,SAAS,IAAI,WAAW,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;YACpE,MAAM,IAAI,GAAG,0BAA0B,CAAqB,WAAW,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;YACxF,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC;QAC5D,CAAC;QACD,uFAAuF;QACvF,8FAA8F;QAC9F,mGAAmG;QACnG,4FAA4F;QAC5F,2FAA2F;QAC3F,IAAI,WAAW,KAAK,SAAS,IAAI,WAAW,CAAC,IAAI,KAAK,YAAY;YAAE,OAAO,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACpH,kGAAkG;QAClG,MAAM,SAAS,GAAG,wBAAwB,CAAC,uBAAuB,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,SAAS,EAAE,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC/I,OAAO,EAAE,KAAK,EAAE,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,CAAC,MAAM,EAAE,CAAC;IAC9D,CAAC;IAED;;;OAGG;IACH,QAAQ,CAAC,MAAc;QACrB,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC1C,IAAI,MAAM,KAAK,SAAS,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC;YAAE,OAAO,MAAM,CAAC;QACtE,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC;YAAE,OAAO,SAAS,CAAC;QACjD,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACnD,IAAI,IAAI,KAAK,SAAS;YAAE,OAAO,SAAS,CAAC;QAEzC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC3B,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACrG,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACjF,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAE9B,IAAI,MAAgC,CAAC;QACrC,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACnD,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,KAAK,SAAS,IAAI,UAAU,EAAE,QAAQ,KAAK,IAAI;gBACtF,CAAC,CAAC,IAAI,CAAC,WAAW;gBAClB,CAAC,CAAC,MAAM,EAAE,IAAI,IAAI,IAAI,CAAC,WAAW,CAAC;YACrC,MAAM,OAAO,GAAG,UAAU,KAAK,SAAS,IAAI,MAAM,KAAK,SAAS;gBAC9D,CAAC,CAAC,IAAI,CAAC,wBAAwB,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,CAAC,IAAI,CAAC;gBAC9D,CAAC,CAAC,SAAS,CAAC;YACd,MAAM,SAAS,GAAG,OAAO,IAAI,wBAAwB,CAAC,uBAAuB,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;YAC1H,MAAM,GAAG;gBACP,SAAS;gBACT,MAAM,EAAE,cAAc,CAAC,MAAM,EAAE,MAAM,IAAI,IAAI,CAAC,aAAa,EAAE,oBAAoB,CAAC,SAAS,CAAC,CAAC;gBAC7F,IAAI,EAAE,IAAI,CAAC,QAAQ,KAAK,IAAI,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,KAAK,SAAS;oBAClE,CAAC,CAAC,IAAI,CAAC,WAAY;oBACnB,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,CAAC,MAAM,EAAE;aACzD,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACnC,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,4GAA4G;IAC5G,wBAAwB,CAAC,IAAY,EAAE,MAAc,EAAE,UAAsB;QAC3E,IAAI,MAAM,CAAC,IAAI,KAAK,aAAa;YAAE,OAAO,2BAA2B,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QAC/G,IAAI,MAAM,CAAC,IAAI,KAAK,mBAAmB,IAAI,MAAM,CAAC,IAAI,KAAK,iBAAiB;YAAE,OAAO,SAAS,CAAC;QAC/F,IAAI,MAAM,GAAG,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAChD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,MAAM,GAAG,8BAA8B,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;YACtG,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;QAC7C,CAAC;QACD,OAAO,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,uBAAuB,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC;IACvF,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,SAAwB,EAAE,IAAY,EAAE,OAAwB;IAClG,OAAO,IAAI,kBAAkB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC;AAC9E,CAAC","sourcesContent":["import {\n resolveLayoutGroupSettings,\n type GridLayoutSettings,\n type LayoutProfileId,\n type LinearLayoutSettings,\n type UINode,\n} from \"@pixi-ui-editor/schema\";\nimport { getCanvasLogicalSize, getCanvasScale, resolveAnchoredTransform, resolveProfileTransform, type LayoutSize } from \"./layout.js\";\nimport { resolveGridFlow } from \"./layoutGroups.js\";\n\nexport type AffineTransform = {\n a: number;\n b: number;\n c: number;\n d: number;\n tx: number;\n ty: number;\n};\n\n/** Viewport pair a scene carries; a prefab being edited on its own has none. */\nexport type NodeHierarchyLayout = {\n readonly referenceViewports: Record<LayoutProfileId, LayoutSize>;\n readonly preferredViewports: Record<LayoutProfileId, LayoutSize>;\n};\n\n/**\n * Любая иерархия авторинга, по которой резолвятся родители. Владелец обязан отдавать индекс, а не\n * список: линейный поиск родителя делал обход всей иерархии квадратичным.\n */\nexport type NodeHierarchy = {\n readonly nodesById: ReadonlyMap<string, UINode>;\n readonly layout?: NodeHierarchyLayout;\n};\n\n/** Подстановка для иерархии без собственного viewport: якорные слагаемые обнуляются. */\nexport const NO_PARENT_LAYOUT_SIZE: LayoutSize = { width: 0, height: 0 };\n\nexport const IDENTITY_TRANSFORM: AffineTransform = { a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0 };\n\nconst EPSILON = 1e-8;\n\n/** Единственный индекс id → узел. */\nexport function indexNodesById(nodes: readonly UINode[]): ReadonlyMap<string, UINode> {\n return new Map(nodes.map((node) => [node.id, node]));\n}\n\n/** Оборачивает сырого владельца узлов (сцену, пресет) в форму, которую принимают helpers иерархии. */\nexport function indexNodes(owner: { readonly nodes: readonly UINode[]; readonly layout?: NodeHierarchyLayout }): NodeHierarchy {\n return owner.layout === undefined\n ? { nodesById: indexNodesById(owner.nodes) }\n : { nodesById: indexNodesById(owner.nodes), layout: owner.layout };\n}\n\nexport function multiplyAffine(left: AffineTransform, right: AffineTransform): AffineTransform {\n return {\n a: left.a * right.a + left.c * right.b,\n b: left.b * right.a + left.d * right.b,\n c: left.a * right.c + left.c * right.d,\n d: left.b * right.c + left.d * right.d,\n tx: left.a * right.tx + left.c * right.ty + left.tx,\n ty: left.b * right.tx + left.d * right.ty + left.ty,\n };\n}\n\nexport function invertAffine(matrix: AffineTransform): AffineTransform | undefined {\n const determinant = matrix.a * matrix.d - matrix.b * matrix.c;\n if (Math.abs(determinant) < EPSILON) return undefined;\n\n return {\n a: matrix.d / determinant,\n b: -matrix.b / determinant,\n c: -matrix.c / determinant,\n d: matrix.a / determinant,\n tx: (matrix.c * matrix.ty - matrix.d * matrix.tx) / determinant,\n ty: (matrix.b * matrix.tx - matrix.a * matrix.ty) / determinant,\n };\n}\n\n/** Матрица одного узла в системе координат его родителя — ровно то, что строит Pixi из transform. */\nexport function localTransformMatrix(transform: UINode[\"transform\"]): AffineTransform {\n const cosine = Math.cos(transform.rotation);\n const sine = Math.sin(transform.rotation);\n const a = cosine * transform.scaleX;\n const b = sine * transform.scaleX;\n const c = -sine * transform.scaleY;\n const d = cosine * transform.scaleY;\n const pivotX = (transform.pivotX ?? 0) * transform.width;\n const pivotY = (transform.pivotY ?? 0) * transform.height;\n\n return { a, b, c, d, tx: transform.x - a * pivotX - c * pivotY, ty: transform.y - b * pivotX - d * pivotY };\n}\n\n/** Converts a point in scene coordinates into coordinates local to a parent's world matrix. */\nexport function worldPointToLocal(\n parentWorldMatrix: AffineTransform | undefined,\n point: { x: number; y: number },\n): { x: number; y: number } | undefined {\n const inverseParent = parentWorldMatrix === undefined ? IDENTITY_TRANSFORM : invertAffine(parentWorldMatrix);\n if (inverseParent === undefined) return undefined;\n return {\n x: inverseParent.a * point.x + inverseParent.c * point.y + inverseParent.tx,\n y: inverseParent.b * point.x + inverseParent.d * point.y + inverseParent.ty,\n };\n}\n\nfunction nearlyEqual(left: number, right: number): boolean {\n return Math.abs(left - right) <= 1e-6 * Math.max(1, Math.abs(left), Math.abs(right));\n}\n\n/**\n * Converts a world matrix to a schema transform relative to a new parent.\n * Undefined means the result needs skew (or an inverse of a zero-scale parent), neither of which\n * the current document format can represent without changing the rendered object.\n */\nexport function transformRelativeToParent(\n worldMatrix: AffineTransform,\n parentWorldMatrix: AffineTransform | undefined,\n source: UINode[\"transform\"],\n): UINode[\"transform\"] | undefined {\n const inverseParent = parentWorldMatrix === undefined ? IDENTITY_TRANSFORM : invertAffine(parentWorldMatrix);\n if (inverseParent === undefined) return undefined;\n const local = multiplyAffine(inverseParent, worldMatrix);\n const scaleX = Math.hypot(local.a, local.b);\n if (scaleX < EPSILON) return undefined;\n const rotation = Math.atan2(local.b, local.a);\n const scaleY = (local.a * local.d - local.b * local.c) / scaleX;\n const cosine = Math.cos(rotation);\n const sine = Math.sin(rotation);\n const reconstructed = {\n a: cosine * scaleX,\n b: sine * scaleX,\n c: -sine * scaleY,\n d: cosine * scaleY,\n };\n if (!nearlyEqual(local.a, reconstructed.a) || !nearlyEqual(local.b, reconstructed.b)\n || !nearlyEqual(local.c, reconstructed.c) || !nearlyEqual(local.d, reconstructed.d)) return undefined;\n\n const pivotX = (source.pivotX ?? 0) * source.width;\n const pivotY = (source.pivotY ?? 0) * source.height;\n return {\n ...source,\n x: local.tx + local.a * pivotX + local.c * pivotY,\n y: local.ty + local.b * pivotX + local.d * pivotY,\n scaleX,\n scaleY,\n rotation,\n };\n}\n\n/** Доля свободного места до начала блока: 0 для start, 0.5 для center, 1 для end. */\nfunction alignmentFraction(alignment: string, axis: \"horizontal\" | \"vertical\"): number {\n if (axis === \"horizontal\") return alignment.endsWith(\"right\") ? 1 : alignment.endsWith(\"center\") ? 0.5 : 0;\n return alignment.startsWith(\"lower\") ? 1 : alignment.startsWith(\"middle\") ? 0.5 : 0;\n}\n\nfunction alignmentOffset(alignment: string, freeSpace: number, axis: \"horizontal\" | \"vertical\"): number {\n return Math.max(0, freeSpace) * alignmentFraction(alignment, axis);\n}\n\n/**\n * Смещение линии по одной оси. Свободное место считается по фактическому числу ячеек в линии,\n * поэтому неполная последняя строка выравнивается сама по себе — ровно как justify-content\n * во flex-wrap. Реверс оси меняет физический смысл выравнивания на противоположный, а\n * отрицательное свободное место не зажимается: при переполнении Yoga уводит блок за край.\n */\nfunction lineOffset(alignment: string, axis: \"horizontal\" | \"vertical\", reversed: boolean, inner: number, count: number, cell: number, spacing: number): number {\n const free = inner - (count * cell + Math.max(0, count - 1) * spacing);\n const offset = free * alignmentFraction(alignment, axis);\n return reversed ? free - offset : offset;\n}\n\ntype GridLine = { readonly start: number; readonly count: number; readonly crossOffset: number };\n\n/**\n * Раскладывает детей сетки по линиям переноса ровно так, как это делает Yoga: линия закрывается\n * либо когда ячейки в неё больше не влезают, либо на границе, кратной constraint, где стоит\n * элемент-разрыв. Поперечный зазор приходит только от разрыва, поэтому линии, закрытые ранним\n * переносом, стоят вплотную — см. applyLayoutGroup.\n */\nfunction gridLines(childCount: number, options: { capacity: number; constraintCount: number; usesLineBreaks: boolean; crossCell: number; crossSpacing: number }): GridLine[] {\n const lines: GridLine[] = [];\n let start = 0;\n let crossOffset = 0;\n while (start < childCount) {\n let count = 0;\n while (count < options.capacity && start + count < childCount) {\n count += 1;\n if (options.usesLineBreaks && (start + count) % options.constraintCount === 0) break;\n }\n lines.push({ start, count, crossOffset });\n start += count;\n crossOffset += options.crossCell;\n const spaced = options.usesLineBreaks ? start % options.constraintCount === 0 : true;\n if (start < childCount && spaced) crossOffset += options.crossSpacing;\n }\n if (lines.length === 0) lines.push({ start: 0, count: 1, crossOffset: 0 });\n return lines;\n}\n\n/**\n * Resolves the rectangle that Yoga gives a direct GridLayout child. The authored x/y, anchors and\n * size do not participate while the child is in the grid, so hierarchy reparenting must preserve\n * this managed rectangle rather than the dormant authored transform.\n */\nexport function resolveGridManagedTransform(\n node: UINode,\n parent: Extract<UINode, { type: \"grid-layout\" }>,\n profile: LayoutProfileId,\n parentSize: LayoutSize,\n): UINode[\"transform\"] {\n const settings = resolveLayoutGroupSettings<GridLayoutSettings>(parent, profile);\n const flow = resolveGridFlow(settings);\n const childIndex = Math.max(0, parent.children.indexOf(node.id));\n const childCount = Math.max(1, parent.children.length);\n const innerWidth = Math.max(0, parentSize.width - settings.padding.left - settings.padding.right);\n const innerHeight = Math.max(0, parentSize.height - settings.padding.top - settings.padding.bottom);\n const fittingColumns = Math.max(1, Math.floor((innerWidth + settings.spacingX) / (settings.cellWidth + settings.spacingX)));\n const fittingRows = Math.max(1, Math.floor((innerHeight + settings.spacingY) / (settings.cellHeight + settings.spacingY)));\n const mainCell = flow.fillsByRow ? settings.cellWidth : settings.cellHeight;\n const mainSpacing = flow.fillsByRow ? settings.spacingX : settings.spacingY;\n const crossCell = flow.fillsByRow ? settings.cellHeight : settings.cellWidth;\n const crossSpacing = flow.fillsByRow ? settings.spacingY : settings.spacingX;\n const lines = gridLines(childCount, {\n capacity: Math.max(1, flow.fillsByRow ? fittingColumns : fittingRows),\n constraintCount: flow.usesLineBreaks ? Math.max(1, settings.constraintCount ?? 1) : Number.POSITIVE_INFINITY,\n usesLineBreaks: flow.usesLineBreaks,\n crossCell,\n crossSpacing,\n });\n const line = lines.find((candidate) => childIndex < candidate.start + candidate.count) ?? lines[lines.length - 1]!;\n const itemsInLine = line.count;\n const indexInLine = Math.min(itemsInLine - 1, childIndex - line.start);\n const slotInLine = flow.mainReversed ? itemsInLine - 1 - indexInLine : indexInLine;\n const crossAxis = flow.fillsByRow ? \"vertical\" : \"horizontal\";\n const crossTotal = flow.fillsByRow ? parentSize.height : parentSize.width;\n const crossLead = flow.fillsByRow ? settings.padding.top : settings.padding.left;\n const crossFree = (flow.fillsByRow ? innerHeight : innerWidth) - (lines[lines.length - 1]!.crossOffset + crossCell);\n const crossAlign = crossFree * alignmentFraction(settings.childAlignment, crossAxis);\n const mainPosition = (flow.fillsByRow ? settings.padding.left : settings.padding.top)\n + lineOffset(settings.childAlignment, flow.fillsByRow ? \"horizontal\" : \"vertical\", flow.mainReversed, flow.fillsByRow ? innerWidth : innerHeight, itemsInLine, mainCell, mainSpacing)\n + slotInLine * (mainCell + mainSpacing);\n // wrap-reverse у Yoga отсчитывает линии от дальнего края, отступая ведущим padding, а не\n // замыкающим; выравнивание при этом меряется от той же дальней кромки. Зеркало обязано повторять\n // именно это поведение, иначе рамки выделения разъедутся с картинкой.\n const crossPosition = flow.crossReversed\n ? crossTotal - crossLead - crossCell - crossAlign - line.crossOffset\n : crossLead + crossAlign + line.crossOffset;\n\n const cellX = flow.fillsByRow ? mainPosition : crossPosition;\n const cellY = flow.fillsByRow ? crossPosition : mainPosition;\n // Yoga кладёт результат на пиксельную сетку (pointScaleFactor = 1), округляя обе кромки ячейки.\n // Зеркало округляет так же, иначе на дробных выравниваниях рамка уезжает на полпикселя.\n const x = Math.round(cellX);\n const y = Math.round(cellY);\n const width = Math.round(cellX + settings.cellWidth) - x;\n const height = Math.round(cellY + settings.cellHeight) - y;\n const authored = resolveProfileTransform(node, profile).transform;\n const pivotX = authored.pivotX ?? 0;\n const pivotY = authored.pivotY ?? 0;\n return { ...authored, x: x + pivotX * width, y: y + pivotY * height, width, height };\n}\n\n/**\n * Раскладка ВСЕЙ линейной группы за один проход: Yoga решает линию целиком (grow/shrink делят одно\n * общее свободное место), поэтому пересчитывать её на каждого ребёнка отдельно — квадратичная\n * работа. `NodeTransformSpace` кэширует результат по родителю и берёт из него нужную ячейку.\n */\nfunction resolveLinearManagedTransforms(\n parent: Extract<UINode, { type: \"horizontal-layout\" | \"vertical-layout\" }>,\n profile: LayoutProfileId,\n parentSize: LayoutSize,\n nodesById: ReadonlyMap<string, UINode>,\n): Map<string, UINode[\"transform\"]> {\n const settings = resolveLayoutGroupSettings<LinearLayoutSettings>(parent, profile);\n const horizontal = parent.type === \"horizontal-layout\";\n const children = parent.children.map((id) => nodesById.get(id)).filter((child): child is UINode => child !== undefined);\n const innerMain = Math.max(0, (horizontal ? parentSize.width : parentSize.height)\n - (horizontal ? settings.padding.left + settings.padding.right : settings.padding.top + settings.padding.bottom));\n const innerCross = Math.max(0, (horizontal ? parentSize.height : parentSize.width)\n - (horizontal ? settings.padding.top + settings.padding.bottom : settings.padding.left + settings.padding.right));\n const items = children.map((child) => {\n const authored = resolveProfileTransform(child, profile).transform;\n const ownMain = horizontal ? authored.width : authored.height;\n const ownCross = horizontal ? authored.height : authored.width;\n const expandsMain = horizontal\n ? settings.controlChildWidth && settings.forceExpandWidth\n : settings.controlChildHeight && settings.forceExpandHeight;\n const expandsCross = horizontal\n ? settings.controlChildHeight && settings.forceExpandHeight\n : settings.controlChildWidth && settings.forceExpandWidth;\n const alignSelf = child.layoutItem?.alignSelf;\n return {\n child,\n authored,\n main: child.layoutItem?.flexBasis ?? ownMain,\n cross: expandsCross && (alignSelf === undefined || alignSelf === \"auto\" || alignSelf === \"stretch\") ? innerCross : ownCross,\n grow: expandsMain ? Math.max(1, child.layoutItem?.flexGrow ?? 0) : child.layoutItem?.flexGrow ?? 0,\n shrink: child.layoutItem?.flexShrink ?? 0,\n alignSelf,\n };\n });\n const totalGap = Math.max(0, items.length - 1) * settings.spacing;\n const initialMain = items.reduce((sum, item) => sum + item.main, 0);\n const freeMain = innerMain - totalGap - initialMain;\n if (freeMain > 0) {\n const totalGrow = items.reduce((sum, item) => sum + item.grow, 0);\n if (totalGrow > 0) for (const item of items) item.main += freeMain * item.grow / totalGrow;\n } else if (freeMain < 0) {\n const totalShrinkWeight = items.reduce((sum, item) => sum + item.shrink * item.main, 0);\n if (totalShrinkWeight > 0) {\n for (const item of items) item.main = Math.max(0, item.main + freeMain * item.shrink * item.main / totalShrinkWeight);\n }\n }\n\n const occupiedMain = items.reduce((sum, item) => sum + item.main, 0) + totalGap;\n const remainingMain = Math.max(0, innerMain - occupiedMain);\n const physicalMainOffset = alignmentOffset(settings.childAlignment, remainingMain, horizontal ? \"horizontal\" : \"vertical\");\n const blockOffset = settings.reverseOrder ? remainingMain - physicalMainOffset : physicalMainOffset;\n const orderedItems = settings.reverseOrder ? [...items].reverse() : items;\n const positions = new Map<string, number>();\n let cursor = (horizontal ? settings.padding.left : settings.padding.top) + blockOffset;\n for (const item of orderedItems) {\n positions.set(item.child.id, cursor);\n cursor += item.main + settings.spacing;\n }\n\n const crossLead = horizontal ? settings.padding.top : settings.padding.left;\n const transforms = new Map<string, UINode[\"transform\"]>();\n for (const item of items) {\n const groupCrossOffset = alignmentOffset(settings.childAlignment, innerCross - item.cross, horizontal ? \"vertical\" : \"horizontal\");\n const selfCrossOffset = item.alignSelf === \"center\"\n ? Math.max(0, innerCross - item.cross) / 2\n : item.alignSelf === \"flex-end\"\n ? Math.max(0, innerCross - item.cross)\n : item.alignSelf === \"flex-start\" || item.alignSelf === \"stretch\" ? 0 : groupCrossOffset;\n const mainPosition = positions.get(item.child.id) ?? 0;\n const crossPosition = crossLead + selfCrossOffset;\n const width = horizontal ? item.main : item.cross;\n const height = horizontal ? item.cross : item.main;\n const x = horizontal ? mainPosition : crossPosition;\n const y = horizontal ? crossPosition : mainPosition;\n const pivotX = item.authored.pivotX ?? 0;\n const pivotY = item.authored.pivotY ?? 0;\n transforms.set(item.child.id, { ...item.authored, x: x + pivotX * width, y: y + pivotY * height, width, height });\n }\n return transforms;\n}\n\ntype ResolvedNode = {\n /** Rectangle the node is actually rendered with, including a layout parent's managed cell. */\n readonly transform: UINode[\"transform\"];\n /** Same world matrix Pixi builds from the serialized parent chain. */\n readonly matrix: AffineTransform;\n /** Logical size this node exposes to its own children. */\n readonly size: LayoutSize;\n};\n\n/**\n * Снимок системы координат одной иерархии в одном layout-профиле: мировые матрицы, отрисованные\n * прямоугольники и перенос узла к другому родителю без визуального сдвига.\n *\n * Экземпляр кэширует всё, что посчитал, поэтому он действителен ровно до следующей мутации узлов —\n * после правки документа создавайте новый. Это единственная реализация: и редактор, и рантайм\n * обязаны считать репарент здесь, иначе картинки разъедутся.\n */\nexport class NodeTransformSpace {\n readonly #hierarchy: NodeHierarchy;\n readonly #profile: LayoutProfileId;\n readonly #canvasSize: LayoutSize | undefined;\n readonly #canvasMatrix: AffineTransform;\n readonly #resolved = new Map<string, ResolvedNode | undefined>();\n readonly #parentSizes = new Map<string | null, LayoutSize | undefined>();\n readonly #linearLayouts = new Map<string, Map<string, UINode[\"transform\"]>>();\n readonly #visiting = new Set<string>();\n\n constructor(hierarchy: NodeHierarchy, profile: LayoutProfileId) {\n this.#hierarchy = hierarchy;\n this.#profile = profile;\n const layout = hierarchy.layout;\n const scale = layout === undefined ? 1 : getCanvasScale(layout.referenceViewports[profile], layout.preferredViewports[profile]);\n this.#canvasSize = layout === undefined ? undefined : getCanvasLogicalSize(layout.referenceViewports[profile], layout.preferredViewports[profile]);\n this.#canvasMatrix = { a: scale, b: 0, c: 0, d: scale, tx: 0, ty: 0 };\n }\n\n /** Snapshot for the same hierarchy in another profile; каждый профиль кэшируется отдельно. */\n static forOwner(owner: { readonly nodes: readonly UINode[]; readonly layout?: NodeHierarchyLayout }, profile: LayoutProfileId): NodeTransformSpace {\n return new NodeTransformSpace(indexNodes(owner), profile);\n }\n\n get profile(): LayoutProfileId {\n return this.#profile;\n }\n\n /** Логический RectTransform-размер Canvas; `undefined` у иерархии без собственного viewport. */\n get canvasSize(): LayoutSize | undefined {\n return this.#canvasSize;\n }\n\n /** Matrix of the Unity-like scaled Canvas that owns top-level nodes. */\n getOwnerWorldMatrix(): AffineTransform | undefined {\n return this.#hierarchy.layout === undefined ? undefined : this.#canvasMatrix;\n }\n\n /** Returns the node rectangle that is actually rendered, including a layout parent's managed cell. */\n getRenderedTransform(nodeId: string): UINode[\"transform\"] | undefined {\n return this.#resolve(nodeId)?.transform;\n }\n\n /** Returns the same world matrix Pixi builds from the serialized parent chain. */\n getWorldMatrix(nodeId: string): AffineTransform | undefined {\n return this.#resolve(nodeId)?.matrix;\n }\n\n /** Scene-space point converted into the coordinates of `parentId`'s children. */\n worldPointToLocal(parentId: string | null, point: { x: number; y: number }): { x: number; y: number } | undefined {\n return worldPointToLocal(parentId === null ? this.getOwnerWorldMatrix() : this.getWorldMatrix(parentId), point);\n }\n\n /**\n * Логический размер, относительно которого разрешается anchoredPosition узла.\n *\n * Узел может быть черновиком мутации (его ещё нет в иерархии) — тогда берётся его собственный\n * parentId. `undefined` означает «у иерархии нет своего viewport» (редактируемый пресет): это не\n * то же самое, что нулевой размер, `resolveAnchoredTransform` в этом случае не трогает transform.\n */\n getParentLayoutSize(node: UINode): LayoutSize | undefined {\n return this.getChildLayoutSize(this.#hierarchy.nodesById.get(node.id)?.parentId ?? node.parentId);\n }\n\n /**\n * Размер, который получает ЛЮБОЙ прямой ребёнок узла `parentId` (null — корень иерархии).\n * Именно его требует перенос: якорные слагаемые ребёнка должны сниматься с размера будущего\n * родителя, а не текущего.\n */\n getChildLayoutSize(parentId: string | null): LayoutSize | undefined {\n const cached = this.#parentSizes.get(parentId);\n if (cached !== undefined || this.#parentSizes.has(parentId)) return cached;\n const size = this.#computeChildLayoutSize(parentId);\n this.#parentSizes.set(parentId, size);\n return size;\n }\n\n /**\n * Transform, который сохраняет узел на экране после переноса под `newParentId` — то, что нужно\n * записать в документ. `undefined`, если сохранить картинку нельзя: перенос потребовал бы skew\n * либо родитель невырожденно не обращается (нулевой масштаб).\n */\n getReparentedTransform(nodeId: string, newParentId: string | null): UINode[\"transform\"] | undefined {\n const node = this.#hierarchy.nodesById.get(nodeId);\n if (node === undefined) return undefined;\n const resolved = this.#resolve(nodeId);\n if (resolved === undefined) return undefined;\n const parentWorldMatrix = newParentId === null ? this.getOwnerWorldMatrix() : this.getWorldMatrix(newParentId);\n const preserved = transformRelativeToParent(resolved.matrix, parentWorldMatrix, resolved.transform);\n if (preserved === undefined) return undefined;\n\n // Anchors живут в схеме как доли размера родителя, поэтому мировой transform, разложенный в\n // локальный, ещё содержит вклад НОВОГО родителя: его нужно вычесть, чтобы authored-поля дали\n // на экране ту же рамку.\n const destinationSize = this.getChildLayoutSize(newParentId) ?? NO_PARENT_LAYOUT_SIZE;\n const authored = resolveProfileTransform(node, this.#profile).transform;\n const anchorMinX = authored.anchorMinX ?? 0;\n const anchorMinY = authored.anchorMinY ?? 0;\n const anchorMaxX = authored.anchorMaxX ?? anchorMinX;\n const anchorMaxY = authored.anchorMaxY ?? anchorMinY;\n const pivotX = authored.pivotX ?? 0;\n const pivotY = authored.pivotY ?? 0;\n const spanX = anchorMaxX - anchorMinX;\n const spanY = anchorMaxY - anchorMinY;\n return {\n ...preserved,\n x: preserved.x - (anchorMinX + spanX * pivotX) * destinationSize.width,\n y: preserved.y - (anchorMinY + spanY * pivotY) * destinationSize.height,\n width: preserved.width - spanX * destinationSize.width,\n height: preserved.height - spanY * destinationSize.height,\n };\n }\n\n #computeChildLayoutSize(parentId: string | null): LayoutSize | undefined {\n if (parentId === null) return this.#canvasSize;\n const parent = this.#hierarchy.nodesById.get(parentId);\n if (parent === undefined) return this.#canvasSize;\n if (this.#hierarchy.layout !== undefined && parent.parentId === null) return this.#canvasSize;\n // Прямой ребёнок grid-layout не владеет своим отрисованным размером: фиксированная ячейка Unity\n // GridLayoutGroup полностью переопределяет authored transform (см. applyLayoutItem). Без этой\n // ветки внуки грида (например текст внутри button-ячейки) якорились бы относительно устаревшего\n // authored-размера родителя и не реагировали бы на изменение Cell width/height.\n const grandparent = parent.parentId === null ? undefined : this.#hierarchy.nodesById.get(parent.parentId);\n if (grandparent !== undefined && grandparent.type === \"grid-layout\") {\n const grid = resolveLayoutGroupSettings<GridLayoutSettings>(grandparent, this.#profile);\n return { width: grid.cellWidth, height: grid.cellHeight };\n }\n // Тот же принцип для прямого ребёнка page-group (страницы): она не владеет собственным\n // отрисованным размером — растягивается на весь resolved rectangle группы независимо от своих\n // anchors (`PageItemContainer`/`NodeView.applyResolvedTransform`, managedByLayout). Её собственным\n // детям нужен именно этот forced rectangle, а не anchor-resolved authored-размер страницы —\n // иначе они якорятся относительно значения, которое страница на экране никогда не получит.\n if (grandparent !== undefined && grandparent.type === \"page-group\") return this.getChildLayoutSize(parent.parentId);\n // Родитель может быть сам растянут anchors, поэтому его логический размер разрешается рекурсивно.\n const transform = resolveAnchoredTransform(resolveProfileTransform(parent, this.#profile).transform, this.getChildLayoutSize(parent.parentId));\n return { width: transform.width, height: transform.height };\n }\n\n /**\n * Один обход вверх по цепочке родителей на узел: и отрисованный прямоугольник, и мировая матрица\n * берутся из него. Результат кэшируется, поэтому у ветки с общим предком предки считаются один раз.\n */\n #resolve(nodeId: string): ResolvedNode | undefined {\n const cached = this.#resolved.get(nodeId);\n if (cached !== undefined || this.#resolved.has(nodeId)) return cached;\n if (this.#visiting.has(nodeId)) return undefined;\n const node = this.#hierarchy.nodesById.get(nodeId);\n if (node === undefined) return undefined;\n\n this.#visiting.add(nodeId);\n const parentNode = node.parentId === null ? undefined : this.#hierarchy.nodesById.get(node.parentId);\n const parent = node.parentId === null ? undefined : this.#resolve(node.parentId);\n this.#visiting.delete(nodeId);\n\n let result: ResolvedNode | undefined;\n if (node.parentId === null || parent !== undefined) {\n const parentSize = this.#hierarchy.layout !== undefined && parentNode?.parentId === null\n ? this.#canvasSize\n : parent?.size ?? this.#canvasSize;\n const managed = parentNode !== undefined && parent !== undefined\n ? this.#resolveManagedTransform(node, parentNode, parent.size)\n : undefined;\n const transform = managed ?? resolveAnchoredTransform(resolveProfileTransform(node, this.#profile).transform, parentSize);\n result = {\n transform,\n matrix: multiplyAffine(parent?.matrix ?? this.#canvasMatrix, localTransformMatrix(transform)),\n size: node.parentId === null && this.#hierarchy.layout !== undefined\n ? this.#canvasSize!\n : { width: transform.width, height: transform.height },\n };\n }\n this.#resolved.set(nodeId, result);\n return result;\n }\n\n /** Прямоугольник, который назначает ребёнку родитель-раскладка; `undefined` — позицией владеет сам узел. */\n #resolveManagedTransform(node: UINode, parent: UINode, parentSize: LayoutSize): UINode[\"transform\"] | undefined {\n if (parent.type === \"grid-layout\") return resolveGridManagedTransform(node, parent, this.#profile, parentSize);\n if (parent.type !== \"horizontal-layout\" && parent.type !== \"vertical-layout\") return undefined;\n let layout = this.#linearLayouts.get(parent.id);\n if (layout === undefined) {\n layout = resolveLinearManagedTransforms(parent, this.#profile, parentSize, this.#hierarchy.nodesById);\n this.#linearLayouts.set(parent.id, layout);\n }\n return layout.get(node.id) ?? resolveProfileTransform(node, this.#profile).transform;\n }\n}\n\n/**\n * Разовый запрос размера родителя без явного снимка: удобен на единичных вызовах.\n * В цикле по узлам создавайте один `NodeTransformSpace` — он переиспользует кэши.\n */\nexport function getParentLayoutSize(hierarchy: NodeHierarchy, node: UINode, profile: LayoutProfileId): LayoutSize | undefined {\n return new NodeTransformSpace(hierarchy, profile).getParentLayoutSize(node);\n}\n"]}
@@ -1,8 +1,8 @@
1
1
  import { type ButtonStateKey, type LayoutPadding, type UINode } from "@pixi-ui-editor/schema";
2
2
  import { FancyButton } from "@pixi/ui";
3
- import type { Sound } from "@pixi/sound";
4
3
  import { Texture } from "pixi.js";
5
4
  import { NodeView, type SceneInteractionMode } from "./NodeView.js";
5
+ import type { SceneAudio } from "../audio/bus.js";
6
6
  export type ButtonNode = Extract<UINode, {
7
7
  type: "button";
8
8
  }>;
@@ -19,10 +19,11 @@ export declare class ButtonNodeView extends NodeView {
19
19
  private button;
20
20
  private stateViews;
21
21
  private readonly interaction;
22
- private readonly sounds;
22
+ private readonly audio;
23
+ private readonly nodeId;
23
24
  private soundAssetIds;
24
25
  private enabledState;
25
- constructor(node: ButtonNode, textures: ReadonlyMap<string, Texture> | undefined, interaction: SceneInteractionMode, sounds?: ReadonlyMap<string, Sound>);
26
+ constructor(node: ButtonNode, textures: ReadonlyMap<string, Texture> | undefined, interaction: SceneInteractionMode, audio?: SceneAudio);
26
27
  /**
27
28
  * Invisible (alpha 0) but still hit-testable: Pixi's `containsPoint` hit-tests the fill's geometry
28
29
  * regardless of its alpha. Painted with a real size *before* the view ever reaches `FancyButton`:
@@ -1 +1 @@
1
- {"version":3,"file":"ButtonNodeView.d.ts","sourceRoot":"","sources":["../../src/views/ButtonNodeView.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,cAAc,EAAE,KAAK,aAAa,EAAE,KAAK,MAAM,EAAE,MAAM,wBAAwB,CAAC;AACjH,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAgD,OAAO,EAAE,MAAM,SAAS,CAAC;AAChF,OAAO,EAAE,QAAQ,EAAE,KAAK,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAEpE,MAAM,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,EAAE;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC,CAAC;AAK7D;;;;;;;;GAQG;AACH,qBAAa,cAAe,SAAQ,QAAQ;IAC1C,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,UAAU,CAAqC;IACvD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAuB;IACnD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAyC;IAChE,OAAO,CAAC,aAAa,CAAuB;IAC5C,OAAO,CAAC,YAAY,CAAU;IAE9B,YAAY,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,KAAK,CAAC,EAQvJ;IAED;;;;;;OAMG;IACH,OAAO,CAAC,MAAM,CAAC,gBAAgB;IAI/B,OAAO,CAAC,MAAM,CAAC,eAAe;IAW9B,OAAO,CAAC,MAAM,CAAC,oBAAoB;IAKnC;;;;;;;;OAQG;IACH,OAAO,CAAC,WAAW;IA+BnB,uGAAuG;IACvG,OAAO,CAAC,YAAY;IAMpB,SAAS,CAAC,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,WAAW,CAAC,GAAG,IAAI,CAmDxE;IAED,2FAA2F;IAC3F,gBAAgB,CAAC,SAAS,EAAE,aAAa,GAAG,IAAI,CAS/C;IAED,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,IAAI,OAAO,CAAC,KAAK,EAAE,OAAO,EAEzB;IAED,IAAI,KAAK,IAAI,cAAc,CAE1B;IAED,mGAAmG;IACnG,QAAQ,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,CAEpC;IAED,IAAI,OAAO,IAAI,WAAW,CAAC,SAAS,CAAC,CAAgC;IACrE,IAAI,MAAM,IAAI,WAAW,CAAC,QAAQ,CAAC,CAA+B;IAClE,IAAI,IAAI,IAAI,WAAW,CAAC,MAAM,CAAC,CAA6B;IAC5D,IAAI,OAAO,IAAI,WAAW,CAAC,SAAS,CAAC,CAAgC;IACrE,IAAI,KAAK,IAAI,WAAW,CAAC,OAAO,CAAC,CAA8B;CAChE"}
1
+ {"version":3,"file":"ButtonNodeView.d.ts","sourceRoot":"","sources":["../../src/views/ButtonNodeView.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,cAAc,EAAE,KAAK,aAAa,EAAE,KAAK,MAAM,EAAE,MAAM,wBAAwB,CAAC;AACjH,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAgD,OAAO,EAAE,MAAM,SAAS,CAAC;AAChF,OAAO,EAAE,QAAQ,EAAE,KAAK,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACpE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,MAAM,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,EAAE;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC,CAAC;AAK7D;;;;;;;;GAQG;AACH,qBAAa,cAAe,SAAQ,QAAQ;IAC1C,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,UAAU,CAAqC;IACvD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAuB;IACnD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAyB;IAC/C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,aAAa,CAAuB;IAC5C,OAAO,CAAC,YAAY,CAAU;IAE9B,YAAY,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAAE,WAAW,EAAE,oBAAoB,EAAE,KAAK,CAAC,EAAE,UAAU,EAStI;IAED;;;;;;OAMG;IACH,OAAO,CAAC,MAAM,CAAC,gBAAgB;IAI/B,OAAO,CAAC,MAAM,CAAC,eAAe;IAW9B,OAAO,CAAC,MAAM,CAAC,oBAAoB;IAKnC;;;;;;;;OAQG;IACH,OAAO,CAAC,WAAW;IAgCnB,uGAAuG;IACvG,OAAO,CAAC,YAAY;IAMpB,SAAS,CAAC,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,WAAW,CAAC,GAAG,IAAI,CAmDxE;IAED,2FAA2F;IAC3F,gBAAgB,CAAC,SAAS,EAAE,aAAa,GAAG,IAAI,CAS/C;IAED,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,IAAI,OAAO,CAAC,KAAK,EAAE,OAAO,EAEzB;IAED,IAAI,KAAK,IAAI,cAAc,CAE1B;IAED,mGAAmG;IACnG,QAAQ,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,CAEpC;IAED,IAAI,OAAO,IAAI,WAAW,CAAC,SAAS,CAAC,CAAgC;IACrE,IAAI,MAAM,IAAI,WAAW,CAAC,QAAQ,CAAC,CAA+B;IAClE,IAAI,IAAI,IAAI,WAAW,CAAC,MAAM,CAAC,CAA6B;IAC5D,IAAI,OAAO,IAAI,WAAW,CAAC,SAAS,CAAC,CAAgC;IACrE,IAAI,KAAK,IAAI,WAAW,CAAC,OAAO,CAAC,CAA8B;CAChE"}
@@ -17,13 +17,15 @@ export class ButtonNodeView extends NodeView {
17
17
  button;
18
18
  stateViews;
19
19
  interaction;
20
- sounds;
20
+ audio;
21
+ nodeId;
21
22
  soundAssetIds;
22
23
  enabledState;
23
- constructor(node, textures, interaction, sounds) {
24
+ constructor(node, textures, interaction, audio) {
24
25
  super(textures);
25
26
  this.interaction = interaction;
26
- this.sounds = sounds;
27
+ this.audio = audio;
28
+ this.nodeId = node.id;
27
29
  this.soundAssetIds = node.sounds;
28
30
  this.enabledState = node.enabled;
29
31
  this.buildButton(node);
@@ -84,11 +86,10 @@ export class ButtonNodeView extends NodeView {
84
86
  // Выделение и drag при этом не страдают: попадание ловит hitArea базового NodeView, а не это поддерево.
85
87
  if (this.interaction === "authoring")
86
88
  button.eventMode = "none";
87
- else if (this.sounds !== undefined) {
88
- button.onPress.connect(() => { const result = this.soundAssetIds?.pressAssetId === undefined ? undefined : this.sounds?.get(this.soundAssetIds.pressAssetId)?.play(); if (result instanceof Promise)
89
- void result.catch(() => undefined); });
90
- button.onHover.connect(() => { const result = this.soundAssetIds?.hoverAssetId === undefined ? undefined : this.sounds?.get(this.soundAssetIds.hoverAssetId)?.play(); if (result instanceof Promise)
91
- void result.catch(() => undefined); });
89
+ else if (this.audio !== undefined) {
90
+ // Вьюха только объявляет, что произошло: играть или нет решает подписчик шины (см. audio/bus.ts).
91
+ button.onPress.connect(() => this.audio?.cue("button.press", this.nodeId, this.soundAssetIds?.pressAssetId));
92
+ button.onHover.connect(() => this.audio?.cue("button.hover", this.nodeId, this.soundAssetIds?.hoverAssetId));
92
93
  }
93
94
  this.button = button;
94
95
  this.stateViews = stateViews;
@@ -1 +1 @@
1
- {"version":3,"file":"ButtonNodeView.js","sourceRoot":"","sources":["../../src/views/ButtonNodeView.ts"],"names":[],"mappings":"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","sourcesContent":["import { BUTTON_STATE_KEYS, type ButtonStateKey, type LayoutPadding, type UINode } from \"@pixi-ui-editor/schema\";\r\nimport { FancyButton } from \"@pixi/ui\";\r\nimport type { Sound } from \"@pixi/sound\";\r\nimport { Container, Graphics, NineSliceSprite, Sprite, Texture } from \"pixi.js\";\r\nimport { NodeView, type SceneInteractionMode } from \"./NodeView.js\";\r\n\r\nexport type ButtonNode = Extract<UINode, { type: \"button\" }>;\r\n\r\nconst FANCY_STATE_BY_KEY = { normal: \"default\", hover: \"hover\", pressed: \"pressed\", disabled: \"disabled\" } as const;\r\nconst KEY_BY_FANCY_STATE = { default: \"normal\", hover: \"hover\", pressed: \"pressed\", disabled: \"disabled\" } as const;\r\n\r\n/**\r\n * Adapts a button node to `@pixi/ui`'s `FancyButton`, which owns the pointer state machine —\r\n * this class never reimplements it. Optional states fall back to the normal image, and runtime\r\n * changes to `enabled` or the current state stay in the view: they never touch the document.\r\n *\r\n * `nineSlice`, when set, applies the same borders to all four state views (`NineSliceSprite`\r\n * instead of `Sprite`) — the button's frame shape is normally the same regardless of which state\r\n * image is currently shown.\r\n */\r\nexport class ButtonNodeView extends NodeView {\r\n private button!: FancyButton;\r\n private stateViews!: Record<ButtonStateKey, Container>;\r\n private readonly interaction: SceneInteractionMode;\r\n private readonly sounds: ReadonlyMap<string, Sound> | undefined;\r\n private soundAssetIds: ButtonNode[\"sounds\"];\r\n private enabledState: boolean;\r\n\r\n constructor(node: ButtonNode, textures: ReadonlyMap<string, Texture> | undefined, interaction: SceneInteractionMode, sounds?: ReadonlyMap<string, Sound>) {\r\n super(textures);\r\n this.interaction = interaction;\r\n this.sounds = sounds;\r\n this.soundAssetIds = node.sounds;\r\n this.enabledState = node.enabled;\r\n this.buildButton(node);\r\n this.applyEnabled(node.enabled);\r\n }\r\n\r\n /**\r\n * Invisible (alpha 0) but still hit-testable: Pixi's `containsPoint` hit-tests the fill's geometry\r\n * regardless of its alpha. Painted with a real size *before* the view ever reaches `FancyButton`:\r\n * `FancyButton` reads `defaultView`'s bounds exactly once, synchronously during construction, to\r\n * freeze its own `hitArea` — it never re-reads them afterwards. A `Graphics` still at its default\r\n * (0, 0) size at that moment would freeze a zero-size, permanently unclickable hit area.\r\n */\r\n private static paintPlaceholder(graphics: Graphics, width: number, height: number): void {\r\n graphics.clear().rect(0, 0, width, height).fill({ color: 0x000000, alpha: 0 });\r\n }\r\n\r\n private static createStateView(texture: Texture | undefined, nineSlice: LayoutPadding | undefined, size: { width: number; height: number }): Container {\r\n if (texture === undefined) {\r\n const graphics = new Graphics();\r\n ButtonNodeView.paintPlaceholder(graphics, size.width, size.height);\r\n return graphics;\r\n }\r\n return nineSlice === undefined\r\n ? new Sprite(texture)\r\n : new NineSliceSprite({ texture, leftWidth: nineSlice.left, topHeight: nineSlice.top, rightWidth: nineSlice.right, bottomHeight: nineSlice.bottom });\r\n }\r\n\r\n private static applyStateAppearance(view: Container, node: ButtonNode, state: ButtonStateKey): void {\r\n view.tint = node.states[`${state}Tint`] ?? \"#ffffff\";\r\n view.alpha = node.states[`${state}Opacity`] ?? 1;\r\n }\r\n\r\n /**\r\n * (Re)builds `FancyButton` and its four state views. `FancyButton` has no API to replace a view\r\n * after construction, so any change to a view's *type* — nine-slice toggled, or an asset\r\n * finishing an async load — goes through here instead of `syncContent`'s cheap in-place path.\r\n *\r\n * `size` is the best size known *right now*: the resolved layout rectangle when called from\r\n * `syncContent`, or the authored transform when called from the constructor (before any layout\r\n * pass has run). Only feeds the initial placeholder paint above — see its doc comment for why.\r\n */\r\n private buildButton(node: ButtonNode, size?: { width: number; height: number }): void {\r\n const nineSlice = node.nineSlice;\r\n const resolvedSize = size ?? { width: node.transform.width, height: node.transform.height };\r\n const normalTexture = this.textureFor(node.states.normalAssetId);\r\n const stateViews = {} as Record<ButtonStateKey, Container>;\r\n const viewFor = (state: ButtonStateKey, assetId: string | undefined): Container => {\r\n const texture = (assetId === undefined ? undefined : this.textureFor(assetId)) ?? normalTexture;\r\n const view = ButtonNodeView.createStateView(texture, nineSlice, resolvedSize);\r\n ButtonNodeView.applyStateAppearance(view, node, state);\r\n stateViews[state] = view;\r\n return view;\r\n };\r\n\r\n const button = new FancyButton({\r\n defaultView: viewFor(\"normal\", node.states.normalAssetId),\r\n hoverView: viewFor(\"hover\", node.states.hoverAssetId),\r\n pressedView: viewFor(\"pressed\", node.states.pressedAssetId),\r\n disabledView: viewFor(\"disabled\", node.states.disabledAssetId),\r\n });\r\n // Authoring-сцена инертна: FancyButton уже включил себе eventMode \"static\", снимаем его до applyEnabled.\r\n // Выделение и drag при этом не страдают: попадание ловит hitArea базового NodeView, а не это поддерево.\r\n if (this.interaction === \"authoring\") button.eventMode = \"none\";\r\n else if (this.sounds !== undefined) {\r\n button.onPress.connect(() => { const result = this.soundAssetIds?.pressAssetId === undefined ? undefined : this.sounds?.get(this.soundAssetIds.pressAssetId)?.play(); if (result instanceof Promise) void result.catch(() => undefined); });\r\n button.onHover.connect(() => { const result = this.soundAssetIds?.hoverAssetId === undefined ? undefined : this.sounds?.get(this.soundAssetIds.hoverAssetId)?.play(); if (result instanceof Promise) void result.catch(() => undefined); });\r\n }\r\n this.button = button;\r\n this.stateViews = stateViews;\r\n this.setContent(button);\r\n }\r\n\r\n /** In authoring mode `enabled` may only drive the visuals: `FancyButton` couples it to `eventMode`. */\r\n private applyEnabled(enabled: boolean): void {\r\n this.enabledState = enabled;\r\n if (this.interaction === \"runtime\") this.button.enabled = enabled;\r\n else this.button.setState(enabled ? \"default\" : \"disabled\");\r\n }\r\n\r\n protected syncContent(node: UINode, transform: UINode[\"transform\"]): void {\r\n if (node.type !== \"button\") return;\r\n this.soundAssetIds = node.sounds;\r\n const nineSlice = node.nineSlice;\r\n const normalTexture = this.textureFor(node.states.normalAssetId);\r\n\r\n // A state view's required *type* (Graphics/Sprite/NineSliceSprite) may no longer match what's\r\n // needed — nine-slice toggled, or a texture finished loading after this view had to fall back\r\n // to Graphics. FancyButton can't swap a view after construction, so that goes through a full\r\n // rebuild; everything else (texture identity, border values, size) updates the live views in\r\n // place, which is the path a nine-slice gizmo drag runs every frame.\r\n let needsRebuild = false;\r\n for (const state of BUTTON_STATE_KEYS) {\r\n const assetId = node.states[`${state}AssetId`];\r\n const texture = (assetId === undefined ? undefined : this.textureFor(assetId)) ?? normalTexture;\r\n const view = this.stateViews[state];\r\n const wantsNineSlice = texture !== undefined && nineSlice !== undefined;\r\n const matches = texture === undefined ? view instanceof Graphics : wantsNineSlice ? view instanceof NineSliceSprite : view instanceof Sprite && !(view instanceof NineSliceSprite);\r\n if (!matches) { needsRebuild = true; break; }\r\n }\r\n\r\n if (needsRebuild) {\r\n this.buildButton(node, transform);\r\n } else {\r\n for (const state of BUTTON_STATE_KEYS) {\r\n const view = this.stateViews[state];\r\n const assetId = node.states[`${state}AssetId`];\r\n const texture = (assetId === undefined ? undefined : this.textureFor(assetId)) ?? normalTexture;\r\n // Set the texture before the layout size: Sprite/NineSliceSprite preserve scale when their\r\n // texture changes, so sizing first would shift visual bounds for a differently-sized source.\r\n if (view instanceof NineSliceSprite) {\r\n if (texture !== undefined && view.texture !== texture) view.texture = texture;\r\n if (nineSlice !== undefined) {\r\n view.leftWidth = nineSlice.left;\r\n view.topHeight = nineSlice.top;\r\n view.rightWidth = nineSlice.right;\r\n view.bottomHeight = nineSlice.bottom;\r\n }\r\n view.setSize(transform.width, transform.height);\r\n } else if (view instanceof Sprite) {\r\n if (texture !== undefined && view.texture !== texture) view.texture = texture;\r\n view.setSize(transform.width, transform.height);\r\n } else if (view instanceof Graphics) {\r\n ButtonNodeView.paintPlaceholder(view, transform.width, transform.height);\r\n }\r\n ButtonNodeView.applyStateAppearance(view, node, state);\r\n }\r\n }\r\n\r\n // Только на изменение документа: иначе любой пересчёт layout сбрасывал бы transient preview state.\r\n if (node.enabled !== this.enabledState) this.applyEnabled(node.enabled);\r\n }\r\n\r\n /** Editor-only live preview of nine-slice border edits while dragging the canvas gizmo. */\r\n previewNineSlice(nineSlice: LayoutPadding): void {\r\n for (const state of BUTTON_STATE_KEYS) {\r\n const view = this.stateViews[state];\r\n if (!(view instanceof NineSliceSprite)) continue;\r\n view.leftWidth = nineSlice.left;\r\n view.topHeight = nineSlice.top;\r\n view.rightWidth = nineSlice.right;\r\n view.bottomHeight = nineSlice.bottom;\r\n }\r\n }\r\n\r\n get enabled(): boolean {\r\n return this.enabledState;\r\n }\r\n\r\n set enabled(value: boolean) {\r\n this.applyEnabled(value);\r\n }\r\n\r\n get state(): ButtonStateKey {\r\n return KEY_BY_FANCY_STATE[this.button.state];\r\n }\r\n\r\n /** Forces a visual state without changing `enabled`, so a disabled button still emits no press. */\r\n setState(state: ButtonStateKey): void {\r\n this.button.setState(FANCY_STATE_BY_KEY[state]);\r\n }\r\n\r\n get onPress(): FancyButton[\"onPress\"] { return this.button.onPress; }\r\n get onDown(): FancyButton[\"onDown\"] { return this.button.onDown; }\r\n get onUp(): FancyButton[\"onUp\"] { return this.button.onUp; }\r\n get onHover(): FancyButton[\"onHover\"] { return this.button.onHover; }\r\n get onOut(): FancyButton[\"onOut\"] { return this.button.onOut; }\r\n}\r\n"]}
1
+ {"version":3,"file":"ButtonNodeView.js","sourceRoot":"","sources":["../../src/views/ButtonNodeView.ts"],"names":[],"mappings":"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","sourcesContent":["import { BUTTON_STATE_KEYS, type ButtonStateKey, type LayoutPadding, type UINode } from \"@pixi-ui-editor/schema\";\r\nimport { FancyButton } from \"@pixi/ui\";\r\nimport { Container, Graphics, NineSliceSprite, Sprite, Texture } from \"pixi.js\";\r\nimport { NodeView, type SceneInteractionMode } from \"./NodeView.js\";\r\nimport type { SceneAudio } from \"../audio/bus.js\";\r\n\r\nexport type ButtonNode = Extract<UINode, { type: \"button\" }>;\r\n\r\nconst FANCY_STATE_BY_KEY = { normal: \"default\", hover: \"hover\", pressed: \"pressed\", disabled: \"disabled\" } as const;\r\nconst KEY_BY_FANCY_STATE = { default: \"normal\", hover: \"hover\", pressed: \"pressed\", disabled: \"disabled\" } as const;\r\n\r\n/**\r\n * Adapts a button node to `@pixi/ui`'s `FancyButton`, which owns the pointer state machine —\r\n * this class never reimplements it. Optional states fall back to the normal image, and runtime\r\n * changes to `enabled` or the current state stay in the view: they never touch the document.\r\n *\r\n * `nineSlice`, when set, applies the same borders to all four state views (`NineSliceSprite`\r\n * instead of `Sprite`) — the button's frame shape is normally the same regardless of which state\r\n * image is currently shown.\r\n */\r\nexport class ButtonNodeView extends NodeView {\r\n private button!: FancyButton;\r\n private stateViews!: Record<ButtonStateKey, Container>;\r\n private readonly interaction: SceneInteractionMode;\r\n private readonly audio: SceneAudio | undefined;\r\n private readonly nodeId: string;\r\n private soundAssetIds: ButtonNode[\"sounds\"];\r\n private enabledState: boolean;\r\n\r\n constructor(node: ButtonNode, textures: ReadonlyMap<string, Texture> | undefined, interaction: SceneInteractionMode, audio?: SceneAudio) {\r\n super(textures);\r\n this.interaction = interaction;\r\n this.audio = audio;\r\n this.nodeId = node.id;\r\n this.soundAssetIds = node.sounds;\r\n this.enabledState = node.enabled;\r\n this.buildButton(node);\r\n this.applyEnabled(node.enabled);\r\n }\r\n\r\n /**\r\n * Invisible (alpha 0) but still hit-testable: Pixi's `containsPoint` hit-tests the fill's geometry\r\n * regardless of its alpha. Painted with a real size *before* the view ever reaches `FancyButton`:\r\n * `FancyButton` reads `defaultView`'s bounds exactly once, synchronously during construction, to\r\n * freeze its own `hitArea` — it never re-reads them afterwards. A `Graphics` still at its default\r\n * (0, 0) size at that moment would freeze a zero-size, permanently unclickable hit area.\r\n */\r\n private static paintPlaceholder(graphics: Graphics, width: number, height: number): void {\r\n graphics.clear().rect(0, 0, width, height).fill({ color: 0x000000, alpha: 0 });\r\n }\r\n\r\n private static createStateView(texture: Texture | undefined, nineSlice: LayoutPadding | undefined, size: { width: number; height: number }): Container {\r\n if (texture === undefined) {\r\n const graphics = new Graphics();\r\n ButtonNodeView.paintPlaceholder(graphics, size.width, size.height);\r\n return graphics;\r\n }\r\n return nineSlice === undefined\r\n ? new Sprite(texture)\r\n : new NineSliceSprite({ texture, leftWidth: nineSlice.left, topHeight: nineSlice.top, rightWidth: nineSlice.right, bottomHeight: nineSlice.bottom });\r\n }\r\n\r\n private static applyStateAppearance(view: Container, node: ButtonNode, state: ButtonStateKey): void {\r\n view.tint = node.states[`${state}Tint`] ?? \"#ffffff\";\r\n view.alpha = node.states[`${state}Opacity`] ?? 1;\r\n }\r\n\r\n /**\r\n * (Re)builds `FancyButton` and its four state views. `FancyButton` has no API to replace a view\r\n * after construction, so any change to a view's *type* — nine-slice toggled, or an asset\r\n * finishing an async load — goes through here instead of `syncContent`'s cheap in-place path.\r\n *\r\n * `size` is the best size known *right now*: the resolved layout rectangle when called from\r\n * `syncContent`, or the authored transform when called from the constructor (before any layout\r\n * pass has run). Only feeds the initial placeholder paint above — see its doc comment for why.\r\n */\r\n private buildButton(node: ButtonNode, size?: { width: number; height: number }): void {\r\n const nineSlice = node.nineSlice;\r\n const resolvedSize = size ?? { width: node.transform.width, height: node.transform.height };\r\n const normalTexture = this.textureFor(node.states.normalAssetId);\r\n const stateViews = {} as Record<ButtonStateKey, Container>;\r\n const viewFor = (state: ButtonStateKey, assetId: string | undefined): Container => {\r\n const texture = (assetId === undefined ? undefined : this.textureFor(assetId)) ?? normalTexture;\r\n const view = ButtonNodeView.createStateView(texture, nineSlice, resolvedSize);\r\n ButtonNodeView.applyStateAppearance(view, node, state);\r\n stateViews[state] = view;\r\n return view;\r\n };\r\n\r\n const button = new FancyButton({\r\n defaultView: viewFor(\"normal\", node.states.normalAssetId),\r\n hoverView: viewFor(\"hover\", node.states.hoverAssetId),\r\n pressedView: viewFor(\"pressed\", node.states.pressedAssetId),\r\n disabledView: viewFor(\"disabled\", node.states.disabledAssetId),\r\n });\r\n // Authoring-сцена инертна: FancyButton уже включил себе eventMode \"static\", снимаем его до applyEnabled.\r\n // Выделение и drag при этом не страдают: попадание ловит hitArea базового NodeView, а не это поддерево.\r\n if (this.interaction === \"authoring\") button.eventMode = \"none\";\r\n else if (this.audio !== undefined) {\r\n // Вьюха только объявляет, что произошло: играть или нет — решает подписчик шины (см. audio/bus.ts).\r\n button.onPress.connect(() => this.audio?.cue(\"button.press\", this.nodeId, this.soundAssetIds?.pressAssetId));\r\n button.onHover.connect(() => this.audio?.cue(\"button.hover\", this.nodeId, this.soundAssetIds?.hoverAssetId));\r\n }\r\n this.button = button;\r\n this.stateViews = stateViews;\r\n this.setContent(button);\r\n }\r\n\r\n /** In authoring mode `enabled` may only drive the visuals: `FancyButton` couples it to `eventMode`. */\r\n private applyEnabled(enabled: boolean): void {\r\n this.enabledState = enabled;\r\n if (this.interaction === \"runtime\") this.button.enabled = enabled;\r\n else this.button.setState(enabled ? \"default\" : \"disabled\");\r\n }\r\n\r\n protected syncContent(node: UINode, transform: UINode[\"transform\"]): void {\r\n if (node.type !== \"button\") return;\r\n this.soundAssetIds = node.sounds;\r\n const nineSlice = node.nineSlice;\r\n const normalTexture = this.textureFor(node.states.normalAssetId);\r\n\r\n // A state view's required *type* (Graphics/Sprite/NineSliceSprite) may no longer match what's\r\n // needed — nine-slice toggled, or a texture finished loading after this view had to fall back\r\n // to Graphics. FancyButton can't swap a view after construction, so that goes through a full\r\n // rebuild; everything else (texture identity, border values, size) updates the live views in\r\n // place, which is the path a nine-slice gizmo drag runs every frame.\r\n let needsRebuild = false;\r\n for (const state of BUTTON_STATE_KEYS) {\r\n const assetId = node.states[`${state}AssetId`];\r\n const texture = (assetId === undefined ? undefined : this.textureFor(assetId)) ?? normalTexture;\r\n const view = this.stateViews[state];\r\n const wantsNineSlice = texture !== undefined && nineSlice !== undefined;\r\n const matches = texture === undefined ? view instanceof Graphics : wantsNineSlice ? view instanceof NineSliceSprite : view instanceof Sprite && !(view instanceof NineSliceSprite);\r\n if (!matches) { needsRebuild = true; break; }\r\n }\r\n\r\n if (needsRebuild) {\r\n this.buildButton(node, transform);\r\n } else {\r\n for (const state of BUTTON_STATE_KEYS) {\r\n const view = this.stateViews[state];\r\n const assetId = node.states[`${state}AssetId`];\r\n const texture = (assetId === undefined ? undefined : this.textureFor(assetId)) ?? normalTexture;\r\n // Set the texture before the layout size: Sprite/NineSliceSprite preserve scale when their\r\n // texture changes, so sizing first would shift visual bounds for a differently-sized source.\r\n if (view instanceof NineSliceSprite) {\r\n if (texture !== undefined && view.texture !== texture) view.texture = texture;\r\n if (nineSlice !== undefined) {\r\n view.leftWidth = nineSlice.left;\r\n view.topHeight = nineSlice.top;\r\n view.rightWidth = nineSlice.right;\r\n view.bottomHeight = nineSlice.bottom;\r\n }\r\n view.setSize(transform.width, transform.height);\r\n } else if (view instanceof Sprite) {\r\n if (texture !== undefined && view.texture !== texture) view.texture = texture;\r\n view.setSize(transform.width, transform.height);\r\n } else if (view instanceof Graphics) {\r\n ButtonNodeView.paintPlaceholder(view, transform.width, transform.height);\r\n }\r\n ButtonNodeView.applyStateAppearance(view, node, state);\r\n }\r\n }\r\n\r\n // Только на изменение документа: иначе любой пересчёт layout сбрасывал бы transient preview state.\r\n if (node.enabled !== this.enabledState) this.applyEnabled(node.enabled);\r\n }\r\n\r\n /** Editor-only live preview of nine-slice border edits while dragging the canvas gizmo. */\r\n previewNineSlice(nineSlice: LayoutPadding): void {\r\n for (const state of BUTTON_STATE_KEYS) {\r\n const view = this.stateViews[state];\r\n if (!(view instanceof NineSliceSprite)) continue;\r\n view.leftWidth = nineSlice.left;\r\n view.topHeight = nineSlice.top;\r\n view.rightWidth = nineSlice.right;\r\n view.bottomHeight = nineSlice.bottom;\r\n }\r\n }\r\n\r\n get enabled(): boolean {\r\n return this.enabledState;\r\n }\r\n\r\n set enabled(value: boolean) {\r\n this.applyEnabled(value);\r\n }\r\n\r\n get state(): ButtonStateKey {\r\n return KEY_BY_FANCY_STATE[this.button.state];\r\n }\r\n\r\n /** Forces a visual state without changing `enabled`, so a disabled button still emits no press. */\r\n setState(state: ButtonStateKey): void {\r\n this.button.setState(FANCY_STATE_BY_KEY[state]);\r\n }\r\n\r\n get onPress(): FancyButton[\"onPress\"] { return this.button.onPress; }\r\n get onDown(): FancyButton[\"onDown\"] { return this.button.onDown; }\r\n get onUp(): FancyButton[\"onUp\"] { return this.button.onUp; }\r\n get onHover(): FancyButton[\"onHover\"] { return this.button.onHover; }\r\n get onOut(): FancyButton[\"onOut\"] { return this.button.onOut; }\r\n}\r\n"]}
@@ -1,8 +1,8 @@
1
1
  import { type CheckboxStateKey, type UINode } from "@pixi-ui-editor/schema";
2
2
  import { CheckBox } from "@pixi/ui";
3
- import type { Sound } from "@pixi/sound";
4
3
  import { Texture } from "pixi.js";
5
4
  import { NodeView, type SceneInteractionMode } from "./NodeView.js";
5
+ import type { SceneAudio } from "../audio/bus.js";
6
6
  export type CheckboxNode = Extract<UINode, {
7
7
  type: "checkbox";
8
8
  }>;
@@ -20,7 +20,8 @@ export type CheckboxNode = Extract<UINode, {
20
20
  export declare class CheckboxNodeView extends NodeView {
21
21
  private readonly checkbox;
22
22
  private readonly interaction;
23
- private readonly sounds;
23
+ private readonly audio;
24
+ private readonly nodeId;
24
25
  private soundAssetIds;
25
26
  private uncheckedTexture;
26
27
  private checkedTexture;
@@ -28,7 +29,7 @@ export declare class CheckboxNodeView extends NodeView {
28
29
  private checkedHoverTexture;
29
30
  private enabledState;
30
31
  private hovering;
31
- constructor(node: CheckboxNode, textures: ReadonlyMap<string, Texture> | undefined, interaction: SceneInteractionMode, sounds?: ReadonlyMap<string, Sound>);
32
+ constructor(node: CheckboxNode, textures: ReadonlyMap<string, Texture> | undefined, interaction: SceneInteractionMode, audio?: SceneAudio);
32
33
  private hoverTextureFor;
33
34
  /** Puts the current hover/non-hover texture on both internal Sprites; switching visibility is Switcher's job. */
34
35
  private applyTextures;
@@ -1 +1 @@
1
- {"version":3,"file":"CheckboxNodeView.d.ts","sourceRoot":"","sources":["../../src/views/CheckboxNodeView.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,gBAAgB,EAAE,KAAK,MAAM,EAAE,MAAM,wBAAwB,CAAC;AACjG,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAU,OAAO,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,KAAK,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAEpE,MAAM,MAAM,YAAY,GAAG,OAAO,CAAC,MAAM,EAAE;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC,CAAC;AAEjE;;;;;;;;;;GAUG;AACH,qBAAa,gBAAiB,SAAQ,QAAQ;IAC5C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAW;IACpC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAuB;IACnD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAyC;IAChE,OAAO,CAAC,aAAa,CAAyB;IAC9C,OAAO,CAAC,gBAAgB,CAAU;IAClC,OAAO,CAAC,cAAc,CAAU;IAChC,OAAO,CAAC,qBAAqB,CAAU;IACvC,OAAO,CAAC,mBAAmB,CAAU;IACrC,OAAO,CAAC,YAAY,CAAU;IAC9B,OAAO,CAAC,QAAQ,CAAS;IAEzB,YAAY,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,KAAK,CAAC,EAiCzJ;IAED,OAAO,CAAC,eAAe;IAIvB,iHAAiH;IACjH,OAAO,CAAC,aAAa;IAMrB,4GAA4G;IAC5G,OAAO,CAAC,YAAY;IAMpB,SAAS,CAAC,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,WAAW,CAAC,GAAG,IAAI,CAsBxE;IAED,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,IAAI,OAAO,CAAC,KAAK,EAAE,OAAO,EAEzB;IAED,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,IAAI,OAAO,CAAC,KAAK,EAAE,OAAO,EAEzB;IAED,uGAAuG;IACvG,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAEjC;IAED,IAAI,KAAK,IAAI,gBAAgB,CAE5B;IAED,IAAI,OAAO,IAAI,QAAQ,CAAC,SAAS,CAAC,CAAkC;CACrE"}
1
+ {"version":3,"file":"CheckboxNodeView.d.ts","sourceRoot":"","sources":["../../src/views/CheckboxNodeView.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,gBAAgB,EAAE,KAAK,MAAM,EAAE,MAAM,wBAAwB,CAAC;AACjG,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,EAAU,OAAO,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,KAAK,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACpE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,MAAM,MAAM,YAAY,GAAG,OAAO,CAAC,MAAM,EAAE;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC,CAAC;AAEjE;;;;;;;;;;GAUG;AACH,qBAAa,gBAAiB,SAAQ,QAAQ;IAC5C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAW;IACpC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAuB;IACnD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAyB;IAC/C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,aAAa,CAAyB;IAC9C,OAAO,CAAC,gBAAgB,CAAU;IAClC,OAAO,CAAC,cAAc,CAAU;IAChC,OAAO,CAAC,qBAAqB,CAAU;IACvC,OAAO,CAAC,mBAAmB,CAAU;IACrC,OAAO,CAAC,YAAY,CAAU;IAC9B,OAAO,CAAC,QAAQ,CAAS;IAEzB,YAAY,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAAE,WAAW,EAAE,oBAAoB,EAAE,KAAK,CAAC,EAAE,UAAU,EAiCxI;IAED,OAAO,CAAC,eAAe;IAIvB,iHAAiH;IACjH,OAAO,CAAC,aAAa;IAMrB,4GAA4G;IAC5G,OAAO,CAAC,YAAY;IAMpB,SAAS,CAAC,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,WAAW,CAAC,GAAG,IAAI,CAsBxE;IAED,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,IAAI,OAAO,CAAC,KAAK,EAAE,OAAO,EAEzB;IAED,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,IAAI,OAAO,CAAC,KAAK,EAAE,OAAO,EAEzB;IAED,uGAAuG;IACvG,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAEjC;IAED,IAAI,KAAK,IAAI,gBAAgB,CAE5B;IAED,IAAI,OAAO,IAAI,QAAQ,CAAC,SAAS,CAAC,CAAkC;CACrE"}
@@ -16,7 +16,8 @@ import { NodeView } from "./NodeView.js";
16
16
  export class CheckboxNodeView extends NodeView {
17
17
  checkbox;
18
18
  interaction;
19
- sounds;
19
+ audio;
20
+ nodeId;
20
21
  soundAssetIds;
21
22
  uncheckedTexture;
22
23
  checkedTexture;
@@ -24,10 +25,11 @@ export class CheckboxNodeView extends NodeView {
24
25
  checkedHoverTexture;
25
26
  enabledState;
26
27
  hovering = false;
27
- constructor(node, textures, interaction, sounds) {
28
+ constructor(node, textures, interaction, audio) {
28
29
  super(textures);
29
30
  this.interaction = interaction;
30
- this.sounds = sounds;
31
+ this.audio = audio;
32
+ this.nodeId = node.id;
31
33
  this.soundAssetIds = node.sounds;
32
34
  const unchecked = this.textureFor(node.states.uncheckedAssetId) ?? Texture.WHITE;
33
35
  const checked = this.textureFor(node.states.checkedAssetId) ?? Texture.WHITE;
@@ -47,12 +49,10 @@ export class CheckboxNodeView extends NodeView {
47
49
  else {
48
50
  this.checkbox.innerView.on("pointerover", () => { this.hovering = true; this.applyTextures(); });
49
51
  this.checkbox.innerView.on("pointerout", () => { this.hovering = false; this.applyTextures(); });
50
- if (sounds !== undefined) {
52
+ if (audio !== undefined) {
51
53
  this.checkbox.onCheck.connect((checkedState) => {
52
54
  const assetId = checkedState ? this.soundAssetIds?.checkAssetId : this.soundAssetIds?.uncheckAssetId;
53
- const result = assetId === undefined ? undefined : this.sounds?.get(assetId)?.play();
54
- if (result instanceof Promise)
55
- void result.catch(() => undefined);
55
+ this.audio?.cue(checkedState ? "checkbox.check" : "checkbox.uncheck", this.nodeId, assetId);
56
56
  });
57
57
  }
58
58
  }
@@ -1 +1 @@
1
- {"version":3,"file":"CheckboxNodeView.js","sourceRoot":"","sources":["../../src/views/CheckboxNodeView.ts"],"names":[],"mappings":"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","sourcesContent":["import { CHECKBOX_STATE_KEYS, type CheckboxStateKey, type UINode } from \"@pixi-ui-editor/schema\";\r\nimport { CheckBox } from \"@pixi/ui\";\r\nimport type { Sound } from \"@pixi/sound\";\r\nimport { Sprite, Texture } from \"pixi.js\";\r\nimport { NodeView, type SceneInteractionMode } from \"./NodeView.js\";\r\n\r\nexport type CheckboxNode = Extract<UINode, { type: \"checkbox\" }>;\r\n\r\n/**\r\n * Adapts a checkbox node to `@pixi/ui`'s `CheckBox`, which owns the checked/unchecked switching —\r\n * this class never reimplements it. `group`-based radio exclusivity is wired one layer up, in\r\n * `wireCheckboxGroups` (see scene.ts): this view only exposes `forceCheck` so that wiring can flip\r\n * a sibling without re-emitting `onCheck` and recursing back into itself.\r\n *\r\n * Hover is layered on top of `CheckBox` by hand: unlike `FancyButton`, `CheckBox`/`Switcher` only\r\n * switches between its checked/unchecked views and has no hover state slot of its own. Both of its\r\n * internal Sprites always carry the texture matching the current hover flag — whichever one is\r\n * `visible` at any moment is Switcher's concern, not ours.\r\n */\r\nexport class CheckboxNodeView extends NodeView {\r\n private readonly checkbox: CheckBox;\r\n private readonly interaction: SceneInteractionMode;\r\n private readonly sounds: ReadonlyMap<string, Sound> | undefined;\r\n private soundAssetIds: CheckboxNode[\"sounds\"];\r\n private uncheckedTexture: Texture;\r\n private checkedTexture: Texture;\r\n private uncheckedHoverTexture: Texture;\r\n private checkedHoverTexture: Texture;\r\n private enabledState: boolean;\r\n private hovering = false;\r\n\r\n constructor(node: CheckboxNode, textures: ReadonlyMap<string, Texture> | undefined, interaction: SceneInteractionMode, sounds?: ReadonlyMap<string, Sound>) {\r\n super(textures);\r\n this.interaction = interaction;\r\n this.sounds = sounds;\r\n this.soundAssetIds = node.sounds;\r\n const unchecked = this.textureFor(node.states.uncheckedAssetId) ?? Texture.WHITE;\r\n const checked = this.textureFor(node.states.checkedAssetId) ?? Texture.WHITE;\r\n this.uncheckedTexture = unchecked;\r\n this.checkedTexture = checked;\r\n this.uncheckedHoverTexture = this.hoverTextureFor(node.states.uncheckedHoverAssetId, unchecked);\r\n this.checkedHoverTexture = this.hoverTextureFor(node.states.checkedHoverAssetId, checked);\r\n this.checkbox = new CheckBox({\r\n checked: node.defaultChecked,\r\n style: { unchecked, checked },\r\n });\r\n // Authoring-сцена инертна, как и у button: eventMode \"none\" на верхнем контейнере отключает\r\n // hit-testing всего поддерева, включая `innerView`, который Switcher сам сделал \"static\" — а\r\n // значит и hover в authoring никогда не наступает, так что его незачем отдельно отключать.\r\n if (interaction === \"authoring\") this.checkbox.eventMode = \"none\";\r\n else {\r\n this.checkbox.innerView.on(\"pointerover\", () => { this.hovering = true; this.applyTextures(); });\r\n this.checkbox.innerView.on(\"pointerout\", () => { this.hovering = false; this.applyTextures(); });\r\n if (sounds !== undefined) {\r\n this.checkbox.onCheck.connect((checkedState) => {\r\n const assetId = checkedState ? this.soundAssetIds?.checkAssetId : this.soundAssetIds?.uncheckAssetId;\r\n const result = assetId === undefined ? undefined : this.sounds?.get(assetId)?.play();\r\n if (result instanceof Promise) void result.catch(() => undefined);\r\n });\r\n }\r\n }\r\n this.enabledState = node.enabled;\r\n this.applyEnabled(node.enabled);\r\n this.setContent(this.checkbox);\r\n }\r\n\r\n private hoverTextureFor(assetId: string | undefined, fallback: Texture): Texture {\r\n return (assetId === undefined ? undefined : this.textureFor(assetId)) ?? fallback;\r\n }\r\n\r\n /** Puts the current hover/non-hover texture on both internal Sprites; switching visibility is Switcher's job. */\r\n private applyTextures(): void {\r\n const [uncheckedView, checkedView] = this.checkbox.views;\r\n if (uncheckedView instanceof Sprite) uncheckedView.texture = this.hovering ? this.uncheckedHoverTexture : this.uncheckedTexture;\r\n if (checkedView instanceof Sprite) checkedView.texture = this.hovering ? this.checkedHoverTexture : this.checkedTexture;\r\n }\r\n\r\n /** In authoring mode `enabled` may only drive selectability elsewhere: this view stays inert either way. */\r\n private applyEnabled(enabled: boolean): void {\r\n this.enabledState = enabled;\r\n if (this.interaction === \"authoring\") return;\r\n this.checkbox.eventMode = enabled ? \"static\" : \"none\";\r\n }\r\n\r\n protected syncContent(node: UINode, transform: UINode[\"transform\"]): void {\r\n if (node.type !== \"checkbox\") return;\r\n this.soundAssetIds = node.sounds;\r\n\r\n const unchecked = this.textureFor(node.states.uncheckedAssetId) ?? Texture.WHITE;\r\n const checked = this.textureFor(node.states.checkedAssetId) ?? Texture.WHITE;\r\n // `style` rebuilds both internal views, so it's only reassigned when a base texture actually\r\n // changed — same rule ButtonNodeView follows for its state Sprites. A fresh pair of Sprites\r\n // starts out holding the plain (non-hover) textures `style` was given, so `applyTextures` always\r\n // runs afterwards to restore the current hover look.\r\n if (unchecked !== this.uncheckedTexture || checked !== this.checkedTexture) {\r\n this.uncheckedTexture = unchecked;\r\n this.checkedTexture = checked;\r\n this.checkbox.style = { unchecked, checked };\r\n }\r\n this.uncheckedHoverTexture = this.hoverTextureFor(node.states.uncheckedHoverAssetId, unchecked);\r\n this.checkedHoverTexture = this.hoverTextureFor(node.states.checkedHoverAssetId, checked);\r\n this.applyTextures();\r\n for (const view of this.checkbox.views) if (view instanceof Sprite) view.setSize(transform.width, transform.height);\r\n\r\n // Только на изменение документа: иначе любой пересчёт layout сбрасывал бы transient preview state.\r\n if (node.enabled !== this.enabledState) this.applyEnabled(node.enabled);\r\n }\r\n\r\n get enabled(): boolean {\r\n return this.enabledState;\r\n }\r\n\r\n set enabled(value: boolean) {\r\n this.applyEnabled(value);\r\n }\r\n\r\n get checked(): boolean {\r\n return this.checkbox.checked;\r\n }\r\n\r\n set checked(value: boolean) {\r\n this.checkbox.checked = value;\r\n }\r\n\r\n /** Sets checked state without emitting `onCheck` — used by radio-group wiring to avoid re-entrancy. */\r\n forceCheck(checked: boolean): void {\r\n this.checkbox.forceCheck(checked);\r\n }\r\n\r\n get state(): CheckboxStateKey {\r\n return this.checkbox.checked ? CHECKBOX_STATE_KEYS[1] : CHECKBOX_STATE_KEYS[0];\r\n }\r\n\r\n get onCheck(): CheckBox[\"onCheck\"] { return this.checkbox.onCheck; }\r\n}\r\n"]}
1
+ {"version":3,"file":"CheckboxNodeView.js","sourceRoot":"","sources":["../../src/views/CheckboxNodeView.ts"],"names":[],"mappings":"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","sourcesContent":["import { CHECKBOX_STATE_KEYS, type CheckboxStateKey, type UINode } from \"@pixi-ui-editor/schema\";\r\nimport { CheckBox } from \"@pixi/ui\";\r\nimport { Sprite, Texture } from \"pixi.js\";\r\nimport { NodeView, type SceneInteractionMode } from \"./NodeView.js\";\r\nimport type { SceneAudio } from \"../audio/bus.js\";\r\n\r\nexport type CheckboxNode = Extract<UINode, { type: \"checkbox\" }>;\r\n\r\n/**\r\n * Adapts a checkbox node to `@pixi/ui`'s `CheckBox`, which owns the checked/unchecked switching —\r\n * this class never reimplements it. `group`-based radio exclusivity is wired one layer up, in\r\n * `wireCheckboxGroups` (see scene.ts): this view only exposes `forceCheck` so that wiring can flip\r\n * a sibling without re-emitting `onCheck` and recursing back into itself.\r\n *\r\n * Hover is layered on top of `CheckBox` by hand: unlike `FancyButton`, `CheckBox`/`Switcher` only\r\n * switches between its checked/unchecked views and has no hover state slot of its own. Both of its\r\n * internal Sprites always carry the texture matching the current hover flag — whichever one is\r\n * `visible` at any moment is Switcher's concern, not ours.\r\n */\r\nexport class CheckboxNodeView extends NodeView {\r\n private readonly checkbox: CheckBox;\r\n private readonly interaction: SceneInteractionMode;\r\n private readonly audio: SceneAudio | undefined;\r\n private readonly nodeId: string;\r\n private soundAssetIds: CheckboxNode[\"sounds\"];\r\n private uncheckedTexture: Texture;\r\n private checkedTexture: Texture;\r\n private uncheckedHoverTexture: Texture;\r\n private checkedHoverTexture: Texture;\r\n private enabledState: boolean;\r\n private hovering = false;\r\n\r\n constructor(node: CheckboxNode, textures: ReadonlyMap<string, Texture> | undefined, interaction: SceneInteractionMode, audio?: SceneAudio) {\r\n super(textures);\r\n this.interaction = interaction;\r\n this.audio = audio;\r\n this.nodeId = node.id;\r\n this.soundAssetIds = node.sounds;\r\n const unchecked = this.textureFor(node.states.uncheckedAssetId) ?? Texture.WHITE;\r\n const checked = this.textureFor(node.states.checkedAssetId) ?? Texture.WHITE;\r\n this.uncheckedTexture = unchecked;\r\n this.checkedTexture = checked;\r\n this.uncheckedHoverTexture = this.hoverTextureFor(node.states.uncheckedHoverAssetId, unchecked);\r\n this.checkedHoverTexture = this.hoverTextureFor(node.states.checkedHoverAssetId, checked);\r\n this.checkbox = new CheckBox({\r\n checked: node.defaultChecked,\r\n style: { unchecked, checked },\r\n });\r\n // Authoring-сцена инертна, как и у button: eventMode \"none\" на верхнем контейнере отключает\r\n // hit-testing всего поддерева, включая `innerView`, который Switcher сам сделал \"static\" — а\r\n // значит и hover в authoring никогда не наступает, так что его незачем отдельно отключать.\r\n if (interaction === \"authoring\") this.checkbox.eventMode = \"none\";\r\n else {\r\n this.checkbox.innerView.on(\"pointerover\", () => { this.hovering = true; this.applyTextures(); });\r\n this.checkbox.innerView.on(\"pointerout\", () => { this.hovering = false; this.applyTextures(); });\r\n if (audio !== undefined) {\r\n this.checkbox.onCheck.connect((checkedState) => {\r\n const assetId = checkedState ? this.soundAssetIds?.checkAssetId : this.soundAssetIds?.uncheckAssetId;\r\n this.audio?.cue(checkedState ? \"checkbox.check\" : \"checkbox.uncheck\", this.nodeId, assetId);\r\n });\r\n }\r\n }\r\n this.enabledState = node.enabled;\r\n this.applyEnabled(node.enabled);\r\n this.setContent(this.checkbox);\r\n }\r\n\r\n private hoverTextureFor(assetId: string | undefined, fallback: Texture): Texture {\r\n return (assetId === undefined ? undefined : this.textureFor(assetId)) ?? fallback;\r\n }\r\n\r\n /** Puts the current hover/non-hover texture on both internal Sprites; switching visibility is Switcher's job. */\r\n private applyTextures(): void {\r\n const [uncheckedView, checkedView] = this.checkbox.views;\r\n if (uncheckedView instanceof Sprite) uncheckedView.texture = this.hovering ? this.uncheckedHoverTexture : this.uncheckedTexture;\r\n if (checkedView instanceof Sprite) checkedView.texture = this.hovering ? this.checkedHoverTexture : this.checkedTexture;\r\n }\r\n\r\n /** In authoring mode `enabled` may only drive selectability elsewhere: this view stays inert either way. */\r\n private applyEnabled(enabled: boolean): void {\r\n this.enabledState = enabled;\r\n if (this.interaction === \"authoring\") return;\r\n this.checkbox.eventMode = enabled ? \"static\" : \"none\";\r\n }\r\n\r\n protected syncContent(node: UINode, transform: UINode[\"transform\"]): void {\r\n if (node.type !== \"checkbox\") return;\r\n this.soundAssetIds = node.sounds;\r\n\r\n const unchecked = this.textureFor(node.states.uncheckedAssetId) ?? Texture.WHITE;\r\n const checked = this.textureFor(node.states.checkedAssetId) ?? Texture.WHITE;\r\n // `style` rebuilds both internal views, so it's only reassigned when a base texture actually\r\n // changed — same rule ButtonNodeView follows for its state Sprites. A fresh pair of Sprites\r\n // starts out holding the plain (non-hover) textures `style` was given, so `applyTextures` always\r\n // runs afterwards to restore the current hover look.\r\n if (unchecked !== this.uncheckedTexture || checked !== this.checkedTexture) {\r\n this.uncheckedTexture = unchecked;\r\n this.checkedTexture = checked;\r\n this.checkbox.style = { unchecked, checked };\r\n }\r\n this.uncheckedHoverTexture = this.hoverTextureFor(node.states.uncheckedHoverAssetId, unchecked);\r\n this.checkedHoverTexture = this.hoverTextureFor(node.states.checkedHoverAssetId, checked);\r\n this.applyTextures();\r\n for (const view of this.checkbox.views) if (view instanceof Sprite) view.setSize(transform.width, transform.height);\r\n\r\n // Только на изменение документа: иначе любой пересчёт layout сбрасывал бы transient preview state.\r\n if (node.enabled !== this.enabledState) this.applyEnabled(node.enabled);\r\n }\r\n\r\n get enabled(): boolean {\r\n return this.enabledState;\r\n }\r\n\r\n set enabled(value: boolean) {\r\n this.applyEnabled(value);\r\n }\r\n\r\n get checked(): boolean {\r\n return this.checkbox.checked;\r\n }\r\n\r\n set checked(value: boolean) {\r\n this.checkbox.checked = value;\r\n }\r\n\r\n /** Sets checked state without emitting `onCheck` — used by radio-group wiring to avoid re-entrancy. */\r\n forceCheck(checked: boolean): void {\r\n this.checkbox.forceCheck(checked);\r\n }\r\n\r\n get state(): CheckboxStateKey {\r\n return this.checkbox.checked ? CHECKBOX_STATE_KEYS[1] : CHECKBOX_STATE_KEYS[0];\r\n }\r\n\r\n get onCheck(): CheckBox[\"onCheck\"] { return this.checkbox.onCheck; }\r\n}\r\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"ItemTableNodeView.js","sourceRoot":"","sources":["../../src/views/ItemTableNodeView.ts"],"names":[],"mappings":"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","sourcesContent":["import { resolveItemTableVisibleCount, type LayoutProfileId, type UINode } from \"@pixi-ui-editor/schema\";\r\nimport { Container } from \"pixi.js\";\r\nimport { NodeView } from \"./NodeView.js\";\r\n\r\n/**\r\n * Узел фиксированной вместимости: держит авторский список узлов (`items`, ссылки по адресу — их\r\n * разрешает `scene.ts`, тем же приёмом, что цели spine-коннекторов) и показывает только первые\r\n * `visibleCount` из них — остальные скрыты всегда, а не «на этой странице». Автор раскладывает\r\n * элементы под максимум, а сколько их реально помещается, задаётся на профиль: в разной ориентации\r\n * экрана на экран влезает разное число строк.\r\n *\r\n * Список именно авторский, а не дети: элемент обычно уже лежит там, где его выравнивает layout-группа.\r\n *\r\n * Узел намеренно ничего больше не делает. Он не страницы (`PageGroupNodeView` показывает ровно\r\n * одного ребёнка и растягивает его на себя), не раскладка (позицию элементы сохраняют свою) и ничего не\r\n * знает ни про какие данные: чем наполнить видимые элементы и когда, решает игровой код через\r\n * generic API из `controls.ts` (`getItemTableViewVisibleItems`, `getItemTableViewItem`,\r\n * `setItemTableViewVisibleCount`, `setItemTableViewItemsVisible`). Связка «переключили страницу →\r\n * перезаполнили элементы» тоже принадлежит игре: `PaginationNodeView.onPageChange` и эта таблица\r\n * ничего друг о друге не знают.\r\n *\r\n * Видимость складывается с авторской: элемент, скрытый в документе, не станет видимым из-за\r\n * вместимости, а скрытый вместимостью держится флагом `NodeView.hiddenByOwner` (см. `applyVisibility`).\r\n */\r\nexport class ItemTableNodeView extends NodeView {\r\n private itemViews: (Container | undefined)[] = [];\r\n private authoredVisibleCount = 0;\r\n /** Транзиентное переопределение от игрового кода; `undefined` — авторское значение профиля. */\r\n private runtimeVisibleCount?: number;\r\n /** Транзиентный «скрыть/показать всё» поверх вместимости; `undefined` — вместимость решает сама. */\r\n private forcedItemsVisible?: boolean;\r\n\r\n /**\r\n * Разрешённые views авторского списка `items`, позиционно выровненные с ним (`scene.ts`). Ссылка,\r\n * которая ни во что не разрешилась, сохраняет свою дырку `undefined`, чтобы остальные элементы не\r\n * сдвинулись; сама висячая ссылка — ошибка валидации документа, а не забота этого вида.\r\n */\r\n setItems(views: readonly (Container | undefined)[]): void {\r\n // Выбывшие из списка возвращаются под управление документа: иначе узел, убранный из таблицы,\r\n // остался бы скрытым её прежней вместимостью навсегда.\r\n const next = new Set(views);\r\n for (const previous of this.itemViews) {\r\n if (previous instanceof NodeView && !next.has(previous)) { previous.hiddenByOwner = false; previous.visible = previous.documentVisible; }\r\n }\r\n this.itemViews = [...views];\r\n this.applyVisibility();\r\n }\r\n\r\n /** Элементы в авторском порядке; нерезолвенные ссылки пропущены. */\r\n get items(): Container[] {\r\n return this.itemViews.filter((item): item is Container => item !== undefined);\r\n }\r\n\r\n get visibleCount(): number {\r\n return this.runtimeVisibleCount ?? this.authoredVisibleCount;\r\n }\r\n\r\n /** Транзиентно меняет вместимость; `undefined` возвращает авторское значение профиля. */\r\n set visibleCount(value: number | undefined) {\r\n this.runtimeVisibleCount = value === undefined ? undefined : Math.max(0, Math.round(value));\r\n this.applyVisibility();\r\n }\r\n\r\n /** Элементы, показанные прямо сейчас, в авторском порядке. */\r\n get visibleItems(): Container[] {\r\n return this.items.filter((item) => item.visible);\r\n }\r\n\r\n /** Индекс — позиция в авторском списке, а не среди показанных: адресация не «плавает». */\r\n itemAt(index: number): Container | undefined {\r\n return this.itemViews[index];\r\n }\r\n\r\n /** Показывает или прячет все элементы разом; `undefined` возвращает управление вместимости. */\r\n setItemsVisible(visible: boolean | undefined): void {\r\n this.forcedItemsVisible = visible;\r\n this.applyVisibility();\r\n }\r\n\r\n /**\r\n * Проход по элементам: влезающие включены, остальные выключены. Помимо самого `visible` ставится\r\n * `hiddenByOwner`, потому что `visible` узла пересчитывается из документа на каждом обновлении —\r\n * в том числе из колбэка layout-движка, который для элемента внутри layout-группы срабатывает\r\n * позже прохода таблицы и без флага вернул бы скрытый элемент обратно.\r\n */\r\n private applyVisibility(): void {\r\n const count = this.visibleCount;\r\n this.itemViews.forEach((item, index) => {\r\n if (item === undefined) return;\r\n const enabled = this.forcedItemsVisible ?? index < count;\r\n if (item instanceof NodeView) {\r\n item.hiddenByOwner = !enabled;\r\n item.visible = enabled && item.documentVisible;\r\n return;\r\n }\r\n item.visible = enabled;\r\n });\r\n }\r\n\r\n protected syncContent(node: UINode, _transform: UINode[\"transform\"], profile: LayoutProfileId): void {\r\n if (node.type !== \"item-table\") return;\r\n this.authoredVisibleCount = resolveItemTableVisibleCount(node, profile);\r\n this.applyVisibility();\r\n }\r\n}\r\n"]}
1
+ {"version":3,"file":"ItemTableNodeView.js","sourceRoot":"","sources":["../../src/views/ItemTableNodeView.ts"],"names":[],"mappings":"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","sourcesContent":["import { resolveItemTableVisibleCount, type LayoutProfileId, type UINode } from \"@pixi-ui-editor/schema\";\nimport { Container } from \"pixi.js\";\nimport { NodeView } from \"./NodeView.js\";\n\n/**\n * Узел фиксированной вместимости: держит авторский список узлов (`items`, ссылки по адресу — их\n * разрешает `scene.ts`, тем же приёмом, что цели spine-коннекторов) и показывает только первые\n * `visibleCount` из них — остальные скрыты всегда, а не «на этой странице». Автор раскладывает\n * элементы под максимум, а сколько их реально помещается, задаётся на профиль: в разной ориентации\n * экрана на экран влезает разное число строк.\n *\n * Список именно авторский, а не дети: элемент обычно уже лежит там, где его выравнивает layout-группа.\n *\n * Узел намеренно ничего больше не делает. Он не страницы (`PageGroupNodeView` показывает ровно\n * одного ребёнка и растягивает его на себя), не раскладка (позицию элементы сохраняют свою) и ничего не\n * знает ни про какие данные: чем наполнить видимые элементы и когда, решает игровой код через\n * generic API из `controls.ts` (`getItemTableViewVisibleItems`, `getItemTableViewItem`,\n * `setItemTableViewVisibleCount`, `setItemTableViewItemsVisible`). Связка «переключили страницу →\n * перезаполнили элементы» тоже принадлежит игре: `PaginationNodeView.onPageChange` и эта таблица\n * ничего друг о друге не знают.\n *\n * Видимость складывается с авторской: элемент, скрытый в документе, не станет видимым из-за\n * вместимости, а скрытый вместимостью держится флагом `NodeView.hiddenByOwner` (см. `applyVisibility`).\n */\nexport class ItemTableNodeView extends NodeView {\n private itemViews: (Container | undefined)[] = [];\n private authoredVisibleCount = 0;\n /** Транзиентное переопределение от игрового кода; `undefined` — авторское значение профиля. */\n private runtimeVisibleCount?: number;\n /** Транзиентный «скрыть/показать всё» поверх вместимости; `undefined` — вместимость решает сама. */\n private forcedItemsVisible?: boolean;\n\n /**\n * Разрешённые views авторского списка `items`, позиционно выровненные с ним (`scene.ts`). Ссылка,\n * которая ни во что не разрешилась, сохраняет свою дырку `undefined`, чтобы остальные элементы не\n * сдвинулись; сама висячая ссылка — ошибка валидации документа, а не забота этого вида.\n */\n setItems(views: readonly (Container | undefined)[]): void {\n // Выбывшие из списка возвращаются под управление документа: иначе узел, убранный из таблицы,\n // остался бы скрытым её прежней вместимостью навсегда.\n const next = new Set(views);\n for (const previous of this.itemViews) {\n if (previous instanceof NodeView && !next.has(previous)) { previous.hiddenByOwner = false; previous.visible = previous.documentVisible; }\n }\n this.itemViews = [...views];\n this.applyVisibility();\n }\n\n /** Элементы в авторском порядке; нерезолвенные ссылки пропущены. */\n get items(): Container[] {\n return this.itemViews.filter((item): item is Container => item !== undefined);\n }\n\n get visibleCount(): number {\n return this.runtimeVisibleCount ?? this.authoredVisibleCount;\n }\n\n /** Транзиентно меняет вместимость; `undefined` возвращает авторское значение профиля. */\n set visibleCount(value: number | undefined) {\n this.runtimeVisibleCount = value === undefined ? undefined : Math.max(0, Math.round(value));\n this.applyVisibility();\n }\n\n /** Элементы, показанные прямо сейчас, в авторском порядке. */\n get visibleItems(): Container[] {\n return this.items.filter((item) => item.visible);\n }\n\n /** Индекс — позиция в авторском списке, а не среди показанных: адресация не «плавает». */\n itemAt(index: number): Container | undefined {\n return this.itemViews[index];\n }\n\n /** Показывает или прячет все элементы разом; `undefined` возвращает управление вместимости. */\n setItemsVisible(visible: boolean | undefined): void {\n this.forcedItemsVisible = visible;\n this.applyVisibility();\n }\n\n /**\n * Проход по элементам: влезающие включены, остальные выключены. Помимо самого `visible` ставится\n * `hiddenByOwner`, потому что `visible` узла пересчитывается из документа на каждом обновлении —\n * в том числе из колбэка layout-движка, который для элемента внутри layout-группы срабатывает\n * позже прохода таблицы и без флага вернул бы скрытый элемент обратно.\n */\n private applyVisibility(): void {\n const count = this.visibleCount;\n this.itemViews.forEach((item, index) => {\n if (item === undefined) return;\n const enabled = this.forcedItemsVisible ?? index < count;\n if (item instanceof NodeView) {\n item.hiddenByOwner = !enabled;\n item.visible = enabled && item.documentVisible;\n return;\n }\n item.visible = enabled;\n });\n }\n\n protected syncContent(node: UINode, _transform: UINode[\"transform\"], profile: LayoutProfileId): void {\n if (node.type !== \"item-table\") return;\n this.authoredVisibleCount = resolveItemTableVisibleCount(node, profile);\n this.applyVisibility();\n }\n}\n"]}