{"version":3,"file":"e09416cdeccf652b7e05.chunk.js","mappings":"gOAiBO,MAAMA,GAAW,QAAI,QACfC,GAAa,QAAI,UAGvB,MAAMC,UAAkB,IAE9BC,MAEAC,MAEAC,SAIA,WAAAC,CACCC,EACAH,EACAC,EACAG,GAEAC,MAAM,OAAQD,GACVD,aAAyB,KAC5BG,KAAKP,MAAQI,EAAcJ,QAC3BO,KAAKN,MAAQG,EAAcH,QAC3BM,KAAKL,SAAWE,EAAcF,aAE9BK,KAAKP,MAAQI,EAGbG,KAAKN,MAAQA,EACbM,KAAKL,SAAWA,GAEjBK,KAAKC,UACN,CAEA,KAAAC,GACC,OAAO,IAAIV,EAAUQ,KAAKP,MAAOO,KAAKN,MAAOM,KAAKL,SAAUK,KAC7D,CAEA,QAAIG,GACH,OAAO,QAAI,iBACZ,CAEA,WAAAC,GACC,OAAOJ,KAAKL,SAAWL,EAAWC,CACnC,CAEA,wBAAAc,GACC,GAAIL,KAAKL,SAAU,CAClB,MAAMW,EAAeN,KAAKP,OAAQ,QAAI,gBAAkB,GAClDc,EAAaP,KAAKN,OAAQ,QAAI,cAAgB,GACpD,IAAIc,EAUJ,OARCA,EADGF,GAAgBC,EACZD,EAAe,KAAYC,EACxBD,IAEAC,GAGH,OAED,QAAK,WAAWC,KAAKA,EAC7B,CAAO,CACN,MAAMC,EAAaT,KAAKP,OAAQ,QAAI,cAAgB,GAC9CiB,EAAWV,KAAKN,OAAQ,QAAI,YAAc,GAChD,IAAIc,EACJ,GAAIC,GAAcC,EACjBF,EAAOC,EAAa,KAAYC,OAC1B,GAAID,EACVD,EAAOC,MACD,KAAIC,EAGV,OAAO,QAAI,qBAFXF,EAAOE,CAGR,CACA,OAAO,QAAK,+BAA+BF,KAAKA,EACjD,CACD,CAEA,SAAAG,CAAUC,GACT,OAAO,IAAcC,WAAWD,EAC/BZ,KAAKP,MACLO,KAAKN,MACLM,KAAKL,SAEP,CAEA,gBAAImB,GACH,OAAO,KAAmBC,IAC3B,CAEA,QAAIC,GACH,OAAO,CACR,CAEA,eAAAC,CAAgBC,EAAmBC,GAClC,OAAInB,KAAKL,SACJK,KAAKP,MACD,EAAEyB,EAAUC,GAEZ,CAACD,GAAWC,GAGb,CAACnB,KAAKP,MAAOO,KAAKN,MAE3B,CAEA,QAAAO,GACCF,MAAME,YACN,QAAcD,KAAKP,MAAO,UAC1B,QAAcO,KAAKN,MAAO,UAC1B,QAAcM,KAAKL,SAAU,WAC9B,CAEA,eAAAyB,GAIC,MAAO,QAHGpB,KAAKP,MAAQ,EAAI,IACjBO,KAAKN,MAAQ,EAAI,IACjBM,KAAKL,SAAW,EAAI,GAE/B,CAEA,aAAA0B,GACC,OAAIrB,KAAKL,SACD,CACN2B,SAAU,CAAC,gBAGL,CACNC,UAAW,CAAC,eAGf,E,uKC7HD,MAAMC,EAAU,IAAIC,IAAI,CACvB,CAAC,UAAW,CAAC,MAAgB,GAAO,IACpC,CAAC,aAAc,CAAC,MAAe,GAAM,IACrC,CAAC,WAAY,CAAC,MAAe,GAAO,IACpC,CAAC,cAAe,CAAC,MAAc,GAAM,MAOtC,SAASC,EAAQC,GAChB,MAAwB,iBAAbA,EACHA,EAEAA,EAASC,QAAU,EAE5B,CAEO,MAAMC,UAA0B,IAC/BC,WAIP,WAAAlC,CAAY+B,EAA0CI,EAAsBD,EAAsBhC,GACjGC,MAAM2B,EAAQC,GAAWI,EAAWP,EAAS,eAAgB1B,GAE5DE,KAAK8B,WADkB,iBAAbH,EACQG,EAEAH,EAASG,YAE7B,CAEA,eAAAE,GACC,OAAqBhC,KAAK+B,UArCVE,8BAsCjB,CAEA,KAAA/B,GACC,OAAO,IAAI2B,EAAkB7B,KAAK4B,KAAM5B,KAAK+B,UAAW/B,KAAK8B,WAAY9B,KAC1E,CAEA,QAAIG,GACH,OAAO,QAAI,gBACZ,CAEA,SAAAQ,CAAUC,GACT,OAAO,IAAsBsB,mBAAmBtB,EAASA,EAAQuB,aAAanC,KAAK4B,MAAO5B,KAAK8B,WAChG,CAEA,gBAAIhB,GACH,OAAO,KAAmBsB,YAC3B,CAEA,QAAIpB,GACH,OAAIhB,KAAK8B,WACD,EAEA,CAET,CAEA,WAAIO,GACH,OAAO,CACR,CAEA,eAAAjB,GACC,MAAO,iBAAiBpB,KAAK4B,QAAQ5B,KAAK8B,YAC3C,CAEA,WAAAQ,CAAYC,EAAyBC,IACpC,QAAkBxC,KAAMuC,EAAM,OAAQC,IACtC,QAAkBxC,KAAMuC,EAAM,aAAcC,EAC7C,E,0IC3EM,MAAMC,GAAyB,QAAI,wBAC7BC,GAAgB,QAAI,cAE1B,MAAMC,UAA0B,IACtCC,OACAC,KAIA,WAAAjD,CACCkD,EACAD,EAAO,EACP/C,GAEIgD,aAA+B,KAClC/C,MAAM,qBAAsBD,GAC5BE,KAAK4C,OAASE,EAAoBF,SAAW,KAC7C5C,KAAK6C,KAAO,GACFC,aAA+B,KACzC/C,MAAM,yBAA0BD,GAChCE,KAAK4C,OAASE,EAAoBF,SAAW,KAC7C5C,KAAK6C,KAAO,IAEZ9C,MAAe,IAAT8C,EAAiD,qBAAuB,yBAA0B/C,GACxGE,KAAK4C,OAASE,EACd9C,KAAK6C,KAAOA,GAEb7C,KAAKC,UACN,CAEA,KAAAC,GACC,OAAO,IAAIyC,EAAkB3C,KAAK4C,OAAQ5C,KAAK6C,KAAM7C,KACtD,CAEA,QAAIG,GACH,OAAkB,IAAdH,KAAK6C,KACDJ,EAEAC,CAET,CAEA,0BAAIK,GACH,OAAO,CACR,CAEA,WAAA3C,GACC,OAAkB,IAAdJ,KAAK6C,MACD,QAAI,eAEJ,QAAI,UAEb,CAEA,wBAAAxC,CAAyB2C,EAAuBC,GAC/C,MAAMC,EAAyB,IAAdlD,KAAK6C,MAAiD,QAAI,wBAAyB,QAAI,YAClGM,EAAUnD,KAAK4C,OAAS,GAAI,QAAI,gBAAiB,QAAI,gBAC3D,OAAIK,GACI,QAAK,uCAAuCzC,KAAK0C,EAAUC,IAE3D,QAAK,aAAa3C,KAAK0C,EAAUC,EAE1C,CAEA,SAAAxC,CAAUC,GACT,OAAsB,IAAdZ,KAAK6C,KAEZ,IAA4BO,yBAE5B,IAAgCC,8BAC/BzC,EAASZ,KAAK4C,OAAS,KAC1B,CAEA,gBAAI9B,GACH,OAAkB,IAAdd,KAAK6C,KACD,KAAmBS,mBAEnB,KAAmBC,sBAE5B,CAEA,QAAIvC,GACH,OAAqB,IAAdhB,KAAK6C,K,GAIb,CAEA,QAAA5C,GACCF,MAAME,YACN,QAAaD,KAAK4C,OAAQ,WAC1B,QAAmB5C,KAAK6C,KAAM,EAAF,EAAuE,OACpG,CAEA,eAAAzB,CAAgB4B,EAAuBC,GACtC,OAAIA,EACI,uBAAuBjD,KAAK4C,UAAU5C,KAAK6C,OAE3C,iBAAiB7C,KAAK4C,UAAU5C,KAAK6C,MAE9C,CAEA,aAAAxB,GACC,OAAkB,IAAdrB,KAAK6C,KACD,CACNvB,SAAU,CAAC,qBAGL,CAAC,CAEV,E,2ICzGM,MAAMkC,GAAkB,QAAI,gBACtBC,GAAe,QAAI,aAEzB,MAAMC,UAAmB,IAC/B/D,SACAgE,OACAd,KACAe,qBAIA,WAAAhE,CACCiE,EACAC,EAAA,EACAnE,GAAW,EACXG,GAEA,GAAI+D,aAA4B,IAAsB,CACrD9D,MAAM,cAAeD,GACrBE,KAAKL,SAAWkE,EAAiBlE,WACjC,MAAMoE,EAAIF,EAAiBE,IAAM,KAC3BC,EAAIH,EAAiBG,IAAM,KACjChE,KAAK2D,OAAS,IAAI,KAAQI,EAAGC,GAE5BhE,KAAK4D,qBADFE,EAAoB,GAGKD,EAAiBD,uBAE9C5D,KAAK6C,KAAO,CACb,MAAO,GAAIgB,aAA4B,IAA0B,CAChE9D,MAAM,kBAAmBD,GACzBE,KAAKL,SAAWkE,EAAiBlE,WACjC,MAAMoE,EAAIF,EAAiBE,IAAM,KAC3BC,EAAIH,EAAiBG,IAAM,KACjChE,KAAK2D,OAAS,IAAI,KAAQI,EAAGC,GAE5BhE,KAAK4D,qBADFE,EAAoB,GAGKD,EAAiBD,uBAE9C5D,KAAK6C,KAAO,CACb,MACC9C,MAA8C,IAAxC+D,EAAkE,cAAgB,kBAAmBhE,GAC3GE,KAAKL,SAAWA,EAChBK,KAAK2D,OAASE,EACd7D,KAAK4D,sBAAuB,EAC5B5D,KAAK6C,KAAOiB,EAEb9D,KAAKC,UACN,CAEA,KAAAC,GACC,OAAO,IAAIwD,EAAW1D,KAAK2D,OAAOzD,QAASF,KAAK6C,KAAM7C,KAAKL,SAAUK,KACtE,CAEA,QAAIG,GACH,OAAqB,IAAdH,KAAK6C,KAAmCW,EAAkBC,CAClE,CAEA,0BAAIV,GACH,OAAO,CACR,CAEA,WAAA3C,GACC,OAAkB,IAAdJ,KAAK6C,MACD,QAAI,cAEJ,QAAI,SAEb,CAEA,wBAAAxC,CAAyB2C,EAAuBC,GAC/C,MAAMC,EAAyB,IAAdlD,KAAK6C,MAAmC,QAAI,aAAc,QAAI,SACzEoB,EAAejE,KAAKL,SAAW,KAAM,QAAI,yCAA2C,GACpFwD,GAAU,OAA6BnD,KAAK2D,OAAQ,IAC1D,OAAIV,GACI,QAAK,2CAA2CzC,KAAK0C,EAAUC,EAASc,IAExE,QAAK,iBAAiBzD,KAAK0C,EAAUC,EAASc,EAEvD,CAEA,SAAAtD,CAAUC,GACT,OAAsB,IAAdZ,KAAK6C,KAEZ,IAAqBqB,kBAErB,IAAyBC,uBACxBvD,EAASZ,KAAK2D,OAAOI,EAAI,KAAgB/D,KAAK2D,OAAOK,EAAI,KAAgBhE,KAAKL,SAAUK,KAAK4D,qBAChG,CAEA,gBAAI9C,GACH,OAAkB,IAAdd,KAAK6C,KACD,KAAmBuB,YAEnB,KAAmBC,eAE5B,CAEA,QAAIrD,GACH,OAAqB,IAAdhB,KAAK6C,K,GAIb,CAEA,QAAA5C,GACCF,MAAME,YACN,QAAcD,KAAK2D,OAAQ,WAC3B,QAAmB3D,KAAK6C,KAAM,EAAF,EAAiD,SAC7E,QAAc7C,KAAKL,SAAU,aAC7B,QAAcK,KAAK4D,qBAAsB,uBAC1C,CAEA,eAAAxC,CAAgB4B,EAAuBC,GACtC,OAAIA,EACI,eAAejD,KAAK2D,OAAOI,KAAK/D,KAAK2D,OAAOK,KAAKhE,KAAK6C,QAAQ7C,KAAKL,WAEnE,SAASK,KAAK2D,OAAOI,KAAK/D,KAAK2D,OAAOK,KAAKhE,KAAK6C,QAAQ7C,KAAKL,UAEtE,CAEA,aAAA0B,GACC,OAAkB,IAAdrB,KAAK6C,KACD,CACNvB,SAAU,CAAC,oBAGL,CAAC,CAEV,E,oPC3HM,MAAMgD,EAA+B,CAC3CC,aAAa,EACbC,UAAU,EACVC,SAAS,GAGGC,EAA8B,CAC1CH,aAAa,EACbC,UAAU,EACVC,SAAS,GAGH,MAAME,UAAsB,IAClCC,UACAC,wBACAC,WACAC,OAIA,WAAAnF,CACCoF,EACAC,EACAC,EACAC,EACArF,GAEAC,MAAM,WAAYD,GACdkF,aAAkC,KACrChF,KAAK4E,WAAY,QAA2BI,EAAuBI,qBACnEpF,KAAK8E,WAAaE,EAAuBF,aACzC9E,KAAK+E,QAAS,QAA4BC,EAAuBD,SAAUE,GAC3EjF,KAAK6E,wBAA0BG,EAAuBK,iBACjB,MAAjCrF,KAAK6E,0BAER7E,KAAKmF,oBAAsBnF,KAAK8E,WAAaJ,EAA8BJ,KAG5EtE,KAAK4E,UAAYK,EACjBjF,KAAK8E,WAAaE,EAClBhF,KAAK+E,OAASG,EACdlF,KAAKmF,oBAAsBA,GAE5BnF,KAAKC,UACN,CAEA,KAAAC,GACC,OAAO,IAAIyE,EAAc3E,KAAK8E,WAAY9E,KAAK4E,UAAU1E,QAASF,KAAK+E,OAAQ/E,KAAKmF,oBAAqBnF,KAC1G,CAEA,QAAIG,GACH,OAAO,QAAI,WACZ,CAEA,0BAAI4C,GACH,OAAO,CACR,CAEA,WAAA3C,GACC,OAAO,QAAI,WACZ,CAEA,wBAAAC,CAAyBiF,EAAyCrC,GACjE,MAAMsC,EAAOvF,KAAK8E,YAAa,QAAI,UAAY9E,KAAKwF,WAAWF,GACzDG,GAAO,QAAQH,GAAaG,MAClC,IAAIP,EAEHA,EADGlF,KAAK+E,QACC,QAAK,cAAcvE,KAAKR,KAAK+E,OAAOW,aAAaD,KAEjD,QAAI,aAEd,MAAME,EAAK3F,KAAK4E,UAAUgB,aACpBC,GAAM7F,KAAK4E,UAAUkB,aACrBC,EAAU,GACZ/F,KAAKgG,YACRD,EAAQE,MAAK,QAAK,gCAAgCzF,MAAK,SAAyBR,KAAK4E,UAAUsB,iBAAiBC,YAE7GnG,KAAKoG,WACRL,EAAQE,MAAK,QAAK,oBAAoBzF,KAAKR,KAAK4E,UAAUyB,YAAYF,QAAQ,KAE3EnG,KAAKsG,eACRP,EAAQE,MAAK,QAAK,4BAA4BzF,KAAKmF,EAAGQ,QAAQ,GAAIN,EAAGM,QAAQ,KAEvD,IAAnBJ,EAAQQ,QACXR,EAAQE,KAAK,MAEd,MAAMO,EAAOT,EAAQU,KAAK,MAC1B,OAAIxD,GACI,QAAK,8DAA8DzC,KAAK+E,EAAML,EAAQsB,IAEtF,QAAK,kCAAkChG,KAAK+E,EAAML,EAAQsB,EAEnE,CAEA,SAAA7F,CAAUC,EAA8B8F,GAQvC,OAPA,IAAkBC,cAAc/F,GAChC,IAAkBgG,qBAAqBhG,GACtC,QAAyBA,EAASZ,KAAK4E,YAExC,IAAkBiC,UAAUjG,GAAS,QAAkBZ,KAAK+E,OAAQ2B,IACpE,IAAkBI,cAAclG,EAASZ,KAAK8E,YAC9C,IAAkBiC,kBAAkBnG,EAASZ,KAAK6E,yBAC3C,IAAkBmC,YAAYpG,EACtC,CAEA,gBAAIE,GACH,OAAO,KAAmBmG,QAC3B,CAEA,QAAIjG,GACH,OAAO,CACR,CAEA,QAAAf,GACCF,MAAME,YACN,QAA0BD,KAAK4E,UAAW,cAC1C,QAAc5E,KAAK8E,WAAY,eAC/B,QAAiB,KAAY9E,KAAK+E,OAAS,WAC3C,QAAmB/E,KAAK6E,wBAAyB,EAAG,EAAK,0BAC1D,CAEA,WAAAvC,CAAY4E,EAAoB1E,IAC/B,QAAiBxC,KAAqBkH,EAAO1E,GAC7C,MAAMD,GAAO,QAASoC,EAAeuC,IACrC,QAAqClH,KAAMuC,EAAM,YAAaC,IAC9D,QAAkBxC,KAAMuC,EAAM,aAAcC,IAC5C,QAA+BxC,KAAMuC,EAAM,SAAUC,IACrD,QAAkBxC,KAAMuC,EAAM,0BAA2BC,EAC1D,CAEA,6BAAA2E,CAA8BC,GACzBpH,KAAK+E,SAAWqC,IACnBpH,KAAK+E,OAAS,KAEhB,CAEA,eAAA3D,GACC,MAAMiG,EAAarH,KAAK+E,QAAQuC,IAAM,KACtC,MAAO,YAAYtH,KAAK4E,aAAa5E,KAAK8E,cAAcuC,KAAcrH,KAAK6E,yBAC5E,CAEA,aAAAxD,CAAc+F,GACb,GAAIpH,KAAK+E,QAAU/E,KAAK+E,SAAWqC,EAElC,MAAO,CAAC,EAET,GAAIpH,KAAK8E,WACR,OAAI9E,KAAK+E,OAED,CACNzD,SAAU,CAAC,WAIL,CACNC,UAAW,CAAC,WAGR,CACN,MAAMgG,EAAmC,GAUzC,OATIvH,KAAKsG,eACRiB,EAAQtB,KAAK,YAEVjG,KAAKgG,YACRuB,EAAQtB,KAAK,SAEVjG,KAAKoG,WACRmB,EAAQtB,KAAK,WAES,IAAnBsB,EAAQhB,OACJ,CAAC,EAELvG,KAAK+E,OAED,CACNzD,SAAUiG,GAIJ,CACNhG,UAAWgG,EAGd,CACD,CAEA,iBAAIjB,GACH,OAAO,QAAStG,KAAK6E,wBAAyB,EAC/C,CACA,cAAImB,GACH,OAAO,QAAShG,KAAK6E,wBAAyB,EAC/C,CACA,aAAIuB,GACH,OAAO,QAASpG,KAAK6E,wBAAyB,EAC/C,CACA,uBAAIM,GACH,MAAO,CACNZ,YAAavE,KAAKsG,cAClB9B,SAAUxE,KAAKgG,WACfvB,QAASzE,KAAKoG,UAEhB,CACA,uBAAIjB,CAAoBqC,GACvB,IAAI3C,EAA0B,EAC9BA,GAA2B2C,EAAWjD,YAAe,EAAoD,EACzGM,GAA2B2C,EAAWhD,SAAW,EAAkD,EACnGK,GAA2B2C,EAAW/C,QAAU,EAAiD,EACjGzE,KAAK6E,wBAA0BA,CAChC,E,6HC5NM,MAAM4C,GAAoB,QAAI,QACxBC,GAAoB,QAAK,YAG/B,SAASC,EAAsBP,EAA+BQ,GACpE,GAAc,OAAVA,EACH,OAAO,KAER,MAAMzH,EAAOiH,GAAYS,SAASD,IAAU,KAC5C,OAAIzH,EACI,KAAQK,KAAKL,GAEb,KAAeK,KAAKoH,EAE7B,C,sJCdA,SAASE,IACR,MAAO,CAACC,EAAqBC,EAAeC,IAAmB,IAAI,MAAW,EAC/E,E,0BAEA,MAAMC,GAAiB,QAAI,2BACrBC,GAAuB,QAAK,4DAgB3B,MAAeC,UAA4B,IAQzCxG,KACAG,UACSP,QATjB6G,OAASP,IACTQ,OAAQ,EACRC,QAAS,EACTC,SACAC,iBAAkC,KAElC,WAAA7I,CACQgC,EACAG,EACSP,EAChBkH,EACA5I,GAEAC,MAAM2I,EAAM5I,GANL,KAAA8B,KAAAA,EACA,KAAAG,UAAAA,EACS,KAAAP,QAAAA,EAKhBxB,KAAKwI,SAAWxI,KAAKgC,kBACrBhC,KAAK2I,SACN,CAIA,aAAAC,GACC5I,KAAKwI,SAAWxI,KAAKgC,iBACtB,CAEA,OAAA2G,GAEC3I,KAAKqI,OAASP,IACd9H,KAAKsI,OAAQ,EACbtI,KAAKuI,QAAS,EACdvI,KAAKyI,iBAAmB,KAGxB,MAAMI,EAAS7I,KAAKwI,SAASG,QAAQ3I,KAAK4B,MAC1C,QAAekH,IAAXD,GAAwBA,EAAOtC,OAAS,EAC3CvG,KAAKyI,iBAAmBI,EAAOE,KAAIC,GAASA,EAAMC,OAAMxC,KAAK,UACvD,CACN,MAAMyC,EAAUlJ,KAAKwI,SAASW,6BAA6B,QAC3D,QAAgBL,IAAZI,EACHlJ,KAAKyI,iBAAmBP,MAClB,CACN,MAAMG,EAASrI,KAAKwB,QAAQ4H,IAAIF,GAChC,QAAeJ,IAAXT,EACHrI,KAAKqI,OAASA,EAAO,GACrBrI,KAAKsI,MAAQD,EAAO,GACpBrI,KAAKuI,OAASF,EAAO,OACf,CACN,MAAMgB,EAAY,IAAIrJ,KAAKwB,QAAQ8H,QAAQ7C,KAAK,MAChDzG,KAAKyI,iBAAmBN,EAAqB3H,KAAK6I,EAAWH,EAC9D,CACD,CACD,CACD,CAEA,0BAAInG,GACH,OAAO/C,KAAKsI,MAAQ,EAA8B,CACnD,CAEA,2BAAIiB,GACH,OAAOvJ,KAAKuI,OAAS,EAA8B,CACpD,CAEA,WAAAnI,GACC,MAAMoJ,EAAMxJ,KAAK4B,KAAK6H,MAAM,MAAMlD,OAClC,OAAO,QAAK,kBAAkB/F,KAAKgJ,EACpC,CAEA,YAAAE,GACC,MAAMF,EAAMxJ,KAAK4B,KAAK6H,MAAM,MAAMlD,OAClC,OAAO,QAAK,6BAA6B/F,KAAKgJ,EAC/C,CAEA,kBAAAG,GACC,OAAiC,OAA1B3J,KAAKyI,gBACb,CAEA,qBAAAmB,GACC,OAA8B,OAA1B5J,KAAKyI,kBACD,QAAK,+BAA+BjI,KAAKR,KAAKyI,kBAE9C,EAET,CAEA,GAAAoB,CAAIC,EAA+BC,GAClC,GAA8B,OAA1B/J,KAAKyI,iBAER,OADAuB,QAAQhB,MAAM,yBAAyBe,yCAA+C/J,KAAKyI,kBACpF,MAACK,GAAW,GAEpB,IACC,MAAMmB,EAASjK,KAAKqI,OAAOrI,KAAKwI,SAAU,OAAQsB,GAAa,GAC/D,MAAO,CAACG,EAAOC,MAAOD,EAAOE,KAC9B,CAAE,MAAOC,GAER,OADAJ,QAAQhB,MAAM,yBAAyBe,4BAAkCK,GAClE,MAACtB,GAAW,EACpB,CACD,CAGA,cAAAuB,CAAeC,EAAiBC,GAC/BvK,KAAK4B,MAAO,OAAqB5B,KAAK4B,KAAM0I,EAASC,EACtD,E,yLC3HD,MAAM/I,EAAU,IAAIC,IAAI,CACvB,CAAC,YAAa,CAAC,MAAgB,GAAO,IACtC,CAAC,eAAgB,CAAC,MAAe,GAAM,IACvC,CAAC,mBAAoB,CAAC,MAAiB,GAAO,IAC9C,CAAC,sBAAuB,CAAC,MAAgB,GAAM,MAWhD,SAASC,EAAQC,GAChB,MAAwB,iBAAbA,EACHA,EAEAA,EAASC,QAAU,EAE5B,CAEO,MAAM4I,UAA6B,IAGzC,WAAA5K,CAAY+B,EAA6CI,EAAsBjC,GAC9EC,MAAM2B,EAAQC,GAAWI,EAAWP,EAAS,kBAAmB1B,EACjE,CAEA,eAAAkC,GACC,OAAqBhC,KAAK+B,UAvBV0I,iCAwBjB,CAEA,KAAAvK,GACC,OAAO,IAAIsK,EAAqBxK,KAAK4B,KAAM5B,KAAK+B,UAAW/B,KAC5D,CAEA,QAAIG,GACH,OAAO,QAAI,mBACZ,CAEA,SAAAQ,CAAUC,GACT,OAAO,IAAyB8J,sBAAsB9J,EAASA,EAAQuB,aAAanC,KAAK4B,MAC1F,CAEA,mBAAI+I,GACH,OAAO,KAAsBC,eAC9B,CAEA,QAAI5J,GACH,OAAO,CACR,CAEA,WAAIqB,GACH,OAAO,CACR,CAEA,eAAAjB,GACC,MAAO,oBAAoBpB,KAAK4B,MACjC,CAEA,WAAAU,CAAYC,EAA4BC,IACvC,QAAkBxC,KAAMuC,EAAM,OAAQC,EACvC,E,mHClED,MAAMqI,GAAc,QAAK,WACZC,GAAmB,QAAI,iBAE7B,MAAMC,UAA0B,IAC/BC,QAEP,WAAApL,CACCqL,EACAnL,GAEAC,MAAM,eAAgBD,GAClBmL,aAA+B,IAClCjL,KAAKgL,QAAUC,EAAoBD,UAEnChL,KAAKgL,QAAUC,CAEjB,CAEA,KAAA/K,GACC,OAAO,IAAI6K,EAAkB/K,KAAKgL,QAAShL,KAC5C,CAEA,QAAIG,GACH,OAAO2K,CACR,CAEA,2BAAIvB,GACH,OAAO,CACR,CAEA,SAAA5I,CAAUC,GACT,OAAO,IAAsBsK,mBAAmBtK,EAC/CZ,KAAKgL,QAEP,CAEA,WAAA5K,GACC,OAAOyK,EAAYrK,MAAK,QAAaR,KAAKgL,SAC3C,CAEA,wBAAA3K,CAAyBiF,GACxB,OAAqB,IAAjBtF,KAAKgL,SACD,QAAI,kBAEJH,EAAYrK,MAAK,QAAeR,KAAKgL,QAAS1F,GAAaG,MAEpE,CAEA,iBAAI0F,GACH,OAAO,KAAyBC,YACjC,CAEA,QAAIpK,GACH,OAAO,CACR,CAEA,WAAIqB,GACH,OAAO,CACR,CAEA,eAAAjB,GAAoB,MAAO,WAAWpB,KAAKgL,SAAW,E,qHC7ChD,SAASK,EAAYC,EAA2BC,EAAcC,EAAY,EAAGC,GAAS,GAC5F,GAAIH,aAAiBI,MAAO,CAC3B,MAAM9K,EAAU,IAAI,KAAiB0K,EAAM/E,OAAS,GAMpD,OALA+E,EAAMK,SAAQ,CAACC,EAAOC,KACrBjL,EAAQkL,IAAID,EAAGD,EAAM7H,EAAG6H,EAAM5H,EAAE,KAEjC,QAAoBsH,EAAO,SAC3B1K,EAAQkL,IAAIR,EAAM/E,OAAQ+E,EAAM,GAAGvH,EAAGuH,EAAM,GAAGtH,GACxC,IAAI,KAAcpD,EAAS4K,EAAWD,EAAOE,EACrD,CACC,OAAO,IAAI,KAAa,IAAI,KAAWH,EAAOC,EAAOC,EAAWC,EAElE,CAEA,SAASM,EAAuBC,EAAwBC,GACvD,OAAOA,EAAcC,MAAMF,EAAOG,KACnC,CAEO,SAASC,EAAmBJ,EAAwBK,EAA6CJ,EAAoCK,EAAQ,EAAKC,GAAW,EAAOC,GAAW,EAAOC,EAAwB,MACpN,MAAMrF,EAAa4E,EAAOtD,KACpBgE,EAAatF,EAAWsF,WACxB9H,EAAYmH,EAAuBC,EAAQC,GACjD,GAAII,aAAoB,KAAK,CAC5B,MAAMM,EAAMN,EACNO,EAAYD,EAAIE,UAAUC,UAAUJ,EAAWK,OAAOC,QAAQ,GAC9DC,EAAa,IAAI,KAAW,KAAQC,QAASN,GAC7CO,EAAsB,IAAI,KAAgBT,EAAWU,uBAAwBH,GACnFA,EAAWI,QAAUf,GAASN,EAAOsB,eAAiB,GAAM,GAC5D,MAAMC,EAAwB,GAE9B,GADAA,EAAKtH,KAAKkH,GACNZ,EAAU,CACb,MAAMhB,EAAQ,IAAWiC,eAAetN,QACxCqL,EAAMe,MAAQ,GACdiB,EAAKtH,KA7CD,SAAmBqF,EAA2BC,GACpD,GAAID,aAAiBI,MAAO,CAC3B,MAAM9K,EAAU,IAAI,KAAiB0K,EAAM/E,QAI3C,OAHA+E,EAAMK,SAAQ,CAACC,EAAOC,KACrBjL,EAAQkL,IAAID,EAAGD,EAAM7H,EAAG6H,EAAM5H,EAAE,IAE1B,IAAI,KAAkBpD,EAAS2K,EACvC,CACC,OAAO,IAAI,KAAW,IAAI,KAAWD,EAAOC,EAE9C,CAmCakC,CAAUrG,EAAWsG,qBAAsBnC,GACtD,CACA,GAAIiB,EAAU,CACb,MAAMmB,EAAQ,EAAI/I,EAAUyB,YAC5BkH,EAAKtH,KAAKoF,EAAYjE,EAAWsG,qBAAsB,IAAWF,eAAgBG,GACnF,CACA,MAAMC,EAAgB,IAAI,KAAgBhJ,EAAW2I,GACrD,GAAiB,OAAbd,IAAsBmB,EAAcC,OAAOC,eAAerB,GAC7D,OAEDE,EAAIoB,iBAAiBH,EACtB,KAAO,CACN,MAAMpL,EAAM6J,EAEN2B,EAAkBpJ,EAAUsH,MAAMQ,EAAWU,wBAC/CpB,EAAOsB,iBACV9K,EAAIyL,YAAc,IAEnB,MAAMC,EAAe1L,EAAI2L,eACzB3L,EAAI4L,UAAUJ,EAAgBpI,aAAcoI,EAAgBlI,cAC5DtD,EAAI6L,OAAOL,EAAgBM,eAC3B9L,EAAI+L,MAAMP,EAAgB3H,YAAa2H,EAAgB3H,aACvD,MAAMmI,EAAO9B,EAAWK,OAAOyB,KAC/B9B,EAAWK,OAAO0B,KAAKjM,EAAK,EAAG,EAAGgM,EAAKzK,EAAGyK,EAAKxK,IAC/C,SAAQuI,EAAU,wCAClB/J,EAAIkM,aAAaR,GACblC,EAAOsB,iBACV9K,EAAIyL,YAAc,EAEpB,CAED,CAEO,SAASU,EACftC,EACAuC,EACAC,EACAC,EACAC,EACAC,EAAwC,KACxCC,EAAiC,KACjCxC,EAAwB,MAIxB,MAAMyC,EAA8C,CAAC,GAAI,GAAI,GAAI,IACjE,IAAK,MAAMlD,KAAU6C,EAAMM,QAC1BD,EAAOlD,EAAOtD,KAAK1H,MAAMiF,KAAK+F,GAG/B,IAAK,MAAOpE,EAAOwH,KAAUF,EAAOG,UAAW,CAC9C,MAAMC,EAAaL,EAAerH,GAAS,EAAM,GACjD,IAAK,MAAMoE,KAAUoD,EAAO,CAC3B,GAAIN,GAAgBS,IAAIvD,GAEvB,SAED,MAAMO,EAAWwC,GAAiBQ,IAAIvD,IAA8B,OAAnB8C,EAC3CtC,EAAWwC,IAAmBhD,EAC9BwD,EAAcxD,EAAOtD,KAAK4D,MAIhC,GAFAF,EAAmBJ,EAAQK,EAAUuC,EADvBU,EAAaE,EACgCjD,EAAUC,EAAUC,GAE3E+C,EAAc,GAAK,CACtB,MAAM5K,EAAYmH,EAAuBC,EAAQ4C,GAC3Ca,GAAmB,QAAkBzD,EAAOtD,KAAKgH,aAAc9K,GACjEyH,aAAoB,MACvBA,EAAS0B,iBAAiB1C,EAAYoE,EAAkB,IAAME,MAAMzP,QAAQ0P,SAASN,GAAa,GAAG,GAEvG,CACD,CACD,CACD,C,yLC3HA,SAASO,EAAqBC,EAAiBC,GAC9C,GAAID,EAAEvJ,SAAWwJ,EAAExJ,OAClB,OAAO,EAER,IAAK,IAAIsF,EAAI,EAAGA,EAAIiE,EAAEvJ,SAAUsF,EAC/B,GAAIiE,EAAEjE,KAAOkE,EAAElE,GACd,OAAO,EAGT,OAAO,CACR,CAEA,SAASmE,EAA0BC,GAClC,IAAIC,EAAI,GACR,IAAK,IAAIrE,EAAI,EAAGA,EAAIoE,EAAO1J,OAAQsF,GAAK,EAAG,CAG1CqE,GAAK,IAFUD,EAAOpE,MACPoE,EAAOpE,EAAI,OACMA,EAAI,EAAIoE,EAAO1J,OAAS,KAAO,GAChE,CACA,OAAO2J,CACR,CAEO,MAAMC,UAAiB,IACVC,KAAmB7E,MAAtC,WAAA3L,CAAmBwQ,EAAmB7E,GAAgBxL,QAAnC,KAAAqQ,KAAAA,EAAmB,KAAA7E,MAAAA,CAAyB,CAE/D,eAAO8E,CAAStM,EAAWC,EAAW2J,EAAe2C,EAAgB/E,GACpE,OAAO,IAAI4E,EAAS,IAAI,KAAKpM,EAAGC,EAAG2J,EAAO2C,GAAS/E,EACpD,CAEA,UAAIsC,GACH,OAAO7N,KAAKoQ,IACb,CAEA,OAAAG,CAAQC,GACP,MAAMjO,GAAO,QAAY4N,EAAUK,GACnC,OAAa,OAATjO,IAGGvC,KAAKoQ,KAAKG,QAAQhO,EAAK6N,OAC7BpQ,KAAKuL,MAAMgF,QAAQhO,EAAKgJ,OAE1B,CAEA,QAAAkF,GACC,MAAO,YAAYzQ,KAAKoQ,QAAQpQ,KAAKuL,MAAMmF,eAC5C,EAGM,MAAMC,UAAmB,IACZP,KAAmB7E,MAAqBC,UAAsBC,OAAjF,WAAA7L,CAAmBwQ,EAAmB7E,EAAqBC,EAAY,EAAUC,GAAS,GAAS1L,QAAhF,KAAAqQ,KAAAA,EAAmB,KAAA7E,MAAAA,EAAqB,KAAAC,UAAAA,EAAsB,KAAAC,OAAAA,CAA2B,CAE5G,UAAIoC,GACH,OAAO7N,KAAKoQ,KAAKQ,OAAwB,GAAjB5Q,KAAKwL,UAC9B,CAEA,OAAA+E,CAAQC,GACP,MAAMjO,GAAO,QAAYoO,EAAYH,GACrC,OAAa,OAATjO,IAGGvC,KAAKoQ,KAAKG,QAAQhO,EAAK6N,OAC7BpQ,KAAKuL,MAAMgF,QAAQhO,EAAKgJ,QACxBvL,KAAKwL,YAAcjJ,EAAKiJ,WACxBxL,KAAKyL,SAAWlJ,EAAKkJ,OAEvB,CAEA,QAAAgF,GACC,MAAO,cAAczQ,KAAKoQ,QAAQpQ,KAAKuL,MAAMmF,iBAAiB1Q,KAAKyL,QACpE,EAGM,MAAMoF,UAAmB,IACZC,OAAwBC,OAAuBxF,MAAlE,WAAA3L,CAAmBkR,EAAwBC,EAAuBxF,GAAgBxL,QAA/D,KAAA+Q,OAAAA,EAAwB,KAAAC,OAAAA,EAAuB,KAAAxF,MAAAA,CAAyB,CAE3F,UAAIsC,GACH,OAAO,KAAKmD,sBAAsBhR,KAAK8Q,OAAQ,KAAQG,WAAWjR,KAAK+Q,QACxE,CAEA,OAAAR,CAAQC,GACP,MAAMjO,GAAO,QAAYsO,EAAYL,GACrC,OAAa,OAATjO,IAGGvC,KAAK8Q,OAAOP,QAAQhO,EAAKuO,SAC/B9Q,KAAK+Q,SAAWxO,EAAKwO,QACrB/Q,KAAKuL,MAAMgF,QAAQhO,EAAKgJ,OAE1B,CAEA,QAAAkF,GACC,MAAO,cAAczQ,KAAK8Q,UAAU9Q,KAAK+Q,UAAU/Q,KAAKuL,MAAMmF,eAC/D,EAGM,MAAMQ,UAAqB,IACdJ,OAAwBC,OAAuBxF,MAAqBC,UAAsBC,OAA7G,WAAA7L,CAAmBkR,EAAwBC,EAAuBxF,EAAqBC,EAAY,EAAUC,GAAS,GAAS1L,QAA5G,KAAA+Q,OAAAA,EAAwB,KAAAC,OAAAA,EAAuB,KAAAxF,MAAAA,EAAqB,KAAAC,UAAAA,EAAsB,KAAAC,OAAAA,CAA2B,CAExI,UAAIoC,GACH,OAAO,KAAKmD,sBAAsBhR,KAAK8Q,OAAQ,KAAQG,WAAWjR,KAAK+Q,OAA0B,GAAjB/Q,KAAKwL,WACtF,CAEA,OAAA+E,CAAQC,GACP,MAAMjO,GAAO,QAAY2O,EAAcV,GACvC,OAAa,OAATjO,IAGGvC,KAAK8Q,OAAOP,QAAQhO,EAAKuO,SAC/B9Q,KAAK+Q,SAAWxO,EAAKwO,QACrB/Q,KAAKuL,MAAMgF,QAAQhO,EAAKgJ,QACxBvL,KAAKwL,YAAcjJ,EAAKiJ,WACxBxL,KAAKyL,SAAWlJ,EAAKkJ,OAEvB,CAEA,QAAAgF,GACC,MAAO,gBAAgBzQ,KAAK8Q,UAAU9Q,KAAK+Q,UAAU/Q,KAAKuL,MAAMmF,iBAAiB1Q,KAAKyL,QACvF,EAKM,MAAM0F,EACZlB,OAEA,WAAArQ,CAAYwR,GACXpR,KAAKiQ,OAAS,IAAIoB,aAAqB,EAARD,EAChC,CAEA,GAAAtF,CAAIlE,EAAe0J,EAAgBC,EAAgBC,EAAcC,GAChE,MAAM5F,EAAY,EAARjE,EACV5H,KAAKiQ,OAAOpE,GAAKyF,EACjBtR,KAAKiQ,OAAOpE,EAAI,GAAK0F,EACrBvR,KAAKiQ,OAAOpE,EAAI,GAAK2F,EACrBxR,KAAKiQ,OAAOpE,EAAI,GAAK4F,CACtB,EAGM,MAAMC,UAAqB,IAIY/D,MAAsBpC,MAAqBE,OAH/EoC,OACToC,OAEA,WAAArQ,CAAYgB,EAAiC+M,EAAsBpC,EAAqBE,GAAS,GAChG1L,QAD4C,KAAA4N,MAAAA,EAAsB,KAAApC,MAAAA,EAAqB,KAAAE,OAAAA,EAEvFzL,KAAKiQ,OAASrP,EAAQqP,OACtBjQ,KAAK6N,OAAS,KAAK8D,yBAAyB3R,KAAKiQ,QAAQW,OAAe,GAARjD,EACjE,CAEA,kBAAOiE,CAAYC,EAAgBC,EAAcnE,EAAepC,EAAcE,GAAS,GACtF,MAAM7K,EAAU,IAAIuQ,EAAgB,GAEpC,OADAvQ,EAAQkL,IAAI,EAAG+F,EAAM9N,EAAG8N,EAAM7N,EAAG8N,EAAI/N,EAAG+N,EAAI9N,GACrC,IAAI0N,EAAa9Q,EAAS+M,EAAOpC,EAAOE,EAChD,CAEA,OAAA8E,CAAQC,GACP,MAAMjO,GAAO,QAAYmP,EAAclB,GACvC,OAAa,OAATjO,IAGGsN,EAAqB7P,KAAKiQ,OAAQ1N,EAAK0N,SAC7CjQ,KAAKuL,MAAMgF,QAAQhO,EAAKgJ,QACxBvL,KAAK2N,QAAUpL,EAAKoL,OACpB3N,KAAKyL,SAAWlJ,EAAKkJ,OAEvB,CAEA,QAAAgF,GACC,IAAIP,EAAI,gBACR,MAAMD,EAASjQ,KAAKiQ,OACpB,IAAK,IAAIpE,EAAI,EAAGA,EAAIoE,EAAO1J,OAAQsF,GAAK,EAAG,CAK1CqE,GAAK,IAJUD,EAAOpE,MACPoE,EAAOpE,EAAI,QACboE,EAAOpE,EAAI,MACXoE,EAAOpE,EAAI,OAC0BA,EAAI,EAAIoE,EAAO1J,OAAS,KAAO,GAClF,CACA,OAAO2J,EAAI,IAAIlQ,KAAK2N,SAAS3N,KAAKuL,MAAMmF,iBAAiB1Q,KAAKyL,QAC/D,EAGM,MAAMsG,EACZ9B,OAEA,WAAArQ,CAAYwR,GACXpR,KAAKiQ,OAAS,IAAIoB,aAAqB,EAARD,EAChC,CAEA,GAAAtF,CAAIlE,EAAe7D,EAAWC,GAC7B,MAAM6H,EAAY,EAARjE,EACV5H,KAAKiQ,OAAOpE,GAAK9H,EACjB/D,KAAKiQ,OAAOpE,EAAI,GAAK7H,CACtB,EAGM,MAAMgO,UAAsB,IAIYrE,MAAsBpC,MAAqBE,OAHhFoC,OACToC,OAEA,WAAArQ,CAAYgB,EAAkC+M,EAAsBpC,EAAqBE,GAAS,GACjG1L,QAD6C,KAAA4N,MAAAA,EAAsB,KAAApC,MAAAA,EAAqB,KAAAE,OAAAA,EAExFzL,KAAKiQ,OAASrP,EAAQqP,OACtBjQ,KAAK6N,OAAS,KAAK8D,yBAAyB3R,KAAKiQ,QAAQW,OAAe,GAARjD,EACjE,CAEA,OAAA4C,CAAQC,GACP,MAAMjO,GAAO,QAAYyP,EAAexB,GACxC,OAAa,OAATjO,IAGGsN,EAAqB7P,KAAKiQ,OAAQ1N,EAAK0N,SAC7CjQ,KAAKuL,MAAMgF,QAAQhO,EAAKgJ,QACxBvL,KAAK2N,QAAUpL,EAAKoL,OACpB3N,KAAKyL,SAAWlJ,EAAKkJ,OAEvB,CAEA,QAAAgF,GACC,MAAO,iBAAiBT,EAA0BhQ,KAAKiQ,WAAWjQ,KAAK2N,SAAS3N,KAAKuL,MAAMmF,iBAAiB1Q,KAAKyL,QAClH,EAGM,MAAMwG,UAA0B,IAIQ1G,MAHrCsC,OACToC,OAEA,WAAArQ,CAAYgB,EAAkC2K,GAC7CxL,QAD6C,KAAAwL,MAAAA,EAE7CvL,KAAKiQ,OAASrP,EAAQqP,OACtBjQ,KAAK6N,OAAS,KAAK8D,yBAAyB3R,KAAKiQ,OAClD,CAEA,OAAAM,CAAQC,GACP,MAAMjO,GAAO,QAAY0P,EAAmBzB,GAC5C,QAAa,OAATjO,IACHsN,EAAqB7P,KAAKiQ,OAAQ1N,EAAK0N,UACvCjQ,KAAKuL,MAAMgF,QAAQhO,EAAKgJ,OAK1B,CAEA,QAAAkF,GACC,MAAO,qBAAqBT,EAA0BhQ,KAAKiQ,WAAWjQ,KAAKuL,MAAMmF,eAClF,EAGM,MAAMwB,UAAiB,IAGVC,SAA0BlJ,KAAqBmJ,KAAmB7G,MAF5EsC,OAET,WAAAjO,CAAmBuS,EAA0BlJ,EAAqBmJ,EAAmB7G,GACpFxL,QADkB,KAAAoS,SAAAA,EAA0B,KAAAlJ,KAAAA,EAAqB,KAAAmJ,KAAAA,EAAmB,KAAA7G,MAAAA,EAEpF,MAAM8G,EAAWrS,KAAKoS,KAAK5D,KAAKxO,KAAKiJ,MACrCjJ,KAAK6N,OAAS,IAAI,KACjB7N,KAAKmS,SAASpO,EACd/D,KAAKmS,SAASnO,EAAIqO,EAASC,SAC3BD,EAAS7D,KAAKzK,EACdsO,EAAS7D,KAAKxK,EAEhB,CAEA,OAAAuM,CAAQC,GACP,MAAMjO,GAAO,QAAY2P,EAAU1B,GACnC,OAAa,OAATjO,IAGGvC,KAAKmS,SAAS5B,QAAQhO,EAAK4P,WACjCnS,KAAKiJ,OAAS1G,EAAK0G,MACnBjJ,KAAKoS,OAAS7P,EAAK6P,MACnBpS,KAAKuL,MAAMgF,QAAQhO,EAAKgJ,OAE1B,CAEA,QAAAkF,GACC,MAAO,YAAYzQ,KAAKmS,aAAanS,KAAKiJ,UAAS,QAAMjJ,KAAKoS,SAASpS,KAAKuL,MAAMmF,eACnF,EAGM,MAAM6B,UAAmB,IACZJ,SAA0BpF,OAAuBM,QAApE,WAAAzN,CAAmBuS,EAA0BpF,EAAuBM,EAAU,GAAKtN,QAAhE,KAAAoS,SAAAA,EAA0B,KAAApF,OAAAA,EAAuB,KAAAM,QAAAA,CAAwB,CAE5F,UAAIQ,GACH,OAAO,KAAK2E,mBAAmBxS,KAAKmS,SAAUnS,KAAK+M,OAAOyB,KAC3D,CAEA,OAAA+B,CAAQC,GACP,MAAMjO,GAAO,QAAYgQ,EAAY/B,GACrC,OAAa,OAATjO,IAGGvC,KAAKmS,SAAS5B,QAAQhO,EAAK4P,WACjCnS,KAAK+M,SAAWxK,EAAKwK,QACrB/M,KAAKqN,UAAY9K,EAAK8K,QAExB,CAEA,QAAAoD,GACC,MAAO,cAAczQ,KAAKmS,aAAY,QAAMnS,KAAK+M,WAAW/M,KAAKqN,SAClE,EAGM,MAAMoF,UAAwB,IAIjB7N,UAHViJ,OACTN,KAEA,WAAA3N,CAAmBgF,EAAgC8N,GAElD,IAAIC,EADJ5S,QADkB,KAAA6E,UAAAA,EAGd8N,aAAwB,KAC3B1S,KAAKuN,KAAOmF,EACZC,EAAYD,EAAa7E,SAGxB7N,KAAKuN,KADFmF,aAAwBhH,MACf,IAAI,IAAkBgH,GAEtB,IAAI,IAAkB,CAACA,IAEpCC,EAAY3S,KAAKuN,KAAKM,SAEvB,QAAc8E,EAAW,mDACzB3S,KAAK6N,OAAS8E,EAAUC,gBAAgB5S,KAAK4E,UAC9C,CAEA,OAAA2L,CAAQC,GACP,MAAMjO,GAAO,QAAYkQ,EAAiBjC,GAC1C,GAAa,OAATjO,EACH,OAAO,EAER,IAAKvC,KAAK4E,UAAU2L,QAAQhO,EAAKqC,WAChC,OAAO,EAER,MAAMiO,EAAc7S,KAAKuN,KAAKuF,aACxBC,EAAcxQ,EAAKgL,KAAKuF,aAC9B,GAAID,EAAYtM,SAAWwM,EAAYxM,OACtC,OAAO,EAER,IAAK,IAAIsF,EAAI,EAAGA,EAAIgH,EAAYtM,SAAUsF,EACzC,IAAKgH,EAAYhH,GAAI0E,QAAQwC,EAAYlH,IACxC,OAAO,EAGT,OAAO,CACR,CAEA,QAAA4E,CAASuC,EAAS,IACjB,MAAO,iBAAiBhT,KAAK4E,UAAU6L,eAAezQ,KAAKuN,KAAKkD,SAASuC,EAAS,OACnF,E,0KCtUmBC,KAAKC,GAUzB,MAAMC,EAAkB,IAAI,IAAM,WAC5BC,EAAiB,IAAI,IAAM,CAAC,EAAG,EAAG,GAAI,IAQrC,MAAMC,EAeOC,OAAkCC,MAAuBC,OAAwB5L,MAAkB6L,iBAbtHC,KAEAC,SAWA,WAAA/T,CAAmB0T,EAAkCC,EAAuBC,EAAwB5L,EAAQ,EAAU6L,EAAgD,KAAMG,GAAzJ,KAAAN,OAAAA,EAAkC,KAAAC,MAAAA,EAAuB,KAAAC,OAAAA,EAAwB,KAAA5L,MAAAA,EAAkB,KAAA6L,iBAAAA,OAChG3K,IAAjB8K,EACH5T,KAAK0T,KAAOE,EACFJ,aAAkB9H,MAC5B1L,KAAK0T,KAAOF,EAAO5L,IAEnB5H,KAAK0T,KAAOF,EACZxT,KAAKwT,OAAS,CAACA,IAEhBxT,KAAK2T,UAAW,CACjB,EAIM,MAAME,EAMO3O,OAAwC4O,SAA3D,WAAAlU,CAAmBsF,EAA2B,KAAa4O,EAAoB,MAA5D,KAAA5O,OAAAA,EAAwC,KAAA4O,SAAAA,CAC3D,EAIM,MAAMC,EACJC,OAAQ,EACRC,KAAM,EACNC,UAAW,EACXC,WAAY,EACZC,UAAW,EACXC,UAAW,EACXC,SAAU,EAGlBC,SAAW,IAAI,KAEfC,QAAU,IAAI,KAEdC,OAAS,IAAI,KAGb,QAAIC,GAAkB,OAAO1U,KAAKgU,KAAO,CAEzC,MAAIW,GAAgB,OAAO3U,KAAKiU,GAAK,CAErC,WAAIW,GAAqB,OAAO5U,KAAKkU,QAAU,CAE/C,YAAIW,GAAsB,OAAO7U,KAAKyU,OAAOK,IAAI9U,KAAKwU,QAAU,CAEhE,UAAIO,GAAoB,OAAO/U,KAAKyU,OAAOK,IAAI9U,KAAKuU,SAAW,CAE/D,YAAIS,GAAa,OAAOhV,KAAKmU,SAAW,CAExC,WAAIc,GAAY,OAAOjV,KAAKoU,QAAU,CAEtC,WAAIc,GAAY,OAAOlV,KAAKqU,QAAU,CAEtC,UAAIc,GAAW,OAAOnV,KAAKsU,OAAS,CAEpC,iBAAIc,GAAkB,OAAOpV,KAAKoU,UAAYpU,KAAKqU,QAAU,CAK7D,KAAAgB,CAAMtR,EAAWC,EAAWgR,GAAW,EAAOC,GAAU,EAAOC,GAAU,EAAOC,GAAS,GACxFnV,KAAKgU,OAAQ,EACbhU,KAAKkU,UAAW,EAChBlU,KAAKuU,SAASxQ,EAAIA,EAClB/D,KAAKuU,SAASvQ,EAAIA,EAClBhE,KAAKwU,QAAUxU,KAAKuU,SAASrU,QAC7BF,KAAKyU,OAASzU,KAAKuU,SAASrU,QAC5BF,KAAKmU,UAAYa,EACjBhV,KAAKoU,SAAWa,EAChBjV,KAAKqU,SAAWa,EAChBlV,KAAKsU,QAAUa,CAChB,CAEA,IAAAG,CAAKvR,EAAWC,EAAWgR,GAAW,EAAOC,GAAU,EAAOC,GAAU,EAAOC,GAAS,GACvFnV,KAAKyU,OAAO1Q,EAAIA,EAChB/D,KAAKyU,OAAOzQ,EAAIA,EAChBhE,KAAKmU,UAAYa,EACjBhV,KAAKoU,SAAWa,EAChBjV,KAAKqU,SAAWa,EAChBlV,KAAKsU,QAAUa,CAChB,CAEA,OAAAI,CAAQP,GAAW,EAAOC,GAAU,EAAOC,GAAU,EAAOC,GAAS,GACpEnV,KAAKiU,KAAM,EACXjU,KAAKkU,UAAW,EAChBlU,KAAKmU,UAAYa,EACjBhV,KAAKoU,SAAWa,EAChBjV,KAAKqU,SAAWa,EAChBlV,KAAKsU,QAAUa,CAChB,CAEA,MAAAK,GACCxV,KAAKkU,UAAW,CACjB,CAEA,IAAAuB,GACCzV,KAAKwU,QAAUxU,KAAKyU,OAAOvU,QAC3BF,KAAKgU,OAAQ,EACb,MAAM0B,EAAQ1V,KAAKiU,IAEnB,OADAjU,KAAKiU,KAAM,EACJyB,CACR,EA8GM,MAAMC,GAGN,MAAMC,UAAsBD,EAKNE,KAA5B,WAAAjW,CAA4BiW,GAC3B9V,QAD2B,KAAA8V,KAAAA,CAE5B,EAGM,MAAMC,UAA4BH,EAKrBpI,KAAnB,WAAA3N,CAAmB2N,GAClBxN,QADkB,KAAAwN,KAAAA,CAEnB,EAGM,MAAMwI,UAAwBJ,EAQ5BE,KACAtI,KACA3F,MAHR,WAAAhI,CACQiW,EACAtI,EACA3F,GAEP7H,QAJO,KAAA8V,KAAAA,EACA,KAAAtI,KAAAA,EACA,KAAA3F,MAAAA,CAGR,EAGM,MAAMoO,UAA4BL,EAQhCE,KACAtI,KACA3F,MAHR,WAAAhI,CACQiW,EACAtI,EACA3F,GAEP7H,QAJO,KAAA8V,KAAAA,EACA,KAAAtI,KAAAA,EACA,KAAA3F,MAAAA,CAGR,EAGM,MAAMqO,UAAsBN,EAQ1BE,KACAtI,KACA3F,MAHR,WAAAhI,CACQiW,EACAtI,EACA3F,GAEP7H,QAJO,KAAA8V,KAAAA,EACA,KAAAtI,KAAAA,EACA,KAAA3F,MAAAA,CAGR,EAGM,MAAMsO,UAAwBP,EAQ5BE,KACAtI,KACA3F,MAHR,WAAAhI,CACQiW,EACAtI,EACA3F,GAEP7H,QAJO,KAAA8V,KAAAA,EACA,KAAAtI,KAAAA,EACA,KAAA3F,MAAAA,CAGR,EAOM,MAAMuO,UAAsBR,EAS1BE,KACAtI,KACA6I,KACAC,GAJR,WAAAzW,CACQiW,EACAtI,EACA6I,EACAC,GAEPtW,QALO,KAAA8V,KAAAA,EACA,KAAAtI,KAAAA,EACA,KAAA6I,KAAAA,EACA,KAAAC,GAAAA,CAGR,EAGM,MAAMC,UAAoB5K,MAChC,aAAO6K,CAAOC,GACb,MAAMC,EAAc,IAAIH,EAExB,OADAG,EAAYxQ,KAAKuQ,GACVC,CACR,CACA,MAAAC,CAAOnU,GAIN,OAHa,OAATA,GACHvC,KAAKiG,QAAQ1D,GAEPvC,IACR,CACA,cAAA2W,CAAqCjO,EAAsBkO,GAE1D,OADA5W,KAAK6W,cAAiBnO,EAAMkO,GAAU,GAC/B5W,IACR,CACA,aAAA6W,CAAoCnO,EAAsBkO,EAA0BE,GAAO,GAC1F,IAAK,MAAMN,KAAUxW,KACpB,GAAIwW,aAAkB9N,IACrBkO,EAASJ,GACLM,GACH,OAIH,OAAO9W,IACR,CACA,mBAAA+W,CAA0CrO,GACzC,IAAImD,EAAI7L,KAAKuG,OACb,KAAOsF,KAAK,CACI7L,KAAK6L,aACEnD,GACrB1I,KAAKgX,OAAOnL,EAAG,EAEjB,CACA,OAAO7L,IACR,CACA,YAAAiX,CAAmCvO,GAClC,IAAK,MAAM8N,KAAUxW,KACpB,GAAIwW,aAAkB9N,EACrB,OAAO,EAGT,OAAO,CACR,EA2CM,MAAewO,EAEOxO,KAA5B,WAAA9I,CAA4B8I,GAAA,KAAAA,KAAAA,CAAgB,EA2BtC,MAAeyO,UAA6BD,EAElD,WAAAtX,CAAY8I,GACX3I,MAAM2I,EACP,CAqCA,QAAA0O,CAASC,GAAe,OAAO,CAAO,CAGtC,KAAAnX,CAAMmX,IAAe,QAAY,4CAA8C,EAIzE,MAAeC,UAAoCH,EAEzD,WAAAvX,CAAY8I,GACX3I,MAAM2I,EACP,CA6BA,iBAAA6O,CAAkBC,EAAaC,EAAaC,EAAYC,GAAc,OAAO,CAAO,EAuE9E,MAAMC,EA2DU5K,OAAqC6K,eAAwCC,UAzDzFC,KAAwB,KACxBC,KAAsB,KAEtBC,SAA0B,KAI1BC,gBAAiC,KAEjCC,aAAe,IAAIpE,EAEnBqE,MAAQ,IAAIrE,EAEZsE,QAAU,IAAI5W,IAEd6W,WAAa,EAEbC,eAAiB,EAIjBC,aAAc,EAEdC,iBAAkB,EAEpBC,mBAIEC,OAAS,EAETC,SAAW,EAIXrK,MAAQ,EAERsK,SAAW,EACXtQ,OAAqC,CAAC,GAAI,IAC1CuQ,cACAC,aACAC,2BAA4B,EAC5BC,cAAsC,KACtCC,eAAsB,KACtBC,WAA8B,KAG9BC,cAAe,EAGzBC,oBAAsB,KAAM,EAO5B,WAAAzZ,CAAsBoN,EAAqC6K,EAAwCC,GAAY,GAAzF,KAAA9K,OAAAA,EAAqC,KAAA6K,eAAAA,EAAwC,KAAAC,UAAAA,EAClG,MAAMtV,GAAM,QAAQwK,EAAOsM,WAAW,KAAM,CAAEhN,OAAO,KACrDtM,KAAK8Y,cAAgB,IAAI,KAAoB9Y,KAAKgN,OAAQxK,EAAKsV,GAC/D9X,KAAK+Y,aAAe,IAAIQ,QAGxBvZ,KAAK0Y,mBAAqB1Y,KAAKwZ,cAAcC,KAAKzZ,MAElDA,KAAK0Z,cAEL1Z,KAAK2Z,cACN,CAKA,aAAI9M,GACH,OAAO7M,KAAK8Y,aACb,CAGA,gBAAA/K,CAAiByI,EAAuBoD,EAAQ,GAC/C5Z,KAAKuI,OAAOqR,GAAO3T,KAAKuQ,EACzB,CAGA,cAAIqD,GACH,OAAO7Z,KAAKuI,OAAO,EACpB,CAGA,iBAAIuR,GACH,OAAO9Z,KAAKuI,OAAO,EACpB,CAMA,UAAAwR,CAAWrR,GACV,QAAkB,OAAd1I,KAAK+X,OAAkB/X,KAAK+X,KAAKpE,aAGjCjL,GACIA,IAAS1I,KAAK+X,KAAKzE,OAAO5K,KAGnC,CAKA,oBAAAsR,CAAqBxG,GACpB,OAAqB,OAAdxT,KAAK+X,MAAiB/X,KAAK+X,KAAKpE,UAAY3T,KAAK+X,KAAKvE,SAAWA,CACzE,CAGA,eAAIyG,GAAgB,OAAOja,KAAKoZ,YAAc,CAG9C,gBAAAc,GAAqBla,KAAKoZ,cAAe,CAAM,CAOvC,WAAAM,GAEP,MAAMS,EAAc,CACnB,YACA,YACA,UACA,cAED,IAAK,MAAMC,KAAcD,EAAa,CAErC,MAAME,EAAYD,EAAWE,cAC7Bta,KAAKgN,OAAOuN,iBAAiBF,GAAYG,IACxCA,EAAMC,kBACN,OAEAza,KADiD,GAAGoa,UAClCI,EAAM,GAE1B,CAEA,MAAME,EAAc,CACnB,SAED,IAAK,MAAMC,KAAcD,EAAa,CAErC,MAAML,EAAYM,EAAWL,cAC7Bta,KAAKgN,OAAOuN,iBAAiBF,GAAYG,IACxCA,EAAMC,kBACN,OAEAza,KADiD,GAAG2a,UAClCH,EAAM,GAE1B,CAEA,MAAMI,EAAc,CACnB,aACA,YACA,WACA,eAED,IAAK,MAAMC,KAAcD,EAAa,CAErC,MAAMP,EAAYQ,EAAWP,cAC7Bta,KAAKgN,OAAOuN,iBAAiBF,GAAYG,IACxCA,EAAMM,iBACN,OAEA9a,KADiD,GAAG6a,UAClCL,EAAM,GAE1B,CACD,CAOU,qBAAAO,CAAsBP,GAQ/B,OALEA,EAAMrF,OAAS,EAAmB,IAClCqF,EAAMvF,QAAU,EAAoB,IACpCuF,EAAMxF,SAAW,EAAqB,IACtCwF,EAAMtF,QAAU,EAAoB,EAGvC,CAOA,YAAAyE,GACC,GAAI3Z,KAAK8X,UAER,OAED,MAAM9K,EAAShN,KAAKgN,QACpB,QAAaA,GAEe,OAAxBA,EAAOgO,cAA0C,IAAjBhO,EAAOW,OAAiC,IAAlBX,EAAOsD,SAChEtQ,KAAK8Y,cAAcmC,UACnBjb,KAAKkb,iBAEP,CAMQ,UAAAC,GAEP,IAAMnb,KAAKmY,aAAavD,SAAoC,OAAzB5U,KAAKkY,kBAA8BlY,KAAK+X,KAC1E,OAAO,EAIR,IAAK/X,KAAK+X,KAAKpE,UAAa3T,KAAKmY,aAAapD,OAAOqG,QAAUC,GAAgC,CAE9F,MAAM5H,EAAmBzT,KAAK+X,KAAKtE,iBACnC,GAAyB,OAArBA,IAA8BA,EAAiBzT,KAAKmY,aAAapD,OAAOuG,OAG3E,OADAtb,KAAK+X,KAAO,MACL,EAGR/X,KAAK+X,KAAKpE,UAAW,EAErB3T,KAAKub,iBACN,CAGA,OAAOvb,KAAK+X,KAAKpE,QAClB,CAKQ,iBAAA6H,GAEPxb,KAAKgY,KAAO,KACZhY,KAAKiY,SAAW,KAEhBjY,KAAK+X,KAAO,KACZ/X,KAAKgY,KAAO,KAEZhY,KAAKoY,MAAM5C,SACXxV,KAAKmY,aAAa3C,SAElBxV,KAAKkY,gBAAkB,KAGvBlY,KAAKkb,gBACN,CAKQ,cAAAO,CAAejB,GAEtB,MAAMkB,EAAUlB,EAAMmB,QAAU3b,KAAK6Y,SAC/B+C,EAAUpB,EAAMqB,QAAU7b,KAAK6Y,SACrC7Y,KAAKoY,MAAM/C,MAAMqG,EAASE,EAASpB,EAAMxF,SAAUwF,EAAMvF,QAASuF,EAAMtF,QAASsF,EAAMrF,QAE1D,OAAzBnV,KAAKkY,iBACRlY,KAAKmY,aAAa9C,MAAMqG,EAASE,EAASpB,EAAMxF,SAAUwF,EAAMvF,QAASuF,EAAMtF,QAASsF,EAAMrF,QAI/FnV,KAAKkb,gBACN,CAKQ,cAAAY,CAAetB,GAEtB,MAAMkB,EAAUlB,EAAMmB,QAAU3b,KAAK6Y,SAC/B+C,EAAUpB,EAAMqB,QAAU7b,KAAK6Y,SACrC7Y,KAAKoY,MAAM9C,KAAKoG,EAASE,EAASpB,EAAMxF,SAAUwF,EAAMvF,QAASuF,EAAMtF,QAASsF,EAAMrF,QACtFnV,KAAKmY,aAAa7C,KAAKoG,EAASE,EAASpB,EAAMxF,SAAUwF,EAAMvF,QAASuF,EAAMtF,QAASsF,EAAMrF,QAUzFnV,KAAK+X,MACR/X,KAAKmb,aAILnb,KAAKkb,gBAEP,CAKQ,YAAAa,CAAavB,GAEpBxa,KAAKoY,MAAM7C,QAAQiF,EAAMxF,SAAUwF,EAAMvF,QAASuF,EAAMtF,QAASsF,EAAMrF,QACvEnV,KAAKmY,aAAa5C,QAAQiF,EAAMxF,SAAUwF,EAAMvF,QAASuF,EAAMtF,QAASsF,EAAMrF,QAG9EnV,KAAKkb,gBACN,CAKQ,eAAAc,CAAgBxB,GAEvBxa,KAAKwb,mBACN,CAKQ,UAAAb,CAAWH,GAElB,MAAMkB,EAAUlB,EAAMmB,QAAU3b,KAAK6Y,SAC/B+C,EAAUpB,EAAMqB,QAAU7b,KAAK6Y,SACrC7Y,KAAKoY,MAAM9C,KAAKoG,EAASE,EAASpB,EAAMxF,SAAUwF,EAAMvF,QAASuF,EAAMtF,QAASsF,EAAMrF,QACtFnV,KAAKmY,aAAa7C,KAAKoG,EAASE,EAASpB,EAAMxF,SAAUwF,EAAMvF,QAASuF,EAAMtF,QAASsF,EAAMrF,QAG7F,IAAI8G,EAAe,EACnB,GAx8BmB,IAw8BfzB,EAAM0B,UAET,OAKD,GAh9BmB,IA48BR1B,EAAM0B,YAEhBD,EAAe,IAEK,IAAjBzB,EAAM2B,OAET,OAID,MAAM5I,EAAQiH,EAAM2B,OAASF,EACf,IAAV1I,IACHvT,KAAKsY,YAAc/E,EACnBvT,KAAKuY,eAAiBvY,KAAK+a,sBAAsBP,GACjDxa,KAAKkb,iBAEP,CAKQ,eAAAkB,CAAgB5B,GAEvB,IAAK,MAAM6B,KAAS7B,EAAM8B,cAAe,CACxC,MAAMlM,GAAO,QAASmM,QAASF,EAAMnX,QAAQsX,wBACvCC,EAAU,IAAI1I,EACd2I,EAASL,EAAMM,QAAUvM,EAAKwM,KAC9BC,EAASR,EAAMS,QAAU1M,EAAK2M,IACpCN,EAAQpH,MAAMqH,EAAS1c,KAAK6Y,SAAUgE,EAAS7c,KAAK6Y,UACpD7Y,KAAKqY,QAAQvM,IAAIuQ,EAAMW,WAAYP,EACpC,CAGA,GAAIjC,EAAM8B,cAAc/V,OAAS,GAA8B,OAAzBvG,KAAKkY,gBAA0B,CAEpE,MAAMmE,EAAQ7B,EAAM8B,cAAc,GAClCtc,KAAKkY,gBAAkBmE,EAAMW,WAG7B,MAAM5M,GAAO,QAASmM,QAASF,EAAMnX,QAAQsX,wBACvCE,EAASL,EAAMM,QAAUvM,EAAKwM,KAC9BC,EAASR,EAAMS,QAAU1M,EAAK2M,IACpC/c,KAAKmY,aAAa9C,MAAMqH,EAAS1c,KAAK6Y,SAAUgE,EAAS7c,KAAK6Y,SAC/D,CAGA7Y,KAAKkb,gBACN,CAKQ,cAAA+B,CAAezC,GAEtB,IAAK,MAAM6B,KAAS7B,EAAM0C,eAAgB,CACzC,MAAM9M,GAAO,QAASmM,QAASF,EAAMnX,QAAQsX,wBACvCC,EAAUzc,KAAKqY,QAAQjP,IAAIiT,EAAMW,YACvC,QAAgBlU,IAAZ2T,EACH,SAED,MAAMC,EAASL,EAAMM,QAAUvM,EAAKwM,KAC9BC,EAASR,EAAMS,QAAU1M,EAAK2M,IACpCN,EAAQnH,KAAKoH,EAAS1c,KAAK6Y,SAAUgE,EAAS7c,KAAK6Y,SACpD,CAGA,GAA6B,OAAzB7Y,KAAKkY,gBACR,IAAK,MAAMmE,KAAS7B,EAAM0C,eAAgB,CACzC,GAAIb,EAAMW,aAAehd,KAAKkY,gBAC7B,SAGD,MAAM9H,GAAO,QAASmM,QAASF,EAAMnX,QAAQsX,wBACvCE,EAASL,EAAMM,QAAUvM,EAAKwM,KAC9BC,EAASR,EAAMS,QAAU1M,EAAK2M,IACpC/c,KAAKmY,aAAa7C,KAAKoH,EAAS1c,KAAK6Y,SAAUgE,EAAS7c,KAAK6Y,UACzD7Y,KAAK+X,MACR/X,KAAKmb,aAEN,KACD,CAIDnb,KAAKkb,gBACN,CAKQ,aAAAiC,CAAc3C,GAErB,IAAK,MAAM6B,KAAS7B,EAAM0C,eACzBld,KAAKqY,QAAQ+E,OAAOf,EAAMW,YAI3B,GAA6B,OAAzBhd,KAAKkY,gBACR,IAAK,MAAMmE,KAAS7B,EAAM0C,eACzB,GAAIb,EAAMW,aAAehd,KAAKkY,gBAA9B,CAIAlY,KAAKmY,aAAa5C,UAElBvV,KAAKkY,gBAAkB,KACvB,KALA,CAUFlY,KAAKkb,gBACN,CAKQ,gBAAAmC,CAAiB7C,GAExB,IAAK,MAAM6B,KAAS7B,EAAM0C,eACzBld,KAAKqY,QAAQ+E,OAAOf,EAAMW,YAI3B,GAA6B,OAAzBhd,KAAKkY,gBACR,IAAK,MAAMmE,KAAS7B,EAAM0C,eACzB,GAAIb,EAAMW,aAAehd,KAAKkY,gBAK9B,YADAlY,KAAKwb,oBAMPxb,KAAKkb,gBACN,CAGQ,gBAAAoC,IACP,QAActd,KAAKiZ,cAAe,iBAClCjZ,KAAKkZ,eAAiBlZ,KAAKiZ,cAAc,GACzCjZ,KAAKkb,gBACN,CAGQ,eAAAK,GACoB,OAAvBvb,KAAKiZ,gBACRsE,OAAOC,aAAaxd,KAAKiZ,cAAc,IACvCjZ,KAAKiZ,cAAgB,KAEvB,CAOA,cAAAiC,GACKlb,KAAKyY,kBAITzY,KAAKyY,iBAAkB,EACvB8E,OAAOE,sBAAsBzd,KAAK0Y,oBACnC,CAKU,aAAAc,CAAckE,GACD,IAAlB1d,KAAK4Y,SACR5Y,KAAK2Y,OAAS,EAEd3Y,KAAK2Y,OAAS+E,EAAI1d,KAAK4Y,SAExB5Y,KAAK4Y,SAAW8E,EAChB1d,KAAKyY,iBAAkB,EACvBzY,KAAK6X,gBACN,CAQA,KAAA8F,CAAMpP,EAAQ,GACbvO,KAAKoZ,cAAe,EACpBpZ,KAAKuO,MAAQA,EACbvO,KAAK6Y,SAAW,EAAItK,EACpBvO,KAAKiY,SAAW,IACjB,CAQA,GAAAnG,GAGC9R,KAAK8Y,cAAc8E,OAClB,CAAC,IAAI,IAAkB5d,KAAKuI,OAAO,IAAK,IAAI,IAAkBvI,KAAKuI,OAAO,KAC1EvI,KAAKuO,OAENvO,KAAKuI,OAAS,CAAC,GAAI,IACnB,MAAMsV,EAAiB7d,KAAKwY,YAO5B,GANAxY,KAAKwY,aAAc,EACnBxY,KAAKgY,KAAOhY,KAAKiY,SACjBjY,KAAKsY,WAAa,EAClBtY,KAAKqY,QAAQ1M,SAAS8Q,IACrBA,EAAQhH,MAAM,IAEXzV,KAAKmY,aAAa1C,OAAQ,CAC7B,MAAMqI,EAA4B,OAAd9d,KAAK+X,MAAiB/X,KAAK+X,KAAKpE,SAMpD,OALA3T,KAAK+X,KAAO,KACZ/X,KAAKgY,KAAO,KACZhY,KAAKub,kBACLvb,KAAKkZ,eAAiB,KAEf2E,GAAkBC,CAC1B,CACC,OAAOD,CAET,CAIA,MAAAE,CAAUxV,EAAqBxE,EAAWC,EAAW0P,EAASJ,GAC7D,MAAM0K,EAAY1K,EAAO2K,UAAUje,KAAKmY,aAAa1D,OAAO1Q,EAAG/D,KAAKmY,aAAa1D,OAAOzQ,EAAGD,EAAGC,EAAG0P,IAC1FwK,EAAkBC,GAAW7K,EAAO8K,MAAMpe,KAAMuI,EAAQxE,EAAGC,EAAG0P,EAAMsK,GACrEvH,EAAcyH,GAAoB,IAAI5H,EAC5C,IAAI+H,GAAU,EAQd,OAPIL,GACHhe,KAAKmY,aAAaxD,IAClBrB,EAAO2K,UAAUje,KAAKmY,aAAa5D,SAASxQ,EAAG/D,KAAKmY,aAAa5D,SAASvQ,EAAGD,EAAGC,EAAG0P,KAEnF2K,GAAU,EACV5H,EAAYxQ,KAAK,IAAI2P,EAAclC,KAE7B,CACN2K,UACAF,UACA1H,cAEF,CAeA,IAAAlJ,CAAQhF,EAAqBxE,EAAWC,EAAWuC,EAAuB+X,EACzE5K,EACA6K,EACAC,EAAA,EACAC,GAGA,MAAMC,EACL,CACCC,EACAC,IAEAC,EAA+BJ,EAAgBE,EAAUC,GAErDE,EAAYJ,EAAyB,YAAa,GAClDK,IAAgB,QAAaD,EAAW,GACxCE,GAAgB,QAAaF,EAAW,GACxCG,EAAiBP,EAAyB,iBAAkB,IAC5DQ,EAASR,EAAyB,SAAU,IAC5CS,EAAgBT,EAAyB,gBAAiB,GAC1DU,EAAcV,EAAyB,cAAe,GACtDW,EAAeX,EAAyB,eAAgB,GAExDY,EAA6B,IADhBZ,EAAyB,aAAc,IAE1D,UAASY,GAAeN,GAAgB,wDAGxC,MAAMO,EAAwC,iBAAvBf,EACtBA,EAAmBgB,WACnB,QAAahB,EAAoB,GAC5BiB,EAAgBF,IAA0C,iBAAvBf,EACxCA,EAAmBkB,aACnB,QAAalB,EAAoB,IAC5BmB,EAA0BL,GAAeG,EAG/C,IAAItB,EAAyB,KAC7B,MAAM1H,EAAc,IAAIH,EAKlBsJ,EAAW,CAAClI,EAAK3T,EAAG4T,EAAK3T,IAAM+a,EAAerH,EAAKC,EACnDkI,EAAW,CAACnI,EAAK3T,EAAG4T,EAAK3T,IAAM+a,EAAepH,EAAKD,EACnDoI,EAAY,CAACpI,EAAK3T,EAAG4T,EAAK3T,IAAO+a,EAAe,CAACrH,EAAIC,GAAe,CAACA,EAAID,GAG/E,IAAKqI,EAAOC,GAASF,IAErB,MAAMG,EAAY,CAACvI,EAAKqI,EAAOpI,EAAKqI,IAAUjB,EAAerH,EAAKC,EAC5DuI,EAAY,CAACxI,EAAKqI,EAAOpI,EAAKqI,IAAUjB,EAAepH,EAAKD,EAC5DyI,EAAa,CAACzI,EAAKqI,EAAOpI,EAAKqI,IAAWjB,EAAe,CAACrH,EAAIC,GAAe,CAACA,EAAID,IAKjF0I,EAAcC,GAAiBP,EAAUvB,EAAc5Q,MAAO4Q,EAAcjO,SAC5EgQ,EAAQC,IAAUT,EAAU9f,KAAKmY,aAAa1D,OAAO1Q,EAAG/D,KAAKmY,aAAa1D,OAAOzQ,GAIxFgc,KADA1B,EAAsB,OAAZA,EAAmBA,EAAU+B,GACnBA,GAAiB,EAAI,EAGzC,MAAMG,GAAoBJ,EAAenB,EACnClF,GAA2B,OAAd/Z,KAAK+X,MAAiB/X,KAAK+X,KAAKpE,SAC7C8M,GAAmB1G,IAA4B,OAAd/Z,KAAK+X,MAAiB/X,KAAK+X,KAAKvE,SAAWE,EAE5EgN,IADoBjB,IAAkBgB,GAAoB/M,EAAKnN,OAAS,EAAImN,EAAKnN,QACzCia,GAAoBvB,EAAiB,GAAKC,EAASG,GACjG9Y,EAAoB,OAAXA,EAAkBA,EAASma,GACpC,MAAMC,GAAuB1N,KAAK2N,IAAIF,GAAoBna,IACnDsa,GAAuBC,IAA0BX,EAAW5Z,EAAQ+X,GACrEyC,GAAcL,GAAqBC,GACnCK,GAAkC,IAAhB5B,GAA0D,IAAhBA,GAAuC2B,GACnGE,GAAgBjhB,KAAKmY,aAAa1D,OAAOyM,SAASnd,EAAGC,EAAG6c,GAAuBC,IAGjFG,IAAiBjhB,KAAKqY,QAAQ7J,KAAO,IAAMxO,KAAK+Z,eACnD/Z,KAAK+X,KAAO,KACZ/X,KAAKwY,aAAc,GAIpB,IAAK2I,GAAWC,IAAe,CAAC,EAAG,GACnC,GAAIL,GAAa,CAEhB,IAAK/gB,KAAK+Y,aAAaxJ,IAAImE,GAAO,CACjC,MAAM2N,GAAiBX,GAAqBC,IAAwB,EACpE3gB,KAAK+Y,aAAajN,IAAI4H,EAAM,CAAC2N,EAAe,GAC7C,EAGCF,GAAWC,KAAe,QAAQphB,KAAK+Y,aAAa3P,IAAIsK,IACzD,IAAI4N,EAA6B,KAC7BL,KACHE,IAAanhB,KAAKsY,YACbtY,KAAK+X,MAAQ/X,KAAKmY,aAAavD,WAC9B5U,KAAKgZ,2BAA6BhZ,KAAKmY,aAAapD,OAAOqG,QAAUC,IAEzErb,KAAKgZ,2BAA4B,EAEjChZ,KAAKub,kBAEJ+F,EADGvC,GACY/e,KAAKmY,aAAapD,OAAOhR,GAEzB/D,KAAKmY,aAAapD,OAAO/Q,GAE/BhE,KAAKgZ,4BAEdsI,EADGvC,GACY/e,KAAKmY,aAAatD,SAAS9Q,GAE3B/D,KAAKmY,aAAatD,SAAS7Q,KAO1B,OAAhBsd,GAEHH,IAAaG,EAEZF,GADGphB,KAAK2Y,OAAS,EACH2I,EAActhB,KAAK2Y,OAEnB,IAIfwI,IAAaC,GAAcphB,KAAK2Y,OAChCyI,IAAenO,KAAKsO,KAAKvhB,KAAK2Y,OAj1CA,KAk1C1B1F,KAAKuO,IAAIJ,KAAgB,EAC5BphB,KAAKkb,kBAELkG,GAAc,EACdD,GAAYlO,KAAKwO,MAAMN,MAKzB,MAAMO,GAAmB,QAAMP,GAAW,EAAGT,GAAqBC,IAC9De,IAAqBP,KACxBA,GAAYO,EACZN,GAAc,GAGfphB,KAAK+Y,aAAajN,IAAI4H,EAAM,CAACyN,GAAWC,IACzC,MAECD,KAAc5a,EAASma,IAAsB,EAAI,EAGlDS,IAAajC,EAASG,EAEtBU,GAASoB,GAGT,MAAMQ,GACLpC,GACAxF,IACAkH,IACAjhB,KAAK+X,KAAMzE,OAAO5K,OAAS6V,EAAc7V,OACxC+W,GAAiBgB,IAEnB,GAAIkB,GAAe,CAElB,MAAMC,EAAW5C,EAAgB2B,IAAwBL,EAASP,GAASO,EAASP,EACpF,IAAI8B,EAA8E,EAAlE5O,KAAK6O,OAAOF,EAAW3C,EAAiB,GAAKuB,IACzDC,IAECd,IACHkC,GAAa,GAEdA,EAAY5O,KAAK2N,IAAI3N,KAAK8O,IAAIF,EAAW,GAAInO,EAAKnN,OAAS,IAE3Dsb,EAAY5O,KAAK2N,IAAI3N,KAAK8O,IAAIF,EAAW,GAAInO,EAAKnN,QAEnDvG,KAAKiY,SAAWjY,KAAKgY,KAAO,IAAInE,EAAOH,EAAMmO,EAC9C,MAEmB,OAAd7hB,KAAKgY,MAAiBhY,KAAKgY,KAAK9S,SAAWwO,IAC9C1T,KAAKiY,SAAWjY,KAAKgY,KAAO,MAK9B+H,GAASf,EAAgB2B,GAAuBP,EAAe,EAC/D,MAAM4B,GAAYhD,GAAiB,EAAI,EA0IvC,GAxIIW,IACGgC,KAAkBlB,KACvBV,GAASK,EAAenB,GAIxB0C,IACAlB,IACAH,EAASP,EAAQK,EAAenB,EAAiB,IAEjDc,GAASS,GAAoBwB,KAI3BL,KACE3C,GAAiBsB,EAASP,EAAQd,EAAiB,IAElDU,IACJI,GAASS,GAAoBwB,KAOhCtO,EAAK/H,SAAQ,CAACsW,EAASpW,KAEtB,MAAMqW,EAAwC,iBAAvB1D,EACtBA,EAAmB2D,QAAQF,IAC3B,QAAazD,EAAoB,GAC5B4D,IAA2C,iBAAvB5D,EACzBA,EAAmB6D,cAAcJ,IACjC,QAAazD,EAAoB,KAC5B8D,IAA+C,iBAAvB9D,EAC7BA,EAAmB+D,kBAAkBN,IACrC,QAAazD,EAAoB,KAC5BgE,EAAsB/B,IAAoBzgB,KAAK+X,KAAMnQ,QAAUiE,EASrE,GAPC8V,IACArB,GAAUP,EAAQd,EAAiB,GACnCqB,EAASP,EAAQK,EAAenB,EAAiB,IAEjDc,GAASS,GAAoBwB,KAGxBQ,IAAuBb,GAAgB,CAC5C,MAAMc,EAAmBlE,EAAcN,UAAUje,KAAKmY,aAAa1D,OAAO1Q,EAAG/D,KAAKmY,aAAa1D,OAAOzQ,EAAGic,IAAaC,IAAa+B,GAGnI,GAAIO,GAAuBjD,EAAS,EACpB,QAASjI,EAA0BiH,GAC3CmE,iBAAiB1iB,KAAMuI,EAAQ0X,IAAaC,IAAa+B,EACjE,KAAO,CACN,MAAMU,EAAgBpE,EAAcqE,iBAAiB5iB,KAAMuI,EAAQ0X,IAAaC,IAAa+B,EAASpW,EAAGiT,EAAWoD,EAASE,EAAUK,EAAkB/O,EAAK7H,EAAE,GAAI6H,EAAK7H,EAAE,IAC3K4K,EAAYC,OAAOiM,EAAc,IACjCxE,EAAUA,GAAWwE,EAAc,EACpC,CAEA,GAAIF,EAAkB,CAErB,GACCP,GACAliB,KAAKmY,aAAazD,MAClB1U,KAAKqY,QAAQ7J,MAAQ,EACpB,CAED,MAAM+E,EAAQvT,KAAKmY,aAAa1D,OAAOK,IA1MxB,EAAC4C,EAAKqI,EAAOpI,EAAKqI,IAAUjB,EAAe,IAAI,KAAQrH,EAAIC,GAAM,IAAI,KAAQA,EAAID,GA0MrDmL,IAO3C,IADa7iB,KAAKmY,aAAa/C,eAAiBpV,KAAKqZ,wBACzCkF,EAAcnH,SAAS6K,GAAU,CAC5C,MAAMa,EAAgBvE,EAAcre,MAAM+hB,GAC1CjiB,KAAK+X,KAAO,IAAI1E,EAASkL,EAAehL,EAAOuP,EAChD,MACC9iB,KAAK+X,KAAO,IAAI1E,EAASkL,EAAehL,EAAOG,EAAM7H,EAEvD,CAGA,GACCyW,GACAtiB,KAAKmY,aAAazD,MAClB1U,KAAKqY,QAAQ7J,MAAQ,EAErB,GAA2B,OAAvBxO,KAAKiZ,cAAwB,CAChC,MAAM8J,EAAQxF,OAAOyF,WAAWhjB,KAAKsd,iBAAiB7D,KAAKzZ,MAz+CxC,KA0+CnBA,KAAKiZ,cAAgB,CAAC8J,EAAOd,EAC9B,MACCjiB,KAAKiZ,cAAc,GAAKgJ,EAKC,OAAvBjiB,KAAKiZ,eAEJjZ,KAAKiZ,cAAc,KAAOgJ,GAC7BjiB,KAAKub,kBAKHvb,KAAKkZ,iBAAmB+I,IAC3BxL,EAAYxQ,KAAK,IAAI+P,EAAoBiM,EAASvO,EAAM7H,IACxD7L,KAAKkZ,gBAAiB,GAKtBkJ,IACCpiB,KAAK+Z,eACL/Z,KAAKgZ,2BACNhZ,KAAKmY,aAAaxD,IACM,OAAxB3U,KAAKkZ,gBAELzC,EAAYxQ,KAAK,IAAI8P,EAAgBkM,EAASvO,EAAM7H,GAEtD,CAEAkU,GAASS,GAAoBwB,EAC9B,CAGA,GAAIhB,IAAmBnV,EAAI,EAAI6H,EAAKnN,OAAQ,CAC3C,MAAM0c,EAAQlD,GAASd,EAAiB,GAAK,EAAI,EAC3CiE,EAAQlD,GAASK,EAAgB,IAAM,EAC7C,IAAK,IAAI8C,EAAI,EAAGA,EAAI,IAAKA,EAAG,CAC3B,MAAOC,EAAIC,GAAMlD,EAAW8C,EAAOC,EAAY,EAAJC,GAC3C5a,EAAOtC,KAAK,IAAI,KAAW,IAAI,KAAQmd,EAAK,EAAGC,EAAK,GAAI,EAAGlQ,GAC5D,CACD,KAIiB,OAAdnT,KAAKgY,MAAiBhY,KAAKgY,KAAK9S,SAAWwO,EAAM,CACpD,MAAM4P,EAAa3D,GAA2Bc,GACxC8C,GAAWvjB,KAAKgY,KAAKlE,UAAuBwP,EAAa,EAAI,IAAM9C,GACnE7a,EAAKia,KAAcZ,EAAgB2B,GAAuBP,EAAemD,EAASA,GAAUpC,IAC3FiC,EAAIC,GAAMlD,EAAWxa,IACb,QAAS2R,EAA0BiH,GAC3CmE,iBAAiB1iB,KAAMuI,EAAQ6a,EAAIC,EAAIrjB,KAAK+X,KAAMrE,KAC1D,CACA,GAAI+L,IAAkBkC,KAAkBlB,GAAkB,CACzD,MAAM8C,EAAS5D,EAA0B,EAAIjM,EAAKnN,OAASia,GACrD7a,EAAKia,KAAcZ,EAAgB2B,GAAuBP,EAAemD,EAASA,GAAUpC,IAC3FiC,EAAIC,GAAMlD,EAAWxa,GACtB2N,GAAS,QAASgE,EAA0BiH,GAClDjL,EAAOkQ,cAAcxjB,KAAMuI,EAAQ6a,EAAIC,GACd/P,EAAOiE,kBAAkBvX,KAAKmY,aAAa1D,OAAO1Q,EAAG/D,KAAKmY,aAAa1D,OAAOzQ,EAAGof,EAAIC,KAI5GrjB,KAAK+Z,eACL/Z,KAAKgZ,2BACNhZ,KAAKmY,aAAaxD,IACM,OAAxB3U,KAAKkZ,gBAELzC,EAAYxQ,KAAK,IAAI6P,EAAoBpC,GAE3C,CAGA,MAAM+P,GAAkB1C,KAAgB/gB,KAAKmY,aAAavD,SAAoC,OAAzB5U,KAAKkY,kBAA4C,OAAdlY,KAAK+X,MAAkBkJ,GAC/H,GAAIwC,GAAiB,CACpB,MACMC,EAAkBnd,GADHoa,GAAuBD,IAItCiD,GADkBxC,GAAYjC,EAASG,IADzBqB,GAAqBC,KAEFpa,EAASmd,GAC1CE,EAA+B,IAAlBzE,EAAmC,EAAIb,EAAU,GAC7DuF,EAAIC,GAAM3D,EAAWP,IAAa+D,EAAc9D,IAAa+D,IAC7DG,EAAIC,GAAM7D,EAAWP,IAAa+D,EAAeD,EAAiB7D,IAAa+D,EAAa,GACnGrb,EAAOtC,KAAK,KAASoK,SAASwT,EAAIC,EAAIC,EAAKF,EAAIG,EAAKF,EAAI1Q,GACzD,CAGIpT,KAAKmY,aAAaxD,KACrB3U,KAAKgZ,2BAA4B,GAIlC,IAAIiL,GAAwC,KAC5C,GAAIjkB,KAAKmY,aAAaxD,IAAMoF,IAA4B,OAAd/Z,KAAKgY,KAAe,CAG7D,GAAIhY,KAAK+X,KAAMvE,SAAWE,EAAM,CAC/B,MAAM9L,EAAQ5H,KAAK+X,KAAMnQ,MACnBqa,EAAUvO,EAAK9L,GAIrB,GAHoD,iBAAvB4W,EAC5BA,EAAmB0F,UAAUjC,IAC7B,QAAazD,EAAoB,GACf,CAClB,MAAM2F,EAAUzQ,EAAKsD,OAAOpP,EAAO,GAAG,GACtCqc,GAAgB,IAAI/N,EAAgBiO,EAASzQ,EAAM9L,GACnD6O,EAAYxQ,KAAKge,IACjBjkB,KAAKoZ,cAAe,EACpBpZ,KAAKwY,aAAc,CACpB,CACD,CAEA,GAAIxY,KAAKgY,KAAK9S,SAAWwO,EAAM,CAC9B,MAAM9L,EAAQ5H,KAAKgY,KAAKlE,SAClBmO,EAAUjiB,KAAK+X,KAAMrE,KAC3BA,EAAKsD,OAAOpP,EAAO,EAAGqa,GAClBgC,IACHxN,EAAY2N,MACRH,GAAcrc,QAAUA,GAC3B6O,EAAYxQ,KAAK,IAAIkQ,EAAc8L,EAASvO,EAAMuQ,GAAcrc,MAAOA,KAGxE6O,EAAYxQ,KAAK,IAAIgQ,EAAcgM,EAASvO,EAAM9L,IAEnD5H,KAAKoZ,cAAe,EACpBpZ,KAAKwY,aAAc,CACpB,CACD,CAGA,MAAO,CACNiL,mBACAtF,UACA1H,cAEF,CAeA,mBAAA4N,CAAuBtgB,EAAWC,EAAWuC,EAAuB+X,EACnE5K,EACA9L,EACA2W,EACAE,EACAgB,GAAgB,GAGhB,MAAMf,EACL,CACCC,EACAC,IAEAC,EAA+BJ,EAAgBE,EAAUC,GAErDE,EAAYJ,EAAyB,YAAa,GAClDK,IAAgB,QAAaD,EAAW,GACxCE,GAAgB,QAAaF,EAAW,GACxCG,EAAiBP,EAAyB,iBAAkB,IAC5DQ,EAASR,EAAyB,SAAU,IAC5CW,EAAeX,EAAyB,eAAgB,GAExDY,EAA6B,IADhBZ,EAAyB,aAAc,IAE1D,UAASY,GAAeN,GAAgB,wDAExC,MAAMW,EAA0BL,GAAeG,EAKzCK,EAAY,CAACpI,EAAK3T,EAAG4T,EAAK3T,IAAO+a,EAAe,CAACrH,EAAIC,GAAM,CAACA,EAAID,GAEtE,IAAKqI,EAAOC,GAASF,IAErB,MAIOM,EAAcC,GAAiBP,EAAUvB,EAAc5Q,MAAO4Q,EAAcjO,QAInF0P,KADA1B,EAAsB,OAAZA,EAAmBA,EAAU+B,GACnBA,GAAiB,EAAI,EAGzC,MAAMG,EAAoBJ,EAAenB,EAEnCyB,GADmBjB,EAAgB/L,EAAKnN,OAAS,EAAImN,EAAKnN,QAClBia,EAAoBvB,EAAiB,GAAKC,EAASG,GACjG9Y,EAAoB,OAAXA,EAAkBA,EAASma,EACpC,MAAMC,EAAuB1N,KAAK2N,IAAIF,EAAoBna,GAI1D,IAAI4a,EAAY,EAChB,GAJoBT,EAAqBC,EAIxB,CAChB,MAAM5H,EAAe/Y,KAAK+Y,aAAa3P,IAAIsK,QACtB5K,IAAjBiQ,IACHoI,EAAYpI,EAAa,GAE3B,MAECoI,IAAc5a,EAASma,GAAsB,EAAI,EAGlDS,GAAajC,EAASG,EAEtBU,GAASoB,EAGTpB,GAASf,EAAgB2B,EAAuBP,EAAe,EAS/D,OALAL,GAAUS,GAHQxB,GAAiB,EAAI,GAGIpX,EACvC+X,IACHI,GAASK,EAAenB,GAzCN,EAACvH,EAAKqI,EAAOpI,EAAKqI,IAAUjB,EAAe,IAAI,KAAQrH,EAAIC,GAAM,IAAI,KAAQA,EAAID,GA4C7FmL,EACR,CAUA,UAAAyB,CAAW/b,EAAqBxE,EAAWC,EAAW2J,EAAe2C,EAAgBgD,GAClE,OAAdtT,KAAK+X,MAAiB/X,KAAK+X,KAAKpE,UAAYL,EAAOiR,MAAMC,QAAQxkB,KAAK+X,KAAKzE,OAAO5K,OAAS,EAC1F1I,KAAKmY,aAAa1D,OAAOyM,SAASnd,EAAGC,EAAG2J,EAAO2C,IAC9CtQ,KAAKgY,KACRhY,KAAKgY,KAAK9S,OAAS,KAEnBlF,KAAKgY,KAAO,IAAInE,EAAO,MAExB7T,KAAKiY,SAAWjY,KAAKgY,KACrB1E,EAAOmR,cAAczkB,KAAMuI,EAAQxE,EAAGC,EAAG2J,EAAO2C,EAAQtQ,KAAK+X,KAAKzE,OAAO5K,KAAM1I,KAAK+X,KAAKrE,OAEzFJ,EAAOoR,cAAc1kB,KAAMuI,EAAQxE,EAAGC,EAAG2J,EAAO2C,EAAQtQ,KAAK+X,KAAKzE,OAAO5K,KAAM1I,KAAK+X,KAAKrE,MAG1FJ,EAAOqR,UAAU3kB,KAAMuI,EAAQxE,EAAGC,EAAG2J,EAAO2C,EAE9C,CAKA,SAAAsU,GACmB,OAAd5kB,KAAK+X,MAAiB/X,KAAK+X,KAAKpE,UACnC3T,KAAK+X,KAAKzE,OAAOuR,iBAAiB7kB,KAAMA,KAAKuI,OAAO,GAAwBvI,KAAKmY,aAAa1D,OAAO1Q,EAAG/D,KAAKmY,aAAa1D,OAAOzQ,EAAGhE,KAAK+X,KAAKrE,KAAM1T,KAAK+X,KAAM/X,KAAKgY,KAEtK,CAMA,aAAA8M,CAAcC,GACTA,IAAe/kB,KAAKmZ,aACJ,OAAf4L,EACH/kB,KAAKgN,OAAOgY,aAAa,QAASD,GAElC/kB,KAAKgN,OAAOiY,gBAAgB,SAE7BjlB,KAAKmZ,WAAa4L,EAEpB,EAKD,SAASlG,EAAgEJ,EAAoCE,EAAaC,GACzH,MAAM1U,EAAQuU,EAAeE,GAC7B,OAAIzU,QACIA,EAEA0U,CAET,C,8DC7xDA,MAAMsG,EAAwB,CAC7B,oBAAsB,QAAI,gBAC1B,yBAA2B,QAAI,wBAC/B,oBAAsB,QAAI,yBAC1B,qBAAuB,QAAI,sBAC3B,kBAAoB,QAAI,mBACxB,SAAW,QAAI,WACf,WAAa,QAAI,aACjB,QAAU,QAAI,UACd,UAAa,cAGDC,EAAaC,OAAO9b,KAAK4b,GAO/B,SAASG,EAAYC,GAC3B,IAAIC,EAMJ,OALA,OAAwBJ,GAAaK,IAChCA,IAAcF,IACjBC,EAAQC,EACT,IAEMD,CACR,C,8DCtBO,MAAME,EACZC,QACAlX,KAEA,WAAA5O,CAAYmE,EAAWC,EAAW2J,EAAe2C,GAChDtQ,KAAK0lB,QAAU,IAAI,KAAQ3hB,EAAGC,GAC9BhE,KAAKwO,KAAO,IAAI,KAAQb,EAAO2C,EAChC,CAEA,yBAAOkC,CAAmBkT,EAAkBlX,GAC3C,MAAMmX,EAAInX,aAAgB,KAAUA,EAAKzK,EAAIyK,EACvCoX,EAAIpX,aAAgB,KAAUA,EAAKxK,EAAIwK,EAC7C,OAAO,IAAIiX,EAAKC,EAAQ3hB,EAAG2hB,EAAQ1hB,EAAG2hB,EAAGC,EAC1C,CAEA,wBAAOC,CAAkB/U,EAAiBtC,GACzC,MAAMmX,EAAInX,aAAgB,KAAUA,EAAKzK,EAAIyK,EACvCoX,EAAIpX,aAAgB,KAAUA,EAAKxK,EAAIwK,EAC7C,OAAO,IAAIiX,EAAK3U,EAAO/M,EAAQ,GAAJ4hB,EAAS7U,EAAO9M,EAAQ,GAAJ4hB,EAASD,EAAGC,EAC5D,CAEA,4BAAO5U,CAAsBF,EAAiBgV,GAC7C,MAAMC,EAAQD,aAAoB,KAAUA,EAAS/hB,EAAI+hB,EACnDE,EAAQF,aAAoB,KAAUA,EAAS9hB,EAAI8hB,EACzD,OAAO,IAAIL,EAAK3U,EAAO/M,EAAIgiB,EAAOjV,EAAO9M,EAAIgiB,EAAe,EAARD,EAAmB,EAARC,EAChE,CAEA,wBAAOC,CAAkBC,EAAmBC,GAC3C,MAAMC,EAAOnT,KAAK2N,IAAIsF,EAASniB,EAAGoiB,EAASpiB,GACrCsiB,EAAOpT,KAAK2N,IAAIsF,EAASliB,EAAGmiB,EAASniB,GACrCsiB,EAAQrT,KAAK8O,IAAImE,EAASniB,EAAGoiB,EAASpiB,GACtCwiB,EAAQtT,KAAK8O,IAAImE,EAASliB,EAAGmiB,EAASniB,GAC5C,OAAO,IAAIyhB,EAAKW,EAAMC,EAAMC,EAAQF,EAAMG,EAAQF,EACnD,CAEA,iBAAOG,CAAWvW,GAEjB,MAAMwW,EAAoBxW,EAAOyW,QAAO,CAACC,EAAsB/a,KAC9D,MAAMgb,EAAKhb,EAAM7H,EACX8iB,EAAKjb,EAAM5H,EACjB,OAAY,OAAR2iB,EACI,CAACC,EAAIC,EAAID,EAAIC,GAEb,CACN5T,KAAK2N,IAAI+F,EAAI,GAAIC,GACjB3T,KAAK2N,IAAI+F,EAAI,GAAIE,GACjB5T,KAAK8O,IAAI4E,EAAI,GAAIC,GACjB3T,KAAK8O,IAAI4E,EAAI,GAAIE,GAEnB,GACE,OACH,QAAcJ,EAAkB,oDAChC,MAAOL,EAAMC,EAAMC,EAAOC,GAASE,EACnC,OAAO,IAAIhB,EAAKW,EAAMC,EAAMC,EAAQF,EAAMG,EAAQF,EACnD,CAEA,+BAAO1U,CAAyB1B,IAC/B,QAAOA,EAAO1J,QAAU,EAAG,gCAC3B,IAAI6f,EAAOnW,EAAO,GACdoW,EAAOpW,EAAO,GACdqW,EAAQF,EACRG,EAAQF,EACZ,IAAK,IAAIxa,EAAI,EAAGA,EAAIoE,EAAO1J,OAAQsF,GAAK,EACvCua,EAAOnT,KAAK2N,IAAIwF,EAAMnW,EAAOpE,IAC7Bya,EAAQrT,KAAK8O,IAAIuE,EAAOrW,EAAOpE,IAC/Bwa,EAAOpT,KAAK2N,IAAIyF,EAAMpW,EAAOpE,EAAI,IACjC0a,EAAQtT,KAAK8O,IAAIwE,EAAOtW,EAAOpE,EAAI,IAEpC,OAAO,IAAI4Z,EAAKW,EAAMC,EAAMC,EAAQF,EAAMG,EAAQF,EACnD,CAEA,gCAAOS,CAA0BpB,EAAkBqB,GAClD,MAAMvY,EAAOuY,EAAYjS,IAAI4Q,GAC7B,OAAO,IAAID,EAAKC,EAAQ3hB,EAAG2hB,EAAQ1hB,EAAGwK,EAAKzK,EAAGyK,EAAKxK,EACpD,CAEA,kBAAOgjB,CAAY5W,GAClB,OAAO,IAAIqV,EAAKrV,EAAKrM,EAAGqM,EAAKpM,EAAGoM,EAAKzC,MAAOyC,EAAKE,OAClD,CAEA,mBAAO2W,CAAaC,GACnB,OAAOA,EAAMR,QAAO,CAACS,EAAMC,IAAQD,EAAKE,MAAMD,IAC/C,CAEA,WAAO,GACN,OAAO,IAAI3B,EAAK,EAAG,EAAG,EAAG,EAC1B,CAEA,YAAI6B,GACH,OAAO,IAAI,KAAQtnB,KAAK0lB,QAAQ3hB,EAAI/D,KAAKwO,KAAKzK,EAAG/D,KAAK0lB,QAAQ1hB,EAC/D,CACA,cAAIujB,GACH,OAAO,IAAI,KAAQvnB,KAAK0lB,QAAQ3hB,EAAG/D,KAAK0lB,QAAQ1hB,EAAIhE,KAAKwO,KAAKxK,EAC/D,CACA,eAAI+iB,GACH,OAAO/mB,KAAK0lB,QAAQ8B,IAAIxnB,KAAKwO,KAC9B,CACA,eAAIuY,CAAYnb,GACf5L,KAAKwO,KAAO5C,EAAMkJ,IAAI9U,KAAK0lB,QAC5B,CACA,UAAI5U,GACH,OAAO9Q,KAAK0lB,QAAQ8B,IAAIxnB,KAAKwO,KAAKiZ,WAAW,IAC9C,CAEA,KAAI1jB,GAAM,OAAO/D,KAAK0lB,QAAQ3hB,CAAG,CACjC,KAAIC,GAAM,OAAOhE,KAAK0lB,QAAQ1hB,CAAG,CACjC,SAAI2J,GAAU,OAAO3N,KAAKwO,KAAKzK,CAAG,CAClC,UAAIuM,GAAW,OAAOtQ,KAAKwO,KAAKxK,CAAG,CAEnC,QAAI4Y,GAAS,OAAO5c,KAAK+D,CAAG,CAC5B,OAAIgZ,GAAQ,OAAO/c,KAAKgE,CAAG,CAC3B,SAAI0jB,GAAU,OAAO1nB,KAAK+D,EAAI/D,KAAK2N,KAAO,CAC1C,UAAIga,GAAW,OAAO3nB,KAAKgE,EAAIhE,KAAKsQ,MAAQ,CAE5C,WAAIsX,GACH,OAAO3U,KAAK8O,IAAI/hB,KAAK2N,MAAO3N,KAAKsQ,OAClC,CAEA,eAAIuX,GACH,OAAO5U,KAAK8O,IACX9O,KAAKuO,IAAIxhB,KAAK4c,MACd3J,KAAKuO,IAAIxhB,KAAK+c,KACd9J,KAAKuO,IAAIxhB,KAAK0nB,OACdzU,KAAKuO,IAAIxhB,KAAK2nB,QAEhB,CAEA,iBAAIG,GACH,MAAO,CAAC9nB,KAAK0lB,QAAS1lB,KAAKsnB,SAAUtnB,KAAK+mB,YAAa/mB,KAAKunB,WAC7D,CAEA,SAAIQ,GACH,MAAO,CACN,CAAC/nB,KAAK0lB,QAAS1lB,KAAKsnB,UACpB,CAACtnB,KAAKsnB,SAAUtnB,KAAK+mB,aACrB,CAAC/mB,KAAK+mB,YAAa/mB,KAAKunB,YACxB,CAACvnB,KAAKunB,WAAYvnB,KAAK0lB,SAEzB,CAEA,OAAAnV,CAAQhO,GACP,OAAOvC,KAAK0lB,QAAQnV,QAAQhO,EAAKmjB,UAAY1lB,KAAKwO,KAAK+B,QAAQhO,EAAKiM,KACrE,CAEA,QAAAwZ,CAASpc,GACR,MAAMmb,EAAc/mB,KAAK+mB,YACzB,OAAQnb,EAAM7H,GAAK/D,KAAK0lB,QAAQ3hB,GAC9B6H,EAAM7H,EAAIgjB,EAAYhjB,GACtB6H,EAAM5H,GAAKhE,KAAK0lB,QAAQ1hB,GACxB4H,EAAM5H,EAAI+iB,EAAY/iB,CACzB,CAEA,YAAAikB,CAAa7X,GACZ,OAAOpQ,KAAKgoB,SAAS5X,EAAKsV,UAAY1lB,KAAKgoB,SAAS5X,EAAK2W,YAC1D,CAEA,cAAAjZ,CAAevL,GACd,QAAIA,EAAKwB,GAAK/D,KAAK+D,EAAI/D,KAAK2N,WAGxBpL,EAAKyB,GAAKhE,KAAKgE,EAAIhE,KAAKsQ,YAGxBtQ,KAAK+D,GAAKxB,EAAKwB,EAAIxB,EAAKoL,UAGxB3N,KAAKgE,GAAKzB,EAAKyB,EAAIzB,EAAK+N,SAI7B,CAEA,KAAA/B,CAAM2Z,GACL,OAAOzC,EAAKjT,mBACXxS,KAAK0lB,QAAQ+B,WAAWS,GACxBloB,KAAKwO,KAAKiZ,WAAWS,GAEvB,CAEA,KAAAb,CAAM9kB,GACL,OAAOkjB,EAAKqB,0BACX9mB,KAAK0lB,QAAQ9E,IAAIre,EAAKmjB,SACtB1lB,KAAK+mB,YAAYhF,IAAIxf,EAAKwkB,aAE5B,CAEA,YAAAoB,CAAa5lB,GACZ,MAAM0H,EAASwb,EAAKqB,0BACnB9mB,KAAK0lB,QAAQ3D,IAAIxf,EAAKmjB,SACtB1lB,KAAK+mB,YAAYnG,IAAIre,EAAKwkB,cAE3B,OAAI9c,EAAOuE,KAAK4Z,WAAa,EACrB,KAEDne,CACR,CAEA,SAAArF,CAAUyjB,GACT,MAAO,CACNA,EAASC,MAAMtoB,KAAK0lB,SACpB2C,EAASC,MAAMtoB,KAAKsnB,UACpBe,EAASC,MAAMtoB,KAAKunB,YACpBc,EAASC,MAAMtoB,KAAK+mB,aAEtB,CAEA,eAAAnU,CAAgByV,GACf,OAA+B,IAA3BA,EAAS/Z,eAAgD,IAAzB+Z,EAAShiB,YAErCof,EAAKjT,mBAAmBxS,KAAK0lB,QAAQ8B,IAAIa,EAAS9jB,aAAcvE,KAAKwO,MAGrEiX,EAAKe,WAAWxmB,KAAK4E,UAAUyjB,GAExC,CAEA,wBAAAE,GACC,MAAMxB,EAAc/mB,KAAK+mB,YAAYyB,OAC/B9C,EAAU1lB,KAAK0lB,QAAQ+C,QACvBja,EAAOuY,EAAYjS,IAAI4Q,GAC7B,OAAOD,EAAKjT,mBAAmBkT,EAASlX,EACzC,CAEA,MAAAoC,CAAOhO,GACN,OAAO6iB,EAAKqB,0BACX9mB,KAAK0lB,QAAQ5Q,IACM,iBAAXlS,EACN,IAAI,KAAQA,EAAQA,GACpB,IAAI,KAAQA,EAAOga,KAAMha,EAAOma,MAElC/c,KAAK+mB,YAAYS,IACE,iBAAX5kB,EACN,IAAI,KAAQA,EAAQA,GACpB,IAAI,KAAQA,EAAO8kB,MAAO9kB,EAAO+kB,SAGrC,CAEA,KAAAe,CAAM9lB,GACL,OAAO5C,KAAK4Q,OACO,iBAAXhO,GACLA,EACD,CACCma,KAAMna,EAAOma,IACb2K,OAAQ9kB,EAAO8kB,MACfC,QAAS/kB,EAAO+kB,OAChB/K,MAAOha,EAAOga,MAGlB,CAEA,WAAA+L,CAAYC,GACX,OAAOnD,EAAKI,kBAAkB7lB,KAAK8Q,OAAQ9Q,KAAKwO,KAAKiZ,WAAWmB,GACjE,CAEA,QAAAC,CAAS9kB,GACR,OAAO,IAAI0hB,EAAK1hB,EAAG/D,KAAKgE,EAAGhE,KAAK2N,MAAO3N,KAAKsQ,OAC7C,CAEA,QAAAwY,CAAS9kB,GACR,OAAO,IAAIyhB,EAAKzlB,KAAK+D,EAAGC,EAAGhE,KAAK2N,MAAO3N,KAAKsQ,OAC7C,CAEA,YAAAyY,CAAapb,GACZ,OAAO,IAAI8X,EAAKzlB,KAAK+D,EAAG/D,KAAKgE,EAAG2J,EAAO3N,KAAKsQ,OAC7C,CAEA,aAAA0Y,CAAc1Y,GACb,OAAO,IAAImV,EAAKzlB,KAAK+D,EAAG/D,KAAKgE,EAAGhE,KAAK2N,MAAO2C,EAC7C,CAEA,QAAAG,GACC,MAAO,QAAQzQ,KAAK+D,MAAM/D,KAAKgE,MAAMhE,KAAK2N,UAAU3N,KAAKsQ,SAC1D,E,uECvRM,SAAS2Y,EAAkBC,GACjC,MAAM,OAAElc,EAAM,IAAExK,IAAQ,QAAkC0mB,EAAUvb,MAAOub,EAAU5Y,QAErF,OADA9N,EAAI2mB,aAAaD,EAAW,EAAG,GACxBlc,CACR,CAEO,SAASoc,EAAkBpc,GAGjC,OADY,QAAQA,EAAOsM,WAAW,OAC3B+P,aAAa,EAAG,EAAGrc,EAAOW,MAAOX,EAAOsD,OACpD,C,mDCZO,SAASgZ,EAASC,GAExB,OADA,QAAiB,IAAVA,GACAtW,KAAKwV,MAAMxV,KAAKuW,SAAWvW,KAAKwV,MAAMc,GAC9C,CAGO,SAASE,EAAsB7I,EAAamB,GAElD,OAAOnB,EAAM0I,EADCvH,EAAMnB,EAAM,EAE3B,C,mDCDO,SAAS8I,EAA6CC,EAAgBzf,GAC5E,OAAO,QALD,SAA6Dyf,EAAgBzf,GACnF,OALM,SAAsDyf,EAAgBzf,GAC5E,OAAOyf,EAAYC,SAAS1f,EAC7B,CAGQ2f,CAAgBF,EAAazf,GAASA,EAAQ,IACtD,CAGgB4f,CAAuBH,EAAazf,GACpD,C,gHCAO,MAAM6f,EACOC,MAAmDC,SAAtE,WAAArqB,CAAmBoqB,EAAmDC,GAAW,GAA9D,KAAAD,MAAAA,EAAmD,KAAAC,SAAAA,CACtE,CAEA,KAAA/pB,GACC,OAAO,IAAI6pB,EAAU/pB,KAAKgqB,MAAM9pB,QAASF,KAAKiqB,SAC/C,CAEA,WAAA3nB,CAAYC,EAA+CC,IAC1D,QAAmBxC,KAAMuC,EAAM,QAASC,IACxC,QAAkBxC,KAAMuC,EAAM,WAAYC,EAC3C,CAEA,QAAAvC,GACCD,KAAKgqB,MAAM/pB,YACX,QAAcD,KAAKiqB,SAAU,WAC9B,EAIM,MAAMC,EACOF,MAAnB,WAAApqB,CAAmBoqB,GAAA,KAAAA,MAAAA,CACnB,CAEA,KAAA9pB,GACC,OAAO,IAAIgqB,EAAOlqB,KAAKgqB,MAAM9pB,QAC9B,CAEA,WAAAoC,CAAYC,EAA4CC,IACvD,QAAmBxC,KAAMuC,EAAM,QAASC,EACzC,CAEA,QAAAvC,GACCD,KAAKgqB,MAAM/pB,UACZ,EAkBM,MAAMkqB,EAEJC,WACAC,QAEA/c,eACAgd,uBACAC,oBANR,WAAA3qB,CACQwqB,EAAwD,GACxDC,EAAkD,GAElD/c,GAAiB,EACjBgd,GAAyB,EACzBC,GAAsB,GALtB,KAAAH,WAAAA,EACA,KAAAC,QAAAA,EAEA,KAAA/c,eAAAA,EACA,KAAAgd,uBAAAA,EACA,KAAAC,oBAAAA,CAGR,CAEA,KAAArqB,GACC,OAAO,IAAIiqB,EACVnqB,KAAKoqB,WAAWrhB,KAAKyhB,GAAcA,EAAUtqB,UAC7CF,KAAKqqB,QAAQthB,KAAKyN,GAAWA,EAAOtW,UACpCF,KAAKsN,eACLtN,KAAKsqB,uBACLtqB,KAAKuqB,oBAEP,CAEA,OAAAE,GACC,OAAkC,IAA3BzqB,KAAKoqB,WAAW7jB,QAAwC,IAAxBvG,KAAKqqB,QAAQ9jB,MACrD,CAEA,MAAAmkB,GACC,OAAO1qB,KAAKoqB,WAAWO,OACrBH,GACAA,EAAUR,MAAMY,WACfJ,EAAUR,MAAMU,SAAWF,EAAUP,UAEzC,CAEA,MAAAY,CAAOC,EAAkBC,EAA6BzlB,GACrD,MAAM8kB,EAAapqB,KAAKoqB,WAClBC,EAAUrqB,KAAKqqB,QAGfW,EAAeX,EAAQY,QAAQzU,GAAWA,EAAOwT,MAAMkB,wBAAuB3kB,OAC9E4kB,EAAkBd,EAAQY,QAAQzU,GAAWA,EAAOwT,MAAMoB,qBAAoB7kB,OAC9E8kB,EAAehB,EAAQ9jB,OAASykB,EAAeG,EAkCrD,GA/B0C,IAAtBf,EAAW7jB,QAE9BwkB,GAAQ,QAAI,gBAAiB,GAAqB,GAAO,GACzDA,GAAQ,QAAI,gBAAiB,GAAqB,GAAM,KAExDA,GAAQ,QAAI,SAAU,GAAqB,GAAM,GACjDA,GAAQ,QAAI,UAAW,GAAqB,GAAO,IACnD,OAAQX,GAAY,CAACI,EAAW3e,KAC3B2e,EAAUP,UACbc,EAAQ,KAAM,IAAK,GAA4B,GAAM,GAEtD,MAAMO,EAAWlB,EAAWve,EAAI,GAC1B5I,OAAuB6F,IAAbwiB,GAA0BA,EAAStB,MAAMuB,oBACnDC,EAAWpB,EAAWve,EAAI,GAC1B4f,OAAwB3iB,IAAb0iB,GAA0BA,EAASxB,MAAM0B,mBACpD1B,EAAQQ,EAAUR,MAClB/gB,EAAO6hB,EACZd,EAAM5pB,YAAYkF,EAAarC,EAASwoB,GACxCzB,EAAMtgB,aAAapE,EAAarC,EAASwoB,GAAU,GAC9CE,EAA2B,IAAf3B,EAAMhpB,KAA6B,EAA6B,EAClF+pB,EAAQ9hB,EAAM0iB,GAAW,GAAM,GAC3B9f,EAAIue,EAAW7jB,OAAS,GAC3BwkB,EAAQ,MAAO,GAA4B,GAAM,EAClD,KAKFA,EAAQ,MAAO,GAA+B,GAAM,GAG7B,IAAnBV,EAAQ9jB,OACXwkB,GAAQ,QAAI,aAAc,GAAsB,GAAM,OAChD,CACN,MAAMa,EAA+B,CAAC,EAAG,GACnCC,EAAgC,CAACb,EAAeK,EAAcF,EAAkBE,GACtFhB,EAAQ1e,SAAQ,CAAC6K,EAAQ3K,KACxB,MAAMyf,EAAWjB,EAAQxe,EAAI,IAAIme,MAC3B/mB,OAAuB6F,IAAbwiB,GAA0BA,EAASC,oBAC7CC,EAAWnB,EAAQxe,EAAI,IAAIme,MAC3ByB,OAAwB3iB,IAAb0iB,GAA0BA,EAASE,mBAC9C1B,EAAQxT,EAAOwT,MACf/gB,EAAO6hB,EACZd,EAAM5pB,YAAYkF,EAAarC,EAASwoB,GACxCzB,EAAMtgB,aAAapE,EAAarC,EAASwoB,GAAU,GAC9CE,EAA2B,IAAf3B,EAAMhpB,KAA6B,EAA6B,EAElF,GADA+pB,EAAQ9hB,EAAM0iB,EAAW3B,EAAMkB,sBAAuBlB,EAAMoB,oBACzC,IAAfpB,EAAMhpB,KAA4B,CACrC,MAAMA,EAAOgpB,EAAMhpB,KAAO,GAC1B,QAAgB,IAATA,GAAuB,IAATA,EAAY,cACjC4qB,EAAW5qB,IAAS,CACrB,MACC4qB,EAAW,IAAM,EACjBA,EAAW,IAAM,EAElB,GAAI/f,EAAI,IAAMwe,EAAQ9jB,OAAQ,CAC7B,MAAMulB,GAAc9B,EAAMkB,uBAAyBlB,EAAMY,YAAcgB,EAAW,GAAKC,EAAY,GAC7FE,GAAiB/B,EAAMoB,oBAAsBpB,EAAMY,YAAcgB,EAAW,GAAKC,EAAY,GACnGd,EAAQ,KAAM,EAAyBe,EAAYC,EACpD,IAEF,CACD,CAEA,uBAAAC,CAAwBC,GAIvB,MAAMC,EAAS,CAACC,EAAsCrgB,KACrD,IAAK,MAAMmW,KAAWkK,EACrBrgB,EAAI0b,IAAIvF,EACT,EAGKmK,EAAqB,CAACD,EAAsCrgB,EAAgBugB,EAAoCzkB,KACrH,MAAMuc,EAA6B,GACnC,IAAK,MAAMlC,KAAWkK,EACjBrgB,EAAIyD,IAAI0S,KACXnW,EAAIsR,OAAO6E,GACXkC,EAAQle,KAAKgc,IAGXkC,EAAQ5d,OAAS,GACpB8lB,EAAIpmB,KAAK,CAAC2B,EAAOuc,GAClB,EAEKmI,EAAqC,IAAI7qB,IAEzC8qB,EAAe,CAAChlB,EAAqCilB,IACnDjlB,EAAQ0jB,QAAQwB,IACtB,MAAMC,EAAWJ,EAAOljB,IAAIqjB,GAC5B,QAAiB3jB,IAAb4jB,EAAwB,CAC3B,IAAK,MAAO9kB,EAAOykB,KAAQG,EAC1B,GAAI5kB,IAAU8kB,EAEb,OADAL,EAAIpmB,KAAKwmB,IACF,EAIT,OADAD,EAAcvmB,KAAK,CAACymB,EAAU,CAACD,MACxB,CACR,CACA,OAAO,CAAI,IAKPE,EAA2E,GAkCjF,OAjCA3sB,KAAKqqB,QAAQ1e,SAAQ,CAAC6K,EAAQ5O,KAC7B,MAAML,EAAUiP,EAAOwT,MAAM3oB,cAAc4qB,GAE3C,GAAI1kB,EAAQhG,UAAW,CACtB,MAAMA,EAAYgG,EAAQhG,UAAU0pB,QAAQwB,IAAYH,EAAO/c,IAAIkd,KACnE,IAAK,MAAOG,EAAGC,EAAcR,KAAQM,EACpCP,EAAmB7qB,EAAWsrB,EAAcR,EAAKzkB,EAEnD,CAEA,MAAM4kB,EAA+C,GAC/CM,EAAkB,IAAIC,IAC5B,GAAIxlB,EAAQylB,QAAS,CACpB,MAAMC,EAAYV,EAAahlB,EAAQylB,QAASR,GAChD,IAAK,MAAOI,EAAGC,EAAcR,KAAQM,EACpCP,EAAmBa,EAAWJ,EAAcR,EAAKzkB,GAElD,IAAK,MAAM6kB,KAAUQ,EACpBX,EAAOxgB,IAAI2gB,EAAQ7kB,EAErB,CACIL,EAAQjG,UACX4qB,EAAOK,EAAahlB,EAAQjG,SAAUkrB,GAAgBM,GAEnDvlB,EAAQhG,WACX2qB,EAAOK,EAAahlB,EAAQhG,UAAWirB,GAAgBM,IAEnDA,EAAKte,KAAO,GAAKge,EAAcjmB,OAAS,IAAMiQ,EAAOwT,MAAMkD,gBAC/DP,EAAmB1mB,KAAK,CAAC2B,EAAOklB,EAAMN,GACvC,IAIMG,EACL1B,QAAQkC,GAA4B,IAAlBA,EAAM,GAAG3e,OAC3BzF,KAAI,EAAEnB,EAAOglB,EAAGJ,KAAmB,CAAC5kB,EAAO4kB,IAC9C,CAEA,MAAAY,CAAO9nB,EAA8B+nB,GACpC,MAAMD,EAAmB,GAErBptB,KAAKoqB,WAAW7jB,OAAS,GAA6B,IAAxBvG,KAAKqqB,QAAQ9jB,QAC9C6mB,EAAOnnB,MACN,QAAI,oDAAsD,SAC1D,QAAI,uCAIN,MAAMqnB,EAAgBhoB,GAAagoB,iBAAmB,KAChDC,GAAgB,QAAK,uCAC3B,IAAK,MAAO3lB,EAAO4iB,KAAcxqB,KAAKoqB,WAAW/a,UAAW,CAC3D,MAAM2a,EAAQQ,EAAUR,MACnBA,EAAMkD,iBAGPlD,EAAMrgB,mBAAmB2jB,IAC5BF,EAAOnnB,MAAK,QAAK,uCAAuCzF,KAAKoH,EAAOoiB,EAAM7pB,MACvE,QAAUotB,EAAc/sB,KAAKwpB,EAAMpgB,sBAAsB0jB,IAAkB,KAG3EtD,EAAMwD,sBAAwBxtB,KAAKytB,iBAAiBztB,KAAKoqB,WAAYxiB,EAAQ,IAChFwlB,EAAOnnB,MAAK,QAAK,sDAAsDzF,KAAKoH,EAAOoiB,EAAM7pB,OAEtF6pB,EAAM0D,uBAAyB1tB,KAAK2tB,gBAAgB3tB,KAAKoqB,WAAYxiB,EAAQ,IAChFwlB,EAAOnnB,MAAK,QAAK,uDAAuDzF,KAAKoH,EAAOoiB,EAAM7pB,OAE5F,CACA,IAAK,MAAOyH,EAAO4O,KAAWxW,KAAKqqB,QAAQhb,UAAW,CACrD,MAAM2a,EAAQxT,EAAOwT,MAChBA,EAAMkD,iBAGPlD,EAAMrgB,mBAAmB2jB,IAC5BF,EAAOnnB,MAAK,QAAK,kCAAkCzF,KAAKoH,EAAOoiB,EAAM7pB,MAClE,QAAUotB,EAAc/sB,KAAKwpB,EAAMpgB,sBAAsB0jB,IAAkB,KAG3EtD,EAAMwD,sBAAwBxtB,KAAKytB,iBAAiBztB,KAAKqqB,QAASziB,EAAQ,IAC7EwlB,EAAOnnB,MAAK,QAAK,mDAAmDzF,KAAKoH,EAAOoiB,EAAM7pB,OAEnF6pB,EAAM0D,uBAAyB1tB,KAAK2tB,gBAAgB3tB,KAAKqqB,QAASziB,EAAQ,IAC7EwlB,EAAOnnB,MAAK,QAAK,oDAAoDzF,KAAKoH,EAAOoiB,EAAM7pB,OAEzF,CAEA,GAAIH,KAAK0qB,SACR,IAAK,MAAO9iB,EAAO4O,KAAWxW,KAAKqqB,QAAQhb,UAAW,CACrD,MAAM2a,EAAQxT,EAAOwT,MAChBA,EAAMkD,iBAGPlD,EAAM4D,oBACTR,EAAOnnB,MAAK,QAAK,kEAAkEzF,KAAKoH,EAAOoiB,EAAM7pB,OAEvG,CAGD,MAAM0tB,EAAmB7tB,KAAKgsB,wBAAwBsB,GAChDQ,EAAsBlmB,IAC3B,MAAM4O,GAAS,QAAQxW,KAAKqqB,QAAQziB,IAC9B0jB,EAAWtrB,KAAKqqB,QAAQziB,EAAQ,GAChC3E,OAAuB6F,IAAbwiB,GAA0BA,EAAStB,MAAMuB,oBACnDC,EAAWxrB,KAAKqqB,QAAQziB,EAAQ,GAChC6jB,OAAwB3iB,IAAb0iB,GAA0BA,EAASxB,MAAM0B,mBAC1D,OAAOlV,EAAOwT,MAAMtgB,aAAapE,EAAarC,EAASwoB,GAAU,EAAM,EAExE,IAAK,MAAO7jB,EAAOykB,KAAQwB,EAC1BT,EAAOnnB,MACN,QAAK,wEAAwEzF,KAAKoH,EAAOkmB,EAAmBlmB,IAC1G,SAAU,QAAK,mEAAmEpH,KAAKoH,GAAS,OAChGykB,EAAItjB,KACL,EAAEnB,EAAOL,KAAa,QAAS,QAAK,0BAA0B/G,KAC7DoH,EACAkmB,EAAmBlmB,GACnBL,EAAQwB,KAAK0jB,GAAWY,EAAWZ,KAAShmB,KAAK,OAC9C,UACHA,KAAK,IACL,SAGJ,OAAO2mB,CACR,CAEA,eAAAO,CAAkEI,EAAYnmB,GAC7E,MAAMiO,EAAOkY,EAAMnmB,GACnB,YAAgBkB,IAAT+M,GAAsBA,EAAKmU,MAAM0B,kBACzC,CAEA,gBAAA+B,CAAmEM,EAAYnmB,GAC9E,MAAMiO,EAAOkY,EAAMnmB,GACnB,YAAgBkB,IAAT+M,GAAsBA,EAAKmU,MAAMuB,mBACzC,CAKA,QAAAtrB,GACC,IAAK,MAAMuqB,KAAaxqB,KAAKoqB,WAC5BI,EAAUvqB,WAEX,IAAK,MAAMuW,KAAUxW,KAAKqqB,QACzB7T,EAAOvW,YAER,QAAcD,KAAKsN,eAAgB,mBACnC,QAActN,KAAKsqB,uBAAwB,2BAC3C,QAActqB,KAAKuqB,oBAAqB,sBACzC,CAOA,WAAAjoB,CAAYC,EAAyCC,IACpD,QAAwBxC,KAAMuC,EAAM,aAAcC,IAClD,QAAwBxC,KAAMuC,EAAM,UAAWC,IAC/C,QAAkBxC,KAAMuC,EAAM,iBAAkBC,IAChD,QAAkBxC,KAAMuC,EAAM,yBAA0BC,IACxD,QAAkBxC,KAAMuC,EAAM,sBAAuBC,EACtD,E,mCCtXM,MAAMwrB,EAAmB,yBAEzB,SAASC,EAAezf,EAAc0f,EAAS,UACrD,MAAO,GAAGA,KAAU1f,OAAUwf,GAC/B,C","sources":["webpack://ch.enlightware.gamecreator/./src/blocks/actions/flip/flip-block.ts","webpack://ch.enlightware.gamecreator/./src/blocks/actions/script/script-action-block.ts","webpack://ch.enlightware.gamecreator/./src/blocks/actions/speed/angular-speed-block.ts","webpack://ch.enlightware.gamecreator/./src/blocks/actions/speed/speed-block.ts","webpack://ch.enlightware.gamecreator/./src/blocks/actions/teleport/teleport-block.ts","webpack://ch.enlightware.gamecreator/./src/blocks/common/animation/animation-common.ts","webpack://ch.enlightware.gamecreator/./src/blocks/common/script/script-block.ts","webpack://ch.enlightware.gamecreator/./src/blocks/conditions/script/script-condition-block.ts","webpack://ch.enlightware.gamecreator/./src/blocks/generic/read-variable/read-variable-block.ts","webpack://ch.enlightware.gamecreator/./src/game/render.ts","webpack://ch.enlightware.gamecreator/./src/imgui/display-actions.ts","webpack://ch.enlightware.gamecreator/./src/imgui/imgui.ts","webpack://ch.enlightware.gamecreator/./src/limits/limits.ts","webpack://ch.enlightware.gamecreator/./src/math/geometry.ts","webpack://ch.enlightware.gamecreator/./src/utils/conversion.ts","webpack://ch.enlightware.gamecreator/./src/utils/random-core.ts","webpack://ch.enlightware.gamecreator/./src/utils/union-types.ts","webpack://ch.enlightware.gamecreator/./src/vpl/row.ts","webpack://ch.enlightware.gamecreator/./src/vpl/vpl-typography.ts"],"sourcesContent":["/**\n * action: flip an object on its x axis or its y axis\n * @module block-flip\n * @preferred\n */\n/** comment to work-around limitation of typedoc module plugin */\n\n// Copyright 2018-2024 Enlightware GmbH, Switzerland\n\nimport { CandliBlock } from 'game/game-block-definition';\nimport * as flatbuffers from 'flatbuffers';\nimport * as CandliFB from 'flatbuffers/all';\nimport { assertBoolean } from 'utils/assert';\nimport { BlockKind } from 'vpl/block';\nimport { qsT, qsTr } from 'translator/translator';\nimport { Nothing, SpacedAnd } from 'translator/common-texts';\n\nexport const FlipText = qsT('flip');\nexport const OrientText = qsT('orient');\n\n/** Flip a sprite */\nexport class FlipBlock extends CandliBlock {\n\t/** whether to flip the X axis (Y axis stays fixed) */\n\tflipX: boolean;\n\t/** whether to flip the Y axis (X axis stays fixed) */\n\tflipY: boolean;\n\t/* relative: whether the flip is relative to the current flipped state (flip is always relative to the rotation) */\n\trelative: boolean;\n\n\tconstructor(flipX: boolean, flipY: boolean, relative: boolean, lockState?: CandliBlock);\n\tconstructor(fbFlip: CandliFB.Flip);\n\tconstructor(\n\t\tflipXOrFbFlip: boolean | CandliFB.Flip,\n\t\tflipY?: boolean,\n\t\trelative?: boolean,\n\t\tlockState?: CandliBlock\n\t) {\n\t\tsuper('Flip', lockState);\n\t\tif (flipXOrFbFlip instanceof CandliFB.Flip) {\n\t\t\tthis.flipX = flipXOrFbFlip.flipX();\n\t\t\tthis.flipY = flipXOrFbFlip.flipY();\n\t\t\tthis.relative = flipXOrFbFlip.relative();\n\t\t} else {\n\t\t\tthis.flipX = flipXOrFbFlip;\n\t\t\t// FIXME: the \"!\" are to work around Typescript bug 38315, see\n\t\t\t// https://github.com/microsoft/TypeScript/issues/38315\n\t\t\tthis.flipY = flipY!;\n\t\t\tthis.relative = relative!;\n\t\t}\n\t\tthis.validate();\n\t}\n\n\tclone(): FlipBlock {\n\t\treturn new FlipBlock(this.flipX, this.flipY, this.relative, this);\n\t}\n\n\tget name() {\n\t\treturn qsT('Flip or orient');\n\t}\n\n\tsummaryText() {\n\t\treturn this.relative ? FlipText : OrientText;\n\t}\n\n\tdetailedTextIfConfigured() {\n\t\tif (this.relative) {\n\t\t\tconst horizontally = this.flipX ? qsT('horizontally') : '';\n\t\t\tconst vertically = this.flipY ? qsT('vertically') : '';\n\t\t\tlet args;\n\t\t\tif (horizontally && vertically) {\n\t\t\t\targs = horizontally + SpacedAnd + vertically;\n\t\t\t} else if (horizontally) {\n\t\t\t\targs = horizontally;\n\t\t\t} else if (vertically) {\n\t\t\t\targs = vertically;\n\t\t\t} else {\n\t\t\t\targs = Nothing;\n\t\t\t}\n\t\t\treturn qsTr('flip %1').args(args);\n\t\t} else {\n\t\t\tconst horizontal = this.flipX ? qsT('horizontal') : '';\n\t\t\tconst vertical = this.flipY ? qsT('vertical') : '';\n\t\t\tlet args;\n\t\t\tif (horizontal && vertical) {\n\t\t\t\targs = horizontal + SpacedAnd + vertical;\n\t\t\t} else if (horizontal) {\n\t\t\t\targs = horizontal;\n\t\t\t} else if (vertical) {\n\t\t\t\targs = vertical;\n\t\t\t} else {\n\t\t\t\treturn qsT('reset orientation');\n\t\t\t}\n\t\t\treturn qsTr('set inverted %1 orientation').args(args);\n\t\t}\n\t}\n\n\tserialise(builder: flatbuffers.Builder) {\n\t\treturn CandliFB.Flip.createFlip(builder,\n\t\t\tthis.flipX,\n\t\t\tthis.flipY,\n\t\t\tthis.relative\n\t\t);\n\t}\n\n\tget fbActionType() {\n\t\treturn CandliFB.AnyAction.Flip;\n\t}\n\n\tget kind() {\n\t\treturn BlockKind.InstantaneousAction;\n\t}\n\n\tgetAbsoluteFlip(oldFlipX: boolean, oldFlipY: boolean): [boolean, boolean] {\n\t\tif (this.relative) {\n\t\t\tif (this.flipX) {\n\t\t\t\treturn [!oldFlipX, oldFlipY];\n\t\t\t} else {\n\t\t\t\treturn [oldFlipX, !oldFlipY];\n\t\t\t}\n\t\t} else {\n\t\t\treturn [this.flipX, this.flipY];\n\t\t}\n\t}\n\n\tvalidate() {\n\t\tsuper.validate();\n\t\tassertBoolean(this.flipX, 'flipX');\n\t\tassertBoolean(this.flipY, 'flipY');\n\t\tassertBoolean(this.relative, 'relative');\n\t}\n\n\tgetMiniatureKey() {\n\t\tconst x = this.flipX ? 1 : 0;\n\t\tconst y = this.flipY ? 1 : 0;\n\t\tconst r = this.relative ? 1 : 0;\n\t\treturn `flip ${x}${y}${r}`;\n\t}\n\n\tactionEffects() {\n\t\tif (this.relative) {\n\t\t\treturn {\n\t\t\t\tmodifies: ['ORIENTATION'] as const\n\t\t\t}\n\t\t} else {\n\t\t\treturn {\n\t\t\t\toverrides: ['ORIENTATION'] as const\n\t\t\t}\n\t\t}\n\t}\n}\n","/**\n * action: execute a script in an action block\n * @module block-action-script\n * @preferred\n */\n/** comment to work-around limitation of typedoc module plugin */\n\n// Copyright 2018-2024 Enlightware GmbH, Switzerland\n\nimport { CandliBlock } from 'game/game-block-definition';\nimport * as flatbuffers from 'flatbuffers';\nimport * as CandliFB from 'flatbuffers/all';\nimport { BlockKind } from 'vpl/block';\nimport { qsT } from 'translator/translator';\nimport { ScriptAbstractBlock } from 'blocks/common/script/script-block';\nimport { exec_fn_unit_unit as execFnUnitUnit, exec_fn_int_unit as execFnIntUnit, exec_fn_unit_int as execFnUnitInt, exec_fn_int_int as execFnIntInt, ScriptCtx } from 'app-core-web/pkg';\nimport { assertMemberEqual } from 'utils/assert';\n\n\nexport function setupCompiler(scriptCtx: ScriptCtx) {\n\treturn scriptCtx.action_block_script_compiler();\n}\n\nconst execFns = new Map([\n\t['() → ()', [execFnUnitUnit, false, false]],\n\t['(int) → ()', [execFnIntUnit, true, false]],\n\t['() → int', [execFnUnitInt, false, true]],\n\t['(int) → int', [execFnIntInt, true, true]],\n] as const);\n\nexport function validSignatures() {\n\treturn [...execFns.keys()];\n}\n\nfunction getCode(codeOrFb: string | CandliFB.ScriptAction) {\n\tif (typeof codeOrFb === 'string') {\n\t\treturn codeOrFb;\n\t} else {\n\t\treturn codeOrFb.code() ?? '';\n\t}\n}\n\nexport class ScriptActionBlock extends ScriptAbstractBlock {\n\tpublic continuous: boolean;\n\n\tconstructor(code: string, scriptCtx: ScriptCtx, continuous: boolean, lockState?: CandliBlock);\n\tconstructor(fb: CandliFB.ScriptAction, scriptCtx: ScriptCtx, );\n\tconstructor(codeOrFb: string | CandliFB.ScriptAction, scriptCtx: ScriptCtx, continuous?: boolean, lockState?: CandliBlock) {\n\t\tsuper(getCode(codeOrFb), scriptCtx, execFns, 'ScriptAction', lockState);\n\t\tif (typeof codeOrFb === 'string') {\n\t\t\tthis.continuous = continuous!;\n\t\t} else {\n\t\t\tthis.continuous = codeOrFb.continuous();\n\t\t}\n\t}\n\n\trebuildCompiler() {\n\t\treturn setupCompiler(this.scriptCtx);\n\t}\n\n\tclone(): ScriptActionBlock {\n\t\treturn new ScriptActionBlock(this.code, this.scriptCtx, this.continuous, this);\n\t}\n\n\tget name() {\n\t\treturn qsT('Action script');\n\t}\n\n\tserialise(builder: flatbuffers.Builder) {\n\t\treturn CandliFB.ScriptAction.createScriptAction(builder, builder.createString(this.code), this.continuous);\n\t}\n\n\tget fbActionType() {\n\t\treturn CandliFB.AnyAction.ScriptAction;\n\t}\n\n\tget kind() {\n\t\tif (this.continuous) {\n\t\t\treturn BlockKind.ContinuousAction;\n\t\t} else {\n\t\t\treturn BlockKind.InstantaneousAction;\n\t\t}\n\t}\n\n\tget premium() {\n\t\treturn false;\n\t}\n\n\tgetMiniatureKey() {\n\t\treturn `script-action ${this.code} ${this.continuous}`;\n\t}\n\n\tassertEqual(that: ScriptActionBlock, ctx: string) {\n\t\tassertMemberEqual(this, that, 'code', ctx);\n\t\tassertMemberEqual(this, that, 'continuous', ctx);\n\t}\n}","/**\n * @module block-speed\n */\n/** comment to work-around limitation of typedoc module plugin */\n\n// Copyright 2018-2024 Enlightware GmbH, Switzerland\n\nimport { CandliBlock } from 'game/game-block-definition';\nimport * as flatbuffers from 'flatbuffers';\nimport * as CandliFB from 'flatbuffers/all';\nimport { FloatToFixed88, Fixed88ToFloat } from 'flatbuffers/flatbuffers-cast';\nimport { assertIntegerRange, assertNumber } from 'utils/assert';\nimport { BlockKind, ValuePortPresence } from 'vpl/block';\nimport { qsT, qsTr } from 'translator/translator';\n\nexport const enum AngularSpeedBlockMode {\n\tAngularVelocity = 0,\n\tTorque,\n}\n\nexport const AddAngularVelocityText = qsT('Add angular velocity');\nexport const AddTorqueText = qsT('Add torque');\n\nexport class AngularSpeedBlock extends CandliBlock {\n\tamount: number;\n\tmode: AngularSpeedBlockMode;\n\n\tconstructor(intensity: number, mode?: AngularSpeedBlockMode, lockState?: CandliBlock);\n\tconstructor(fbAction: CandliFB.AddAngularVelocity | CandliFB.AddAngularAcceleration);\n\tconstructor(\n\t\tintensityOrFbAction: number | CandliFB.AddAngularVelocity | CandliFB.AddAngularAcceleration,\n\t\tmode = AngularSpeedBlockMode.AngularVelocity,\n\t\tlockState?: CandliBlock\n\t) {\n\t\tif (intensityOrFbAction instanceof CandliFB.AddAngularVelocity) {\n\t\t\tsuper('AddAngularVelocity', lockState);\n\t\t\tthis.amount = intensityOrFbAction.amount() * Fixed88ToFloat;\n\t\t\tthis.mode = AngularSpeedBlockMode.AngularVelocity;\n\t\t} else if (intensityOrFbAction instanceof CandliFB.AddAngularAcceleration) {\n\t\t\tsuper('AddAngularAcceleration', lockState);\n\t\t\tthis.amount = intensityOrFbAction.amount() * Fixed88ToFloat;\n\t\t\tthis.mode = AngularSpeedBlockMode.Torque;\n\t\t} else {\n\t\t\tsuper(mode === AngularSpeedBlockMode.AngularVelocity ? 'AddAngularVelocity' : 'AddAngularAcceleration', lockState);\n\t\t\tthis.amount = intensityOrFbAction;\n\t\t\tthis.mode = mode;\n\t\t}\n\t\tthis.validate();\n\t}\n\n\tclone(): AngularSpeedBlock {\n\t\treturn new AngularSpeedBlock(this.amount, this.mode, this);\n\t}\n\n\tget name() {\n\t\tif (this.mode === AngularSpeedBlockMode.AngularVelocity) {\n\t\t\treturn AddAngularVelocityText;\n\t\t} else {\n\t\t\treturn AddTorqueText;\n\t\t}\n\t}\n\n\tget inputValuePortPresence() {\n\t\treturn ValuePortPresence.Optional;\n\t}\n\n\tsummaryText() {\n\t\tif (this.mode === AngularSpeedBlockMode.AngularVelocity) {\n\t\t\treturn qsT('+ang. vel.');\n\t\t} else {\n\t\t\treturn qsT('+torque');\n\t\t}\n\t}\n\n\tdetailedTextIfConfigured(_userContext: unknown, valueIn: boolean) {\n\t\tconst modeText = this.mode === AngularSpeedBlockMode.AngularVelocity ? qsT('an angular velocity') : qsT('a torque');\n\t\tconst dirText = this.amount < 0 ? qsT('to the left') : qsT('to the right');\n\t\tif (valueIn) {\n\t\t\treturn qsTr('add %1, multiplied by the value, %2').args(modeText, dirText);\n\t\t} else {\n\t\t\treturn qsTr('add %1 %2').args(modeText, dirText);\n\t\t}\n\t}\n\n\tserialise(builder: flatbuffers.Builder) {\n\t\treturn (this.mode === AngularSpeedBlockMode.AngularVelocity ?\n\t\t\t// eslint-disable-next-line @typescript-eslint/unbound-method\n\t\t\tCandliFB.AddAngularVelocity.createAddAngularVelocity :\n\t\t\t// eslint-disable-next-line @typescript-eslint/unbound-method\n\t\t\tCandliFB.AddAngularAcceleration.createAddAngularAcceleration\n\t\t)(builder, this.amount * FloatToFixed88);\n\t}\n\n\tget fbActionType() {\n\t\tif (this.mode === AngularSpeedBlockMode.AngularVelocity) {\n\t\t\treturn CandliFB.AnyAction.AddAngularVelocity;\n\t\t} else {\n\t\t\treturn CandliFB.AnyAction.AddAngularAcceleration;\n\t\t}\n\t}\n\n\tget kind() {\n\t\treturn this.mode === AngularSpeedBlockMode.AngularVelocity ?\n\t\t\tBlockKind.InstantaneousAction :\n\t\t\tBlockKind.ContinuousAction\n\t\t;\n\t}\n\n\tvalidate() {\n\t\tsuper.validate();\n\t\tassertNumber(this.amount, 'amount');\n\t\tassertIntegerRange(this.mode, AngularSpeedBlockMode.AngularVelocity, AngularSpeedBlockMode.Torque, 'mode');\n\t}\n\n\tgetMiniatureKey(_userContext: unknown, valueIn: boolean) {\n\t\tif (valueIn) {\n\t\t\treturn `angular-speed value ${this.amount} ${this.mode}`;\n\t\t} else {\n\t\t\treturn `angular-speed ${this.amount} ${this.mode}`;\n\t\t}\n\t}\n\n\tactionEffects() {\n\t\tif (this.mode === AngularSpeedBlockMode.AngularVelocity) {\n\t\t\treturn {\n\t\t\t\tmodifies: ['ANGULAR_VELOCITY'] as const\n\t\t\t}\n\t\t} else {\n\t\t\treturn {};\n\t\t}\n\t}\n}","/**\n * action: apply force or set speed, apply impulse, or break or stop\n * @module block-speed\n * @preferred\n */\n/** comment to work-around limitation of typedoc module plugin */\n\n// Copyright 2018-2024 Enlightware GmbH, Switzerland\n\nimport { CandliBlock } from 'game/game-block-definition';\nimport * as flatbuffers from 'flatbuffers';\nimport * as CandliFB from 'flatbuffers/all';\nimport { Vector2, assertVector2 } from 'math/linalg';\nimport { assertIntegerRange, assertBoolean } from 'utils/assert';\nimport { Fixed88ToFloat, FloatToFixed88 } from 'flatbuffers/flatbuffers-cast';\nimport { BlockKind, ValuePortPresence } from 'vpl/block';\nimport { qsT, qsTr } from 'translator/translator';\nimport { vectorQualitativeDescription } from 'math/math-to-string';\n\n\nexport const enum SpeedBlockMode {\n\tVelocity = 0,\n\tForce,\n}\n\nexport const AddVelocityText = qsT('Add velocity');\nexport const AddForceText = qsT('Add force');\n\nexport class SpeedBlock extends CandliBlock {\n\trelative: boolean;\n\tvector: Vector2;\n\tmode: SpeedBlockMode;\n\tcompatFixedMagnitude: boolean;\n\n\tconstructor(vector: Vector2, mode?: SpeedBlockMode, relative?: boolean, lockState?: CandliBlock);\n\tconstructor(fbAction: CandliFB.AddVelocity | CandliFB.AddAcceleration, fromVersion: number);\n\tconstructor(\n\t\tvectorOrFbAction: Vector2 | CandliFB.AddVelocity | CandliFB.AddAcceleration,\n\t\tmodeOrFromVersion: SpeedBlockMode | number = SpeedBlockMode.Velocity,\n\t\trelative = false,\n\t\tlockState?: CandliBlock\n\t) {\n\t\tif (vectorOrFbAction instanceof CandliFB.AddVelocity) {\n\t\t\tsuper('AddVelocity', lockState);\n\t\t\tthis.relative = vectorOrFbAction.relative();\n\t\t\tconst x = vectorOrFbAction.x() * Fixed88ToFloat;\n\t\t\tconst y = vectorOrFbAction.y() * Fixed88ToFloat;\n\t\t\tthis.vector = new Vector2(x, y);\n\t\t\tif (modeOrFromVersion < 4) { // see version history in game-core.ts\n\t\t\t\tthis.compatFixedMagnitude = true;\n\t\t\t} else {\n\t\t\t\tthis.compatFixedMagnitude = vectorOrFbAction.compatFixedMagnitude();\n\t\t\t}\n\t\t\tthis.mode = SpeedBlockMode.Velocity;\n\t\t} else if (vectorOrFbAction instanceof CandliFB.AddAcceleration) {\n\t\t\tsuper('AddAcceleration', lockState);\n\t\t\tthis.relative = vectorOrFbAction.relative();\n\t\t\tconst x = vectorOrFbAction.x() * Fixed88ToFloat;\n\t\t\tconst y = vectorOrFbAction.y() * Fixed88ToFloat;\n\t\t\tthis.vector = new Vector2(x, y);\n\t\t\tif (modeOrFromVersion < 4) { // see version history in game-core.ts\n\t\t\t\tthis.compatFixedMagnitude = true;\n\t\t\t} else {\n\t\t\t\tthis.compatFixedMagnitude = vectorOrFbAction.compatFixedMagnitude();\n\t\t\t}\n\t\t\tthis.mode = SpeedBlockMode.Force;\n\t\t} else {\n\t\t\tsuper(modeOrFromVersion as SpeedBlockMode === SpeedBlockMode.Velocity ? 'AddVelocity' : 'AddAcceleration', lockState);\n\t\t\tthis.relative = relative;\n\t\t\tthis.vector = vectorOrFbAction;\n\t\t\tthis.compatFixedMagnitude = false;\n\t\t\tthis.mode = modeOrFromVersion;\n\t\t}\n\t\tthis.validate();\n\t}\n\n\tclone(): SpeedBlock {\n\t\treturn new SpeedBlock(this.vector.clone(), this.mode, this.relative, this);\n\t}\n\n\tget name() {\n\t\treturn this.mode === SpeedBlockMode.Velocity ? AddVelocityText : AddForceText;\n\t}\n\n\tget inputValuePortPresence() {\n\t\treturn ValuePortPresence.Optional;\n\t}\n\n\tsummaryText() {\n\t\tif (this.mode === SpeedBlockMode.Velocity) {\n\t\t\treturn qsT('+velocity');\n\t\t} else {\n\t\t\treturn qsT('+force');\n\t\t}\n\t}\n\n\tdetailedTextIfConfigured(_userContext: unknown, valueIn: boolean) {\n\t\tconst modeText = this.mode === SpeedBlockMode.Velocity ? qsT('velocity') : qsT('force');\n\t\tconst relativeText = this.relative ? ' ' + qsT(\"relative to this object's orientation\") : '';\n\t\tconst dirText = vectorQualitativeDescription(this.vector, '');\n\t\tif (valueIn) {\n\t\t\treturn qsTr('add a %1, multiplied by the value, %2%3').args(modeText, dirText, relativeText);\n\t\t} else {\n\t\t\treturn qsTr('add a %1 %2%3').args(modeText, dirText, relativeText);\n\t\t}\n\t}\n\n\tserialise(builder: flatbuffers.Builder) {\n\t\treturn (this.mode === SpeedBlockMode.Velocity ?\n\t\t\t// eslint-disable-next-line @typescript-eslint/unbound-method\n\t\t\tCandliFB.AddVelocity.createAddVelocity :\n\t\t\t// eslint-disable-next-line @typescript-eslint/unbound-method\n\t\t\tCandliFB.AddAcceleration.createAddAcceleration\n\t\t)(builder, this.vector.x * FloatToFixed88, this.vector.y * FloatToFixed88, this.relative, this.compatFixedMagnitude);\n\t}\n\n\tget fbActionType() {\n\t\tif (this.mode === SpeedBlockMode.Velocity) {\n\t\t\treturn CandliFB.AnyAction.AddVelocity;\n\t\t} else {\n\t\t\treturn CandliFB.AnyAction.AddAcceleration;\n\t\t}\n\t}\n\n\tget kind() {\n\t\treturn this.mode === SpeedBlockMode.Velocity ?\n\t\t\tBlockKind.InstantaneousAction :\n\t\t\tBlockKind.ContinuousAction\n\t\t;\n\t}\n\n\tvalidate() {\n\t\tsuper.validate();\n\t\tassertVector2(this.vector, 'vector');\n\t\tassertIntegerRange(this.mode, SpeedBlockMode.Velocity, SpeedBlockMode.Force, 'mode');\n\t\tassertBoolean(this.relative, 'relative');\n\t\tassertBoolean(this.compatFixedMagnitude, 'compatFixedMagnitude');\n\t}\n\n\tgetMiniatureKey(_userContext: unknown, valueIn: boolean) {\n\t\tif (valueIn) {\n\t\t\treturn `speed value ${this.vector.x} ${this.vector.y} ${this.mode} ${this.relative}`;\n\t\t} else {\n\t\t\treturn `speed ${this.vector.x} ${this.vector.y} ${this.mode} ${this.relative}`;\n\t\t}\n\t}\n\n\tactionEffects() {\n\t\tif (this.mode === SpeedBlockMode.Velocity) {\n\t\t\treturn {\n\t\t\t\tmodifies: ['LINEAR_VELOCITY'] as const\n\t\t\t}\n\t\t} else {\n\t\t\treturn {};\n\t\t}\n\t}\n}\n","/**\n * action: teleport instance or camera\n * @module block-teleport\n * @preferred\n */\n/** comment to work-around limitation of typedoc module plugin */\n\n// Copyright 2018-2024 Enlightware GmbH, Switzerland\n\nimport { CandliBlock, ObjectTypeIdMap } from 'game/game-block-definition';\nimport * as flatbuffers from 'flatbuffers';\nimport * as CandliFB from 'flatbuffers/all';\nimport { SimilarityTransform, assertSimilarityTransform } from 'math/linalg';\nimport { assertClassEqual, assertBoolean, assertMemberEqual, assertTypeOrNull, assertIntegerRange } from 'utils/assert';\nimport { fromFbObjectTypeRefOptional, fromFbSimilarityTransform2, toFbObjectTypeRef, toFbSimilarityTransform2 } from 'flatbuffers/flatbuffers-cast';\nimport { BlockKind, ValuePortPresence } from 'vpl/block';\nimport { defined, downcast } from 'utils/types';\nimport { assertMemberObjectTypeOptEqual, assertMemberSimilarityTransformEqual } from 'utils/assert-specific';\nimport { qsT, qsTr } from 'translator/translator';\nimport { ObjectType } from 'game/game-core';\nimport { isBitSet } from 'utils/flags';\nimport { SimilarityTransformComponents } from 'imgui/similarity-transform-fitter';\nimport { CandliEffects, EditedObjectContext } from 'level/behaviour-editor-interface';\nimport { Nothing, SpacedAnd } from 'translator/common-texts';\nimport { normalizeDegreesAround0 } from 'math/helpers';\n\nconst enum TeleportTransformComponentsBits {\n\tTranslation = 0,\n\tRotation = 1,\n\tScaling = 2\n}\n\nexport const DefaultTransformPartsObject = {\n\ttranslation: true,\n\trotation: false,\n\tscaling: false\n} as const;\n\nexport const DefaultTransformPartsCamera = {\n\ttranslation: true,\n\trotation: false,\n\tscaling: true\n} as const;\n\nexport class TeleportBlock extends CandliBlock {\n\ttransform: SimilarityTransform;\n\ttransformComponentsBits!: number; // bit-field, see TeleportTransformParts\n\tmoveCamera: boolean;\n\tbeacon: ObjectType | null;\n\n\tconstructor(moveCamera: boolean, transform: SimilarityTransform, target: ObjectType | null, transformComponents: SimilarityTransformComponents, lockState?: CandliBlock);\n\tconstructor(fbTeleport: CandliFB.Teleport, objectTypes: ObjectType[]);\n\tconstructor(\n\t\tmoveCameraOrFbTeleport: boolean | CandliFB.Teleport,\n\t\ttransformOrObjectTypes: SimilarityTransform | ObjectType[],\n\t\ttarget?: ObjectType | null,\n\t\ttransformComponents?: SimilarityTransformComponents,\n\t\tlockState?: CandliBlock\n\t) {\n\t\tsuper('Teleport', lockState);\n\t\tif (moveCameraOrFbTeleport instanceof CandliFB.Teleport) {\n\t\t\tthis.transform = fromFbSimilarityTransform2(moveCameraOrFbTeleport.toBeaconTransform());\n\t\t\tthis.moveCamera = moveCameraOrFbTeleport.moveCamera();\n\t\t\tthis.beacon = fromFbObjectTypeRefOptional(moveCameraOrFbTeleport.beacon(), transformOrObjectTypes as ObjectType[]);\n\t\t\tthis.transformComponentsBits = moveCameraOrFbTeleport.transformParts();\n\t\t\tif (this.transformComponentsBits === 0xff) {\n\t\t\t\t// special uninitialized value, initialize now\n\t\t\t\tthis.transformComponents = this.moveCamera ? DefaultTransformPartsCamera : DefaultTransformPartsObject;\n\t\t\t}\n\t\t} else {\n\t\t\tthis.transform = transformOrObjectTypes as SimilarityTransform;\n\t\t\tthis.moveCamera = moveCameraOrFbTeleport;\n\t\t\tthis.beacon = target!;\n\t\t\tthis.transformComponents = transformComponents!;\n\t\t}\n\t\tthis.validate();\n\t}\n\n\tclone(): TeleportBlock {\n\t\treturn new TeleportBlock(this.moveCamera, this.transform.clone(), this.beacon, this.transformComponents, this);\n\t}\n\n\tget name() {\n\t\treturn qsT('Teleport');\n\t}\n\n\tget inputValuePortPresence() {\n\t\treturn ValuePortPresence.Optional;\n\t}\n\n\tsummaryText() {\n\t\treturn qsT('teleport');\n\t}\n\n\tdetailedTextIfConfigured(userContext: EditedObjectContext | null, valueIn: boolean) {\n\t\tconst self = this.moveCamera ? qsT('camera') : this.thisObject(userContext);\n\t\tconst game = defined(userContext?.game);\n\t\tlet target;\n\t\tif (this.beacon) {\n\t\t\ttarget = qsTr('closest %1').args(this.beacon.objectOfType(game));\n\t\t} else {\n\t\t\ttarget = qsT('the world');\n\t\t}\n\t\tconst dx = this.transform.translationX;\n\t\tconst dy = -this.transform.translationY;\n\t\tconst trTexts = [];\n\t\tif (this.doRotation) {\n\t\t\ttrTexts.push(qsTr('set orientation angle to %1°').args(normalizeDegreesAround0(-this.transform.rotationDegrees).toFixed()));\n\t\t}\n\t\tif (this.doScaling) {\n\t\t\ttrTexts.push(qsTr('set scale to %1×').args(this.transform.scaleFactor.toFixed(1)));\n\t\t}\n\t\tif (this.doTranslation) {\n\t\t\ttrTexts.push(qsTr('set position to (%1, %2)').args(dx.toFixed(1), dy.toFixed(1)));\n\t\t}\n\t\tif (trTexts.length === 0) {\n\t\t\ttrTexts.push(Nothing);\n\t\t}\n\t\tconst what = trTexts.join(SpacedAnd);\n\t\tif (valueIn) {\n\t\t\treturn qsTr('teleport %1 relative to %2: %3 all multiplied by the value').args(self, target, what);\n\t\t} else {\n\t\t\treturn qsTr('teleport %1 relative to %2: %3').args(self, target, what);\n\t\t}\n\t}\n\n\tserialise(builder: flatbuffers.Builder, objectTypes: ObjectTypeIdMap) {\n\t\tCandliFB.Teleport.startTeleport(builder);\n\t\tCandliFB.Teleport.addToBeaconTransform(builder,\n\t\t\ttoFbSimilarityTransform2(builder, this.transform)\n\t\t);\n\t\tCandliFB.Teleport.addBeacon(builder, toFbObjectTypeRef(this.beacon, objectTypes));\n\t\tCandliFB.Teleport.addMoveCamera(builder, this.moveCamera);\n\t\tCandliFB.Teleport.addTransformParts(builder, this.transformComponentsBits);\n\t\treturn CandliFB.Teleport.endTeleport(builder);\n\t}\n\n\tget fbActionType() {\n\t\treturn CandliFB.AnyAction.Teleport;\n\t}\n\n\tget kind() {\n\t\treturn BlockKind.InstantaneousAction;\n\t}\n\n\tvalidate() {\n\t\tsuper.validate();\n\t\tassertSimilarityTransform(this.transform, 'transform');\n\t\tassertBoolean(this.moveCamera, 'moveCamera');\n\t\tassertTypeOrNull(ObjectType, this.beacon, 'beacon');\n\t\tassertIntegerRange(this.transformComponentsBits, 0, 0x7, 'transformComponentsBits');\n\t}\n\n\tassertEqual(_that: CandliBlock, ctx: string) {\n\t\tassertClassEqual(this as CandliBlock, _that, ctx);\n\t\tconst that = downcast(TeleportBlock, _that);\n\t\tassertMemberSimilarityTransformEqual(this, that, 'transform', ctx);\n\t\tassertMemberEqual(this, that, 'moveCamera', ctx);\n\t\tassertMemberObjectTypeOptEqual(this, that, 'beacon', ctx);\n\t\tassertMemberEqual(this, that, 'transformComponentsBits', ctx);\n\t}\n\n\treleaseReferencesToObjectType(objectType: ObjectType) {\n\t\tif (this.beacon === objectType) {\n\t\t\tthis.beacon = null;\n\t\t}\n\t}\n\n\tgetMiniatureKey() {\n\t\tconst beaconText = this.beacon?.id ?? null;\n\t\treturn `teleport ${this.transform} ${this.moveCamera} ${beaconText} ${this.transformComponentsBits}`;\n\t}\n\n\tactionEffects(objectType: ObjectType | null) {\n\t\tif (this.beacon && this.beacon !== objectType) {\n\t\t\t// if we have a beacon other than ourselves, we are not sure that this action will have an effect\n\t\t\treturn {};\n\t\t}\n\t\tif (this.moveCamera) {\n\t\t\tif (this.beacon) {\n\t\t\t\t// move camera to beacon\n\t\t\t\treturn {\n\t\t\t\t\tmodifies: ['CAMERA'] as const\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// set camera in the world\n\t\t\t\treturn {\n\t\t\t\t\toverrides: ['CAMERA'] as const\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tconst effects: (keyof CandliEffects)[] = [];\n\t\t\tif (this.doTranslation) {\n\t\t\t\teffects.push('POSITION');\n\t\t\t}\n\t\t\tif (this.doRotation) {\n\t\t\t\teffects.push('ANGLE');\n\t\t\t}\n\t\t\tif (this.doScaling) {\n\t\t\t\teffects.push('SCALING');\n\t\t\t}\n\t\t\tif (effects.length === 0) {\n\t\t\t\treturn {};\n\t\t\t}\n\t\t\tif (this.beacon) {\n\t\t\t\t// teleport object to beacon\n\t\t\t\treturn {\n\t\t\t\t\tmodifies: effects\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// teleport object to the world\n\t\t\t\treturn {\n\t\t\t\t\toverrides: effects\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t}\n\n\tget doTranslation() {\n\t\treturn isBitSet(this.transformComponentsBits, TeleportTransformComponentsBits.Translation);\n\t}\n\tget doRotation() {\n\t\treturn isBitSet(this.transformComponentsBits, TeleportTransformComponentsBits.Rotation);\n\t}\n\tget doScaling() {\n\t\treturn isBitSet(this.transformComponentsBits, TeleportTransformComponentsBits.Scaling);\n\t}\n\tget transformComponents() {\n\t\treturn {\n\t\t\ttranslation: this.doTranslation,\n\t\t\trotation: this.doRotation,\n\t\t\tscaling: this.doScaling\n\t\t};\n\t}\n\tset transformComponents(components: SimilarityTransformComponents) {\n\t\tlet transformComponentsBits = 0;\n\t\ttransformComponentsBits |= components.translation ? (1 << TeleportTransformComponentsBits.Translation) : 0;\n\t\ttransformComponentsBits |= components.rotation ? (1 << TeleportTransformComponentsBits.Rotation) : 0;\n\t\ttransformComponentsBits |= components.scaling ? (1 << TeleportTransformComponentsBits.Scaling) : 0;\n\t\tthis.transformComponentsBits = transformComponentsBits;\n\t}\n}\n\n\n","/**\n * common code to all animation blocks\n * @module block-animation-common\n * @preferred\n */\n/** comment to work-around limitation of typedoc module plugin */\n\n// Copyright 2018-2024 Enlightware GmbH, Switzerland\n\nimport { ObjectType, Animation } from 'game/game-core';\nimport { Quoting, UndefinedText, WithNumberSign } from 'translator/common-texts';\nimport { qsT, qsTr } from 'translator/translator';\nimport { FRAME_SIZE } from './frame-artist';\nimport { assertFalse } from 'utils/assert';\nimport { toStr } from 'utils/types';\n\n// types\nexport type AnimationIndex = number;\n\n// constants\nexport const AnimationIdleText = qsT('idle');\nexport const AnimWithIndexText = qsTr('anim. %1');\n\n// functions\nexport function quotedAnimNameOrIndex(objectType: ObjectType | null, index: number | null) {\n\tif (index === null) {\n\t\treturn UndefinedText;\n\t}\n\tconst name = objectType?.animName(index) ?? null;\n\tif (name) {\n\t\treturn Quoting.args(name);\n\t} else {\n\t\treturn WithNumberSign.args(index);\n\t}\n}\n\nexport function computeFrameScaleFactor(animations: Animation[]) {\n\tlet maxExtent = 0;\n\tfor (const animation of animations) {\n\t\tfor (const frame of animation.frames) {\n\t\t\tif (frame === undefined || frame === null) {\n\t\t\t\tassertFalse(`undefined frame in animation ${animation.name}: ${toStr(animation)}`);\n\t\t\t}\n\t\t\tmaxExtent = Math.max(maxExtent, frame.maxExtent);\n\t\t}\n\t}\n\treturn FRAME_SIZE * 0.48 / maxExtent;\n}","/**\n * @module block-script\n */\n/** comment to work-around limitation of typedoc module plugin */\n\n// Copyright 2018-2024 Enlightware GmbH, Switzerland\n\nimport { ScriptCtx, Compiler, ExecOutput } from 'app-core-web/pkg';\nimport { CandliBlock } from 'game/game-block-definition';\nimport { SpacedOr } from 'translator/common-texts';\nimport { qsT, qsTr } from 'translator/translator';\nimport { ValuePortPresence } from 'vpl/block';\nimport { renameCandliVariable } from './script-parser';\n\n/// A function that executes a script block.\nexport type ExecFn = (_compiler: Compiler, _name: string, _input: number) => ExecOutput;\n\n/// A map of possible functions, along with whether they take an input and produce an output.\nexport type ExecFns = Map;\n\nfunction fallbackExecFn() {\n\treturn (_compiler: Compiler, _name: string, _input: number) => new ExecOutput(true);\n}\n\nconst FnMainNotFound = qsT('Function main not found');\nconst FnMainWrongSignature = qsTr('Function main must have signature %1, but got %2 instead');\n\nexport function verifyMainSignature(compiler: Compiler, validSignatures: string[]) {\n\tconst mainSig = compiler.fn_signature_without_effects('main');\n\tif (mainSig === undefined) {\n\t\treturn FnMainNotFound;\n\t} else {\n\t\tif (validSignatures.includes(mainSig)) {\n\t\t\treturn null\n\t\t} else {\n\t\t\tconst validSigsText = validSignatures.join(SpacedOr);\n\t\t\treturn FnMainWrongSignature.args(validSigsText, mainSig);\n\t\t}\n\t}\n}\n\nexport abstract class ScriptAbstractBlock extends CandliBlock {\n\texecFn = fallbackExecFn();\n\tinput = false;\n\toutput = false;\n\tcompiler: Compiler;\n\tcompilationError: string | null = null;\n\n\tconstructor(\n\t\tpublic code: string,\n\t\tpublic scriptCtx: ScriptCtx,\n\t\tpublic readonly execFns: ExecFns,\n\t\ttype: string,\n\t\tlockState?: CandliBlock\n\t) {\n\t\tsuper(type, lockState);\n\t\tthis.compiler = this.rebuildCompiler();\n\t\tthis.compile();\n\t}\n\n\tprotected abstract rebuildCompiler(): Compiler;\n\n\tsetupCompiler() {\n\t\tthis.compiler = this.rebuildCompiler();\n\t}\n\n\tcompile() {\n\t\t// reset compilation state\n\t\tthis.execFn = fallbackExecFn();\n\t\tthis.input = false;\n\t\tthis.output = false;\n\t\tthis.compilationError = null;\n\n\t\t// recompile\n\t\tconst errors = this.compiler.compile(this.code);\n\t\tif (errors !== undefined && errors.length > 0) {\n\t\t\tthis.compilationError = errors.map(error => error.text).join('; ');\n\t\t} else {\n\t\t\tconst mainSig = this.compiler.fn_signature_without_effects('main');\n\t\t\tif (mainSig === undefined) {\n\t\t\t\tthis.compilationError = FnMainNotFound;\n\t\t\t} else {\n\t\t\t\tconst execFn = this.execFns.get(mainSig);\n\t\t\t\tif (execFn !== undefined) {\n\t\t\t\t\tthis.execFn = execFn[0];\n\t\t\t\t\tthis.input = execFn[1];\n\t\t\t\t\tthis.output = execFn[2];\n\t\t\t\t} else {\n\t\t\t\t\tconst validSigs = [...this.execFns.keys()].join(SpacedOr);\n\t\t\t\t\tthis.compilationError = FnMainWrongSignature.args(validSigs, mainSig);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tget inputValuePortPresence() {\n\t\treturn this.input ? ValuePortPresence.Mandatory : ValuePortPresence.None;\n\t}\n\n\tget outputValuePortPresence() {\n\t\treturn this.output ? ValuePortPresence.Mandatory : ValuePortPresence.None;\n\t}\n\n\tsummaryText() {\n\t\tconst len = this.code.split('\\n').length;\n\t\treturn qsTr('script (%1 l.)').args(len);\n\t}\n\n\tdetailedText() {\n\t\tconst len = this.code.split('\\n').length;\n\t\treturn qsTr('execute script (%1 lines)').args(len);\n\t}\n\n\tneedsConfiguration() {\n\t\treturn this.compilationError !== null;\n\t}\n\n\tneedsConfigurationFix() {\n\t\tif (this.compilationError !== null) {\n\t\t\treturn qsTr('fix compilation error: \"%1\"').args(this.compilationError);\n\t\t} else {\n\t\t\treturn '';\n\t\t}\n\t}\n\n\trun(lastValue: number | undefined, logCtx: string) {\n\t\tif (this.compilationError !== null) {\n\t\t\tconsole.error(`ScriptAbstractBlock @ ${logCtx} cannot run due to compilation error:`, this.compilationError);\n\t\t\treturn [undefined, false] as const;\n\t\t}\n\t\ttry {\n\t\t\tconst result = this.execFn(this.compiler, 'main', lastValue ?? 0);\n\t\t\treturn [result.value, result.cont] as const;\n\t\t} catch (e) {\n\t\t\tconsole.error(`ScriptAbstractBlock @ ${logCtx} error during execution:`, e);\n\t\t\treturn [undefined, false] as const;\n\t\t}\n\t}\n\n\t/// Rename all occurrences of a Candli variable, using the Lezer grammar.\n\trenameVariable(oldName: string, newName: string) {\n\t\tthis.code = renameCandliVariable(this.code, oldName, newName);\n\t}\n}\n","/**\n * condition: execute a script in a condition block\n * @module block-condition-script\n * @preferred\n */\n/** comment to work-around limitation of typedoc module plugin */\n\n// Copyright 2018-2024 Enlightware GmbH, Switzerland\n\nimport { CandliBlock } from 'game/game-block-definition';\nimport * as flatbuffers from 'flatbuffers';\nimport * as CandliFB from 'flatbuffers/all';\nimport { BlockKind } from 'vpl/block';\nimport { qsT } from 'translator/translator';\nimport { ScriptAbstractBlock } from 'blocks/common/script/script-block';\nimport { exec_fn_unit_bool as execFnUnitBool, exec_fn_int_bool as execFnIntBool, exec_fn_unit_tuple as execFnUnitTuple, exec_fn_int_tuple as execFnIntTuple, ScriptCtx } from 'app-core-web/pkg';\nimport { assertMemberEqual } from 'utils/assert';\n\n\nconst execFns = new Map([\n\t['() → bool', [execFnUnitBool, false, false]],\n\t['(int) → bool', [execFnIntBool, true, false]],\n\t['() → (bool, int)', [execFnUnitTuple, false, true]],\n\t['(int) → (bool, int)', [execFnIntTuple, true, true]],\n] as const);\n\nexport function setupCompiler(scriptCtx: ScriptCtx) {\n\treturn scriptCtx.condition_block_script_compiler();\n}\n\nexport function validSignatures() {\n\treturn [...execFns.keys()];\n}\n\nfunction getCode(codeOrFb: string | CandliFB.ScriptCondition) {\n\tif (typeof codeOrFb === 'string') {\n\t\treturn codeOrFb;\n\t} else {\n\t\treturn codeOrFb.code() ?? '';\n\t}\n}\n\nexport class ScriptConditionBlock extends ScriptAbstractBlock {\n\tconstructor(code: string, scriptCtx: ScriptCtx, lockState?: CandliBlock);\n\tconstructor(fb: CandliFB.ScriptCondition, scriptCtx: ScriptCtx);\n\tconstructor(codeOrFb: string | CandliFB.ScriptCondition, scriptCtx: ScriptCtx, lockState?: CandliBlock) {\n\t\tsuper(getCode(codeOrFb), scriptCtx, execFns, 'ScriptCondition', lockState);\n\t}\n\n\trebuildCompiler() {\n\t\treturn setupCompiler(this.scriptCtx);\n\t}\n\n\tclone(): ScriptConditionBlock {\n\t\treturn new ScriptConditionBlock(this.code, this.scriptCtx, this);\n\t}\n\n\tget name() {\n\t\treturn qsT('Condition script');\n\t}\n\n\tserialise(builder: flatbuffers.Builder) {\n\t\treturn CandliFB.ScriptCondition.createScriptCondition(builder, builder.createString(this.code));\n\t}\n\n\tget fbConditionType() {\n\t\treturn CandliFB.AnyCondition.ScriptCondition;\n\t}\n\n\tget kind(): BlockKind {\n\t\treturn BlockKind.Condition;\n\t}\n\n\tget premium() {\n\t\treturn false;\n\t}\n\n\tgetMiniatureKey() {\n\t\treturn `script-condition ${this.code}`;\n\t}\n\n\tassertEqual(that: ScriptConditionBlock, ctx: string) {\n\t\tassertMemberEqual(this, that, 'code', ctx);\n\t}\n}","/**\n * generic: read the value of a variable\n * @module block-read-variable\n * @preferred\n */\n/** comment to work-around limitation of typedoc module plugin */\n\n// Copyright 2018-2024 Enlightware GmbH, Switzerland\n\nimport { CandliBlock } from 'game/game-block-definition';\nimport * as flatbuffers from 'flatbuffers';\nimport * as CandliFB from 'flatbuffers/all';\nimport { BlockKind, ValuePortPresence } from 'vpl/block';\nimport { qsT, qsTr } from 'translator/translator';\nimport { varLongNameAcc, varShortName } from 'blocks/common/variable/variable-block';\nimport { EditedObjectContext } from 'level/behaviour-editor-interface';\n\nconst ReadTextArg = qsTr('read %1');\nexport const ReadVariableText = qsT('Read variable');\n\nexport class ReadVariableBlock extends CandliBlock {\n\tpublic address: number;\n\n\tconstructor(\n\t\taddressOrFbVariable: number | CandliFB.ReadVariable,\n\t\tlockState?: CandliBlock\n\t) {\n\t\tsuper('ReadVariable', lockState);\n\t\tif (addressOrFbVariable instanceof CandliFB.ReadVariable) {\n\t\t\tthis.address = addressOrFbVariable.address();\n\t\t} else {\n\t\t\tthis.address = addressOrFbVariable;\n\t\t}\n\t}\n\n\tclone(): ReadVariableBlock {\n\t\treturn new ReadVariableBlock(this.address, this);\n\t}\n\n\tget name() {\n\t\treturn ReadVariableText;\n\t}\n\n\tget outputValuePortPresence() {\n\t\treturn ValuePortPresence.Mandatory;\n\t}\n\n\tserialise(builder: flatbuffers.Builder) {\n\t\treturn CandliFB.ReadVariable.createReadVariable(builder,\n\t\t\tthis.address\n\t\t);\n\t}\n\n\tsummaryText() {\n\t\treturn ReadTextArg.args(varShortName(this.address));\n\t}\n\n\tdetailedTextIfConfigured(userContext: EditedObjectContext | null) {\n\t\tif (this.address === 0) {\n\t\t\treturn qsT('read the score');\n\t\t} else {\n\t\t\treturn ReadTextArg.args(varLongNameAcc(this.address, userContext?.game));\n\t\t}\n\t}\n\n\tget fbGenericType() {\n\t\treturn CandliFB.AnyGenericBlock.ReadVariable;\n\t}\n\n\tget kind(): BlockKind {\n\t\treturn BlockKind.Generic;\n\t}\n\n\tget premium() {\n\t\treturn true;\n\t}\n\n\tgetMiniatureKey() { return `readVar ${this.address}`; }\n}\n","/**\n * @module game\n */\n/** comment to work-around limitation of typedoc module plugin */\n\n// Copyright 2018-2024 Enlightware GmbH, Switzerland\n\nimport { Level, ObjectInstance } from './game-core';\nimport { Vector2, SimilarityTransform, transformVectors2 } from 'math/linalg';\nimport { AnyCanvasRenderingContext2D } from 'imgui/imgui-types';\nimport { DrawLineStrip, DrawSprite, FillCircle, FillConvexPolygon, PointListBuilder, StrokeCircle, StrokeRect, TransformedList } from 'imgui/display-actions';\nimport { EditableLayers, LayersAllEditable } from 'level/level-editor-interface';\nimport { DisplayAction } from 'imgui/display-list';\nimport { Color } from 'color/color';\nimport { Rect } from 'math/geometry';\nimport { assert, assertNonEmptyArray } from 'utils/assert';\nimport { ColorTheme } from 'vpl/color-theme';\nimport { FixedSizeArray } from 'utils/array-types';\nimport { GUI } from 'imgui/imgui';\n\nexport function fillShape(shape: Vector2[] | number, color: Color): DisplayAction {\n\tif (shape instanceof Array) {\n\t\tconst builder = new PointListBuilder(shape.length);\n\t\tshape.forEach((point, i) => {\n\t\t\tbuilder.set(i, point.x, point.y);\n\t\t});\n\t\treturn new FillConvexPolygon(builder, color);\n\t} else {\n\t\treturn new FillCircle(new Vector2(), shape, color);\n\t}\n}\n\nexport function strokeShape(shape: Vector2[] | number, color: Color, lineWidth = 1, dashed = false): DisplayAction {\n\tif (shape instanceof Array) {\n\t\tconst builder = new PointListBuilder(shape.length + 1);\n\t\tshape.forEach((point, i) => {\n\t\t\tbuilder.set(i, point.x, point.y);\n\t\t});\n\t\tassertNonEmptyArray(shape, 'shape');\n\t\tbuilder.set(shape.length, shape[0].x, shape[0].y);\n\t\treturn new DrawLineStrip(builder, lineWidth, color, dashed);\n\t} else {\n\t\treturn new StrokeCircle(new Vector2(), shape, color, lineWidth, dashed);\n\t}\n}\n\nfunction computeObjectTransform(object: ObjectInstance, worldToCanvas: SimilarityTransform) {\n\treturn worldToCanvas.after(object.pose);\n}\n\nexport function drawObjectInstance(object: ObjectInstance, ctxOrGUI: AnyCanvasRenderingContext2D | GUI, worldToCanvas: SimilarityTransform, alpha = 1.0, selected = false, outlined = false, clipRect: Rect | null = null) {\n\tconst objectType = object.type;\n\tconst firstFrame = objectType.firstFrame;\n\tconst transform = computeObjectTransform(object, worldToCanvas);\n\tif (ctxOrGUI instanceof GUI) {\n\t\tconst gui = ctxOrGUI;\n\t\tconst guiSprite = gui.renderCtx.addSprite(firstFrame.sprite.canvas, false);\n\t\tconst drawSprite = new DrawSprite(Vector2.zeros(), guiSprite);\n\t\tconst spriteTransformList = new TransformedList(firstFrame.partFromPixelTransform, drawSprite);\n\t\tdrawSprite.opacity = alpha * (object.movementLocked ? 0.5 : 1.0);\n\t\tconst list: DisplayAction[] = [];\n\t\tlist.push(spriteTransformList);\n\t\tif (selected) {\n\t\t\tconst color = ColorTheme.secondaryColor.clone();\n\t\t\tcolor.alpha = 0.5;\n\t\t\tlist.push(fillShape(objectType.polygonShapeOrRadius, color));\n\t\t}\n\t\tif (outlined) {\n\t\t\tconst width = 2 / transform.scaleFactor;\n\t\t\tlist.push(strokeShape(objectType.polygonShapeOrRadius, ColorTheme.secondaryColor, width));\n\t\t}\n\t\tconst transformList = new TransformedList(transform, list);\n\t\tif (clipRect !== null && !transformList.extent.intersectsRect(clipRect)) {\n\t\t\treturn;\n\t\t}\n\t\tgui.addDisplayAction(transformList);\n\t} else {\n\t\tconst ctx = ctxOrGUI;\n\t\t// ignore clipRect in this case\n\t\tconst spriteTransform = transform.after(firstFrame.partFromPixelTransform);\n\t\tif (object.movementLocked) {\n\t\t\tctx.globalAlpha = 0.5;\n\t\t}\n\t\tconst oldTransform = ctx.getTransform();\n\t\tctx.translate(spriteTransform.translationX, spriteTransform.translationY);\n\t\tctx.rotate(spriteTransform.rotationAngle);\n\t\tctx.scale(spriteTransform.scaleFactor, spriteTransform.scaleFactor);\n\t\tconst size = firstFrame.sprite.size;\n\t\tfirstFrame.sprite.draw(ctx, 0, 0, size.x, size.y);\n\t\tassert(!selected, 'selected unimplemented for canvasCtx');\n\t\tctx.setTransform(oldTransform);\n\t\tif (object.movementLocked) {\n\t\t\tctx.globalAlpha = 1.0;\n\t\t}\n\t}\n\n}\n\nexport function drawLevelObjects(\n\tctxOrGUI: AnyCanvasRenderingContext2D | GUI,\n\tworldToScreen: SimilarityTransform,\n\tlevel: Level,\n\tdraggedObjects: Set | null,\n\tselectedObjects: Set | null,\n\toutlinedObject: ObjectInstance | null = null,\n\teditableLayers: EditableLayers = LayersAllEditable,\n\tclipRect: Rect | null = null\n) {\n\t// paint objects in two passes\n\t// first collect into layers\n\tconst layers: FixedSizeArray = [[], [], [], []];\n\tfor (const object of level.objects) {\n\t\tlayers[object.type.kind].push(object);\n\t}\n\t/// then render all layers\n\tfor (const [index, layer] of layers.entries()) {\n\t\tconst layerAlpha = editableLayers[index] ? 1.0 : 0.5;\n\t\tfor (const object of layer) {\n\t\t\tif (draggedObjects?.has(object)) {\n\t\t\t\t// skip objects being dragged\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst selected = selectedObjects?.has(object) && draggedObjects === null;\n\t\t\tconst outlined = outlinedObject === object;\n\t\t\tconst objectAlpha = object.type.alpha;\n\t\t\tconst alpha = layerAlpha * objectAlpha;\n\t\t\tdrawObjectInstance(object, ctxOrGUI, worldToScreen, alpha, selected, outlined, clipRect);\n\t\t\t// show dashed shape for objects with alpha < 0.5\n\t\t\tif (objectAlpha < 0.5) {\n\t\t\t\tconst transform = computeObjectTransform(object, worldToScreen);\n\t\t\t\tconst transformedShape = transformVectors2(object.type.polygonShape, transform);\n\t\t\t\tif (ctxOrGUI instanceof GUI) {\n\t\t\t\t\tctxOrGUI.addDisplayAction(strokeShape(transformedShape, Color.white.clone().setAlpha(layerAlpha), 2, true));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}","/**\n * @module imgui\n */\n\n// Copyright 2018-2024 Enlightware GmbH, Switzerland\n\nimport { assertNonNull } from 'utils/assert';\nimport { SimilarityTransform, Vector2 } from 'math/linalg';\nimport { Rect } from 'math/geometry';\nimport { Color } from 'color/color';\nimport { Font, Sprite } from './render-context';\nimport { DisplayAction, SealedDisplayList } from './display-list';\nimport { dynamicCast, toStr } from 'utils/types';\n\nfunction areFloat32ArrayEqual(a: Float32Array, b: Float32Array) {\n\tif (a.length !== b.length) {\n\t\treturn false;\n\t}\n\tfor (let i = 0; i < a.length; ++i) {\n\t\tif (a[i] !== b[i]) {\n\t\t\treturn false;\n\t\t}\n\t}\n\treturn true;\n}\n\nfunction pointFloat32ArrayToString(points: Float32Array) {\n\tlet s = '';\n\tfor (let i = 0; i < points.length; i += 2) {\n\t\tconst startX = points[i];\n\t\tconst startY = points[i + 1];\n\t\ts += `(${startX},${startY})` + (i + 2 < points.length ? ', ' : '');\n\t}\n\treturn s;\n}\n\nexport class FillRect extends DisplayAction {\n\tconstructor(public rect: Rect, public color: Color) { super(); }\n\n\tstatic fromRect(x: number, y: number, width: number, height: number, color: Color) {\n\t\treturn new FillRect(new Rect(x, y, width, height), color);\n\t}\n\n\tget extent() {\n\t\treturn this.rect;\n\t}\n\n\tisEqual(other: DisplayAction): boolean {\n\t\tconst that = dynamicCast(FillRect, other);\n\t\tif (that === null) {\n\t\t\treturn false;\n\t\t}\n\t\treturn this.rect.isEqual(that.rect) &&\n\t\t\tthis.color.isEqual(that.color)\n\t\t;\n\t}\n\n\ttoString() {\n\t\treturn `FillRect ${this.rect} ${this.color.rgbaHexString}`;\n\t}\n}\n\nexport class StrokeRect extends DisplayAction {\n\tconstructor(public rect: Rect, public color: Color, public lineWidth = 1, public dashed = false) { super(); }\n\n\tget extent() {\n\t\treturn this.rect.dilate(this.lineWidth * 0.5);\n\t}\n\n\tisEqual(other: DisplayAction): boolean {\n\t\tconst that = dynamicCast(StrokeRect, other);\n\t\tif (that === null) {\n\t\t\treturn false;\n\t\t}\n\t\treturn this.rect.isEqual(that.rect) &&\n\t\t\tthis.color.isEqual(that.color) &&\n\t\t\tthis.lineWidth === that.lineWidth &&\n\t\t\tthis.dashed === that.dashed\n\t\t;\n\t}\n\n\ttoString() {\n\t\treturn `StrokeRect ${this.rect} ${this.color.rgbaHexString} ${this.dashed}`;\n\t}\n}\n\nexport class FillCircle extends DisplayAction {\n\tconstructor(public center: Vector2, public radius: number, public color: Color) { super(); }\n\n\tget extent() {\n\t\treturn Rect.fromCenterAndHalfSize(this.center, Vector2.fromScalar(this.radius));\n\t}\n\n\tisEqual(other: DisplayAction): boolean {\n\t\tconst that = dynamicCast(FillCircle, other);\n\t\tif (that === null) {\n\t\t\treturn false;\n\t\t}\n\t\treturn this.center.isEqual(that.center) &&\n\t\t\tthis.radius === that.radius &&\n\t\t\tthis.color.isEqual(that.color)\n\t\t;\n\t}\n\n\ttoString() {\n\t\treturn `FillCircle ${this.center} ${this.radius} ${this.color.rgbaHexString}`;\n\t}\n}\n\nexport class StrokeCircle extends DisplayAction {\n\tconstructor(public center: Vector2, public radius: number, public color: Color, public lineWidth = 1, public dashed = false) { super(); }\n\n\tget extent() {\n\t\treturn Rect.fromCenterAndHalfSize(this.center, Vector2.fromScalar(this.radius + this.lineWidth * 0.5));\n\t}\n\n\tisEqual(other: DisplayAction): boolean {\n\t\tconst that = dynamicCast(StrokeCircle, other);\n\t\tif (that === null) {\n\t\t\treturn false;\n\t\t}\n\t\treturn this.center.isEqual(that.center) &&\n\t\t\tthis.radius === that.radius &&\n\t\t\tthis.color.isEqual(that.color) &&\n\t\t\tthis.lineWidth === that.lineWidth &&\n\t\t\tthis.dashed === that.dashed\n\t\t;\n\t}\n\n\ttoString() {\n\t\treturn `StrokeCircle ${this.center} ${this.radius} ${this.color.rgbaHexString} ${this.dashed}`;\n\t}\n}\n\n// TODO: add draw capsule if useful\n\nexport class LineListBuilder {\n\tpoints: Float32Array;\n\n\tconstructor(count: number) {\n\t\tthis.points = new Float32Array(count * 4);\n\t}\n\n\tset(index: number, startX: number, startY: number, endX: number, endY: number) {\n\t\tconst i = index * 4;\n\t\tthis.points[i] = startX;\n\t\tthis.points[i + 1] = startY;\n\t\tthis.points[i + 2] = endX;\n\t\tthis.points[i + 3] = endY;\n\t}\n}\n\nexport class DrawLineList extends DisplayAction {\n\treadonly extent: Rect;\n\tpoints: Float32Array;\n\n\tconstructor(builder: LineListBuilder, public width: number, public color: Color, public dashed = false) {\n\t\tsuper();\n\t\tthis.points = builder.points;\n\t\tthis.extent = Rect.fromPointsAsFloat32Array(this.points).dilate(width * 0.5);\n\t}\n\n\tstatic fromSegment(start: Vector2, end: Vector2, width: number, color: Color, dashed = false) {\n\t\tconst builder = new LineListBuilder(1);\n\t\tbuilder.set(0, start.x, start.y, end.x, end.y);\n\t\treturn new DrawLineList(builder, width, color, dashed);\n\t}\n\n\tisEqual(other: DisplayAction): boolean {\n\t\tconst that = dynamicCast(DrawLineList, other);\n\t\tif (that === null) {\n\t\t\treturn false;\n\t\t}\n\t\treturn areFloat32ArrayEqual(this.points, that.points) &&\n\t\t\tthis.color.isEqual(that.color) &&\n\t\t\tthis.width === that.width &&\n\t\t\tthis.dashed === that.dashed\n\t\t;\n\t}\n\n\ttoString() {\n\t\tlet s = 'DrawLineList ';\n\t\tconst points = this.points;\n\t\tfor (let i = 0; i < points.length; i += 4) {\n\t\t\tconst startX = points[i];\n\t\t\tconst startY = points[i + 1];\n\t\t\tconst endX = points[i + 2];\n\t\t\tconst endY = points[i + 3];\n\t\t\ts += `(${startX},${startY})-(${endX},${endY})` + (i + 4 < points.length ? ', ' : '');\n\t\t}\n\t\treturn s + ` ${this.width} ${this.color.rgbaHexString} ${this.dashed}`;\n\t}\n}\n\nexport class PointListBuilder {\n\tpoints: Float32Array;\n\n\tconstructor(count: number) {\n\t\tthis.points = new Float32Array(count * 2);\n\t}\n\n\tset(index: number, x: number, y: number) {\n\t\tconst i = index * 2;\n\t\tthis.points[i] = x;\n\t\tthis.points[i + 1] = y;\n\t}\n}\n\nexport class DrawLineStrip extends DisplayAction {\n\treadonly extent: Rect;\n\tpoints: Float32Array;\n\n\tconstructor(builder: PointListBuilder, public width: number, public color: Color, public dashed = false) {\n\t\tsuper();\n\t\tthis.points = builder.points;\n\t\tthis.extent = Rect.fromPointsAsFloat32Array(this.points).dilate(width * 0.5);\n\t}\n\n\tisEqual(other: DisplayAction): boolean {\n\t\tconst that = dynamicCast(DrawLineStrip, other);\n\t\tif (that === null) {\n\t\t\treturn false;\n\t\t}\n\t\treturn areFloat32ArrayEqual(this.points, that.points) &&\n\t\t\tthis.color.isEqual(that.color) &&\n\t\t\tthis.width === that.width &&\n\t\t\tthis.dashed === that.dashed\n\t\t;\n\t}\n\n\ttoString() {\n\t\treturn `DrawLineStrip ${pointFloat32ArrayToString(this.points)} ${this.width} ${this.color.rgbaHexString} ${this.dashed}`;\n\t}\n}\n\nexport class FillConvexPolygon extends DisplayAction {\n\treadonly extent: Rect;\n\tpoints: Float32Array;\n\n\tconstructor(builder: PointListBuilder, public color: Color) {\n\t\tsuper();\n\t\tthis.points = builder.points;\n\t\tthis.extent = Rect.fromPointsAsFloat32Array(this.points);\n\t}\n\n\tisEqual(other: DisplayAction): boolean {\n\t\tconst that = dynamicCast(FillConvexPolygon, other);\n\t\tif (that !== null &&\n\t\t\tareFloat32ArrayEqual(this.points, that.points) &&\n\t\t\tthis.color.isEqual(that.color)\n\t\t) {\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\ttoString() {\n\t\treturn `FillConvexPolygon ${pointFloat32ArrayToString(this.points)} ${this.color.rgbaHexString}`;\n\t}\n}\n\nexport class DrawText extends DisplayAction {\n\treadonly extent: Rect;\n\n\tconstructor(public position: Vector2, public text: string, public font: Font, public color: Color) {\n\t\tsuper();\n\t\tconst textSize = this.font.size(this.text);\n\t\tthis.extent = new Rect(\n\t\t\tthis.position.x,\n\t\t\tthis.position.y - textSize.baseline,\n\t\t\ttextSize.size.x,\n\t\t\ttextSize.size.y\n\t\t);\n\t}\n\n\tisEqual(other: DisplayAction): boolean {\n\t\tconst that = dynamicCast(DrawText, other);\n\t\tif (that === null) {\n\t\t\treturn false;\n\t\t}\n\t\treturn this.position.isEqual(that.position) &&\n\t\t\tthis.text === that.text &&\n\t\t\tthis.font === that.font &&\n\t\t\tthis.color.isEqual(that.color)\n\t\t;\n\t}\n\n\ttoString() {\n\t\treturn `DrawText ${this.position} \"${this.text}\" ${toStr(this.font)} ${this.color.rgbaHexString}`;\n\t}\n}\n\nexport class DrawSprite extends DisplayAction {\n\tconstructor(public position: Vector2, public sprite: Sprite, public opacity = 1) { super(); }\n\n\tget extent() {\n\t\treturn Rect.fromTopLeftAndSize(this.position, this.sprite.size);\n\t}\n\n\tisEqual(other: DisplayAction): boolean {\n\t\tconst that = dynamicCast(DrawSprite, other);\n\t\tif (that === null) {\n\t\t\treturn false;\n\t\t}\n\t\treturn this.position.isEqual(that.position) &&\n\t\t\tthis.sprite === that.sprite &&\n\t\t\tthis.opacity === that.opacity\n\t\t;\n\t}\n\n\ttoString() {\n\t\treturn `DrawSprite ${this.position} ${toStr(this.sprite)} ${this.opacity}`;\n\t}\n}\n\nexport class TransformedList extends DisplayAction {\n\treadonly extent: Rect;\n\tlist: SealedDisplayList;\n\n\tconstructor(public transform: SimilarityTransform, listOrAction: SealedDisplayList | DisplayAction[] | DisplayAction) {\n\t\tsuper();\n\t\tlet innerRect: Rect | null;\n\t\tif (listOrAction instanceof SealedDisplayList) {\n\t\t\tthis.list = listOrAction;\n\t\t\tinnerRect = listOrAction.extent;\n\t\t} else {\n\t\t\tif (listOrAction instanceof Array) {\n\t\t\t\tthis.list = new SealedDisplayList(listOrAction);\n\t\t\t} else {\n\t\t\t\tthis.list = new SealedDisplayList([listOrAction]);\n\t\t\t}\n\t\t\tinnerRect = this.list.extent;\n\t\t}\n\t\tassertNonNull(innerRect, 'constructing a transformed list with no actions');\n\t\tthis.extent = innerRect.transformAsAABB(this.transform);\n\t}\n\n\tisEqual(other: DisplayAction): boolean {\n\t\tconst that = dynamicCast(TransformedList, other);\n\t\tif (that === null) {\n\t\t\treturn false;\n\t\t}\n\t\tif (!this.transform.isEqual(that.transform)) {\n\t\t\treturn false;\n\t\t}\n\t\tconst thisActions = this.list.getActions();\n\t\tconst thatActions = that.list.getActions();\n\t\tif (thisActions.length !== thatActions.length) {\n\t\t\treturn false;\n\t\t}\n\t\tfor (let i = 0; i < thisActions.length; ++i) {\n\t\t\tif (!thisActions[i]!.isEqual(thatActions[i]!)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n\n\ttoString(indent = '') {\n\t\treturn `TransformList ${this.transform.toString()}\\n${this.list.toString(indent + '\\t')}`;\n\t}\n}","/**\n * An immediate-mode GUI that supports generic content and drag and drop in lists.\n * @module imgui\n * @preferred\n */\n/** comment to work-around limitation of typedoc module plugin */\n\n// Copyright 2018-2024 Enlightware GmbH, Switzerland\n\nimport { nonnull, defined, downcast, Constructor } from '../utils/types';\nimport { isBitMaskSet } from '../utils/flags';\nimport { Vector2 } from '../math/linalg';\nimport { clamp } from 'math/helpers';\nimport { resizeCanvas } from 'utils/html';\nimport { assert, assertFalse, assertNonNull, assertNull } from 'utils/assert';\nimport { DisplayAction, DisplayList, SealedDisplayList } from './display-list';\nimport { CanvasRenderContext } from './canvas-renderer';\nimport { RenderContext } from './render-context';\nimport { FillCircle, FillRect } from './display-actions';\nimport { Color } from 'color/color';\nimport * as Platform from './imgui-platform';\nimport { uniqueId } from 'utils/debug';\n\n/** Pointer distance threshold after which a drag is considered dragging */\nexport const DragThreshold = 6;\n\n/** Minimum duration in ms to trigger a long press on a list */\nconst LongPressDuration = 500;\n\nconst DomDeltaLine = 0x01;\nconst DomDeltaPage = 0x02;\n\nconst ScrollBreakTimeConstantMs = 500;\n\nconst A60deg = 60 * Math.PI / 180;\n\nfunction isAngleVertical(angle: number) {\n\treturn Math.abs(angle) > A60deg && Math.abs(angle) < (Math.PI - A60deg);\n}\n\nfunction isAngleHorizontal(angle: number) {\n\treturn Math.abs(angle) < A60deg || Math.abs(angle) > (Math.PI - A60deg);\n}\n\nconst ScrollMarkColor = new Color('#dcdcdc');\nconst ScrollBarColor = new Color([0, 0, 0], 0.4);\n\n// local classes for implementing drag & drop\n\n/** A function that, given an angle, tells if this is an allowed drag */\ntype DragAllowedDirection = (angle: number) => boolean;\n\n/** Drag information. */\nexport class DragFrom {\n\t/** The data being dragged, can be of any type. */\n\tdata: unknown;\n\t/** Whether drag is actually occurring. */\n\tdragging: boolean;\n\n\t/**\n\t * Constructor.\n\t * @param artist - Artist that can paint this drag data.\n\t * @param delta - The position of dragging point wrt top-left side of the dragged image.\n\t * @param source - Source array of the dragged element, or the dragged element itself if not coming from an array.\n\t * @param index - Index in the source array of the dragged element.\n\t * @param allowedDirection - If non null, a function returning whether the drag is allowed for a given angle.\n\t * @param explicitData - Explicit data to be passed to the artist.\n\t */\n\tconstructor(public artist: DragContentArtist, public delta: Vector2, public source: unknown, public index = 0, public allowedDirection: DragAllowedDirection | null = null, explicitData?: unknown) {\n\t\tif (explicitData !== undefined) {\n\t\t\tthis.data = explicitData;\n\t\t} else if (source instanceof Array) {\n\t\t\tthis.data = source[index];\n\t\t} else {\n\t\t\tthis.data = source;\n\t\t\tthis.source = [source];\n\t\t}\n\t\tthis.dragging = false;\n\t}\n}\n\n/** Drop information. */\nexport class DropTo {\n\t/**\n\t * Constructor.\n\t * @param target - Target array where the dragged element should be dropped to.\n\t * @param userData - Context-specific data to locate the element in its target context.\n\t */\n\tconstructor(public target: unknown[] | null = null, public userData: unknown = null) {\n\t}\n}\n\n/** A pointer represents either a mouse, a simulated mouse on touch interfaces, or a single touch. */\nexport class Pointer {\n\tprivate _down = false;\n\tprivate _up = false;\n\tprivate _pressed = false;\n\tprivate _shiftKey = false;\n\tprivate _ctrlKey = false;\n\tprivate _metaKey = false;\n\tprivate _altKey = false;\n\n\t/** pointer position upon press */\n\tpressPos = new Vector2();\n\t/** pointer position and last call to [[GUI.end]] */\n\tlastPos = new Vector2();\n\t/** current pointer position */\n\tcurPos = new Vector2();\n\n\t/** true when mouse or touch was just pressed */\n\tget down(): boolean { return this._down; }\n\t/** true when mouse or touch was just released */\n\tget up(): boolean { return this._up; }\n\t/** true when mouse or touch is being pressed and processed */\n\tget pressed(): boolean { return this._pressed; }\n\t/** difference between curPos and lastPos */\n\tget deltaPos(): Vector2 { return this.curPos.sub(this.lastPos); }\n\t/** different between curPos and pressPos */\n\tget motion(): Vector2 { return this.curPos.sub(this.pressPos); }\n\t/** whether Shift key is pressed */\n\tget shiftKey() { return this._shiftKey; }\n\t/** whether Ctrl key is pressed */\n\tget ctrlKey() { return this._ctrlKey; }\n\t/** whether Meta key is pressed */\n\tget metaKey() { return this._metaKey; }\n\t/** whether Alt key is pressed */\n\tget altKey() { return this._altKey; }\n\t/** whether Ctrl or Meta key is pressed (for MacOS compatibility) */\n\tget ctrlOrMetaKey() { return this._ctrlKey || this._metaKey; }\n\n\t// the following methods are only intended to be used by GUI class and its children.\n\n\t/** pointer was pressed at (x, y) */\n\tpress(x: number, y: number, shiftKey = false, ctrlKey = false, metaKey = false, altKey = false) {\n\t\tthis._down = true;\n\t\tthis._pressed = true;\n\t\tthis.pressPos.x = x;\n\t\tthis.pressPos.y = y;\n\t\tthis.lastPos = this.pressPos.clone();\n\t\tthis.curPos = this.pressPos.clone();\n\t\tthis._shiftKey = shiftKey;\n\t\tthis._ctrlKey = ctrlKey;\n\t\tthis._metaKey = metaKey;\n\t\tthis._altKey = altKey;\n\t}\n\t/** pointer was moved to (x, y) */\n\tmove(x: number, y: number, shiftKey = false, ctrlKey = false, metaKey = false, altKey = false) {\n\t\tthis.curPos.x = x;\n\t\tthis.curPos.y = y;\n\t\tthis._shiftKey = shiftKey;\n\t\tthis._ctrlKey = ctrlKey;\n\t\tthis._metaKey = metaKey;\n\t\tthis._altKey = altKey;\n\t}\n\t/** pointer was released */\n\trelease(shiftKey = false, ctrlKey = false, metaKey = false, altKey = false) {\n\t\tthis._up = true;\n\t\tthis._pressed = false;\n\t\tthis._shiftKey = shiftKey;\n\t\tthis._ctrlKey = ctrlKey;\n\t\tthis._metaKey = metaKey;\n\t\tthis._altKey = altKey;\n\t}\n\t/** pointer was cancelled (e.g. got out of screen) */\n\tcancel() {\n\t\tthis._pressed = false;\n\t}\n\t/** copy current pos to last, clear down and up, return if it was up */\n\tstep(): boolean {\n\t\tthis.lastPos = this.curPos.clone();\n\t\tthis._down = false;\n\t\tconst wasUp = this._up;\n\t\tthis._up = false;\n\t\treturn wasUp;\n\t}\n}\n\n/** Render the GUI. Must call [[GUI.begin]] at the beginning and [[GUI.end]] at the end, and call itself recursively if [[GUI.end]] returns true. */\nexport type RenderFunction = () => void;\n\n// flag constants\n\n/** The orientation and direction of GUI elements. */\nexport const enum Direction {\n\t/** Default: horizontal and left to right */\n\tDefault = 0,\n\t/** bit: Vertical orientation */\n\tVertical = 0b01,\n\t/** bit: Right to left direction */\n\tRightToLeft = 0b10\n}\n\n/** The side of a widget element */\nexport const enum Side {\n\t/** Default: left or top */\n\tLeftOrTop = 0,\n\t/** bit: right or bottom */\n\tRightOrBottom = 0b1\n}\n\nexport const enum ListSide {\n\t/** Start of list */\n\tFront = 0,\n\t/** End of list */\n\tTail = 1\n}\n\n/** The interaction options of lists. */\nexport const enum ListInteractionOptions {\n\t/** Default: no drag and drop but click. */\n\tDefault = 0b00000,\n\t/** bit: allow DnD to copy. */\n\tDndDrag = 0b00001,\n\t/** bit: allow DnD to remove. */\n\tDndRemove = 0b00010,\n\t/** bit: allow DnD to add or reorder. */\n\tDndDrop = 0b00100,\n\t/** bit: allow DnD to drop others. */\n\tDndOthers = 0b01000,\n\t/** mask: allow to reorder list entries by DnD. */\n\tDndReorder = DndDrag | DndDrop | DndRemove,\n\t/** bit: click disabled. */\n\tClickDisabled = 0b10000,\n\t/** bit: long press disabled. */\n\tLongPressDisabled = 0b100000\n}\nexport interface ListInteractionConfig {\n\tDndDrag(element: any): boolean;\n\tDndRemove(element: any): boolean;\n\tDndDrop(): boolean;\n\tDndOthers(): boolean;\n\tClickDisabled(element: any): boolean;\n\tLongPressDisabled(element: any): boolean;\n}\n\n/** Whether scroll marks should be shown */\nexport const enum ListScrollMark {\n\t/** Default: show if scroll is necessary */\n\tAuto = 0,\n\t/** Do not show */\n\tNever,\n\t/** Always show */\n\tAlways\n}\n\n/** The options on how to display a list. */\nexport interface ListDisplayOptions {\n\t/** The orientation and direction (default: Direction.Default). */\n\tdirection?: Direction;\n\t/** The amount of margins on each sides of the list (default: 16). */\n\tmargin?: number;\n\t/** The amount of spacing between elements (default: 16). */\n\telementSpacing?: number;\n\t/** The side to display scroll bars (default: Side.LeftOrTop). */\n\tscrollbarSide?: Side;\n\t/** Whether scroll marks should be shown (default: false). */\n\tscrollMarks?: ListScrollMark;\n\t/** How much internal margin scrolled content can have on extreme positions (default: 0). */\n\tscrollMargin?: number;\n\t/** On which side ot show extension mark (default: Tail). */\n\textendSide?: ListSide\n}\n\n/** The status of a button */\nexport interface ButtonStatus {\n\t/** pressed? */\n\tclicked: boolean;\n\t/** An optional tooltip */\n\ttooltip: string | null;\n\t/** Actions performed by the user since last call */\n\tuserActions: UserActions;\n}\n\n/** The status of a list. */\nexport interface ListStatus {\n\t/** Whether the list is currently being scrolled */\n\tisBeingScrolled: boolean;\n\t/** An optional tooltip */\n\ttooltip: string | null;\n\t/** Actions performed by the user since last call */\n\tuserActions: UserActions;\n}\n\n/** An action resulting from the user interacting with the GUI. */\nexport class UserAction {\n}\n/** A button was clicked. */\nexport class ButtonClicked extends UserAction {\n\t/**\n\t * Constructor.\n\t * @param item the item, the data passed to the button\n\t */\n\tconstructor(public readonly item: unknown) {\n\t\tsuper();\n\t}\n}\n/** A drop hint in a list was clicked */\nexport class ListDropHintClicked extends UserAction {\n\t/**\n\t * Constructor.\n\t * @param list the list that was clicked\n\t */\n\tconstructor(public list: unknown[]) {\n\t\tsuper();\n\t}\n}\n/** An item in a list was clicked. */\nexport class ListItemClicked extends UserAction {\n\t/**\n\t * Constructor.\n\t * @param item the item, list[index] when clicked\n\t * @param list the list that was clicked\n\t * @param index the index of the item, when clicked\n\t */\n\tconstructor(\n\t\tpublic item: unknown,\n\t\tpublic list: unknown[],\n\t\tpublic index: number\n\t) {\n\t\tsuper();\n\t}\n}\n/** An item in a list was long pressed. */\nexport class ListItemLongPressed extends UserAction {\n\t/**\n\t * Constructor.\n\t * @param item the item, list[index] when clicked\n\t * @param list the list that was clicked\n\t * @param index the index of the item, when clicked\n\t */\n\tconstructor(\n\t\tpublic item: unknown,\n\t\tpublic list: unknown[],\n\t\tpublic index: number\n\t) {\n\t\tsuper();\n\t}\n}\n/** An element was added to a list. */\nexport class ListItemAdded extends UserAction {\n\t/**\n\t * Constructor.\n\t * @param item the item, list[index] just after addition\n\t * @param list the list that was modified\n\t * @param index the index where the item was added, just after addition\n\t */\n\tconstructor(\n\t\tpublic item: unknown,\n\t\tpublic list: unknown[],\n\t\tpublic index: number\n\t) {\n\t\tsuper();\n\t}\n}\n/** An element was removed from a list. */\nexport class ListItemRemoved extends UserAction {\n\t/**\n\t * Constructor.\n\t * @param item the item, list[index] just before deletion\n\t * @param list the list that was modified\n\t * @param index the index where the item was located, just before deletion\n\t */\n\tconstructor(\n\t\tpublic item: unknown,\n\t\tpublic list: unknown[],\n\t\tpublic index: number\n\t) {\n\t\tsuper();\n\t}\n}\n/** The selection was modified. */\nexport class SelectionChanged extends UserAction {\n}\n\n/** An element was moved within a list. */\nexport class ListItemMoved extends UserAction {\n\t/**\n\t * Constructor.\n\t * @param item the item, list[index] just before deletion\n\t * @param list the list that was modified\n\t * @param from the index where the item was located previously\n\t * @param to the index where the item is located previously\n\t */\n\tconstructor(\n\t\tpublic item: unknown,\n\t\tpublic list: unknown[],\n\t\tpublic from: number,\n\t\tpublic to: number\n\t) {\n\t\tsuper();\n\t}\n}\n/** A set of user actions, implemented as a vector because the number is small. */\nexport class UserActions extends Array {\n\tstatic single(action: UserAction) {\n\t\tconst userActions = new UserActions();\n\t\tuserActions.push(action);\n\t\treturn userActions;\n\t}\n\tappend(that: OptionalUserActions) {\n\t\tif (that !== null) {\n\t\t\tthis.push(...that);\n\t\t}\n\t\treturn this;\n\t}\n\tforFirstAction(type: Constructor, callback: (a: A) => void) {\n\t\tthis.forEachAction(type, callback, true);\n\t\treturn this;\n\t}\n\tforEachAction(type: Constructor, callback: (a: A) => void, once = false) {\n\t\tfor (const action of this) {\n\t\t\tif (action instanceof type) {\n\t\t\t\tcallback(action as A);\n\t\t\t\tif (once) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t}\n\tremoveActionsOfType(type: Constructor) {\n\t\tlet i = this.length;\n\t\twhile (i--) {\n\t\t\tconst action = this[i];\n\t\t\tif (action instanceof type) {\n\t\t\t\tthis.splice(i, 1);\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t}\n\tcontainsType(type: Constructor) {\n\t\tfor (const action of this) {\n\t\t\tif (action instanceof type) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n}\nexport type OptionalUserActions = UserActions | null;\nexport type OptionalTooltip = string | null;\nexport type PaintElementReturn = [OptionalUserActions, OptionalTooltip];\n\n/** Modifier keys for input events, such as CTRL, etc. */\nexport const enum KeyModifiers {\n\tDefault = 0,\n\tAlt = 0b0001,\n\tCtrl = 0b0010,\n\tShift = 0b0100,\n\tMeta = 0b1000\n}\n\nexport const enum DisplayOutput {\n\tMain = 0,\n\tOverlay = 1\n}\n\nexport abstract class ButtonArtist {\n\t/**\n\t * Paints content as button.\n\t * @param gui - The GUI which requested the paint.\n\t * @param output - The display list into which the drawn commands are pushed.\n\t * @param x - The x-position on the GUI's canvas at which to paint.\n\t * @param y - The y-position on the GUI's canvas at which to paint.\n\t * @param data - The content to paint.\n\t */\n\tabstract paint(gui: GUI, output: DisplayList, x: number, y: number, data: T, getTooltip: boolean): PaintElementReturn;\n\n\t/**\n\t * Free-form intersection test between a point (px, py) and the content to be painted.\n\t * @param px - The x-coordinate of the point to test.\n\t * @param py - The y-coordinate of the point to test.\n\t * @param x - The x-coordinate of the element to be painted.\n\t * @param y - The y-coordinate of the element to be painted.\n\t * @param data - The content to be painted.\n\t */\n\tabstract isPointIn(px: number, py: number, x: number, y: number, data: T): boolean;\n}\n\n/** An class that can paint drag content. */\nexport abstract class DragContentArtist {\n\t/** Constructor. Takes the type of the content, to be used for drag and drop comparison. */\n\tconstructor(public readonly type: symbol) {\t}\n\n\t/**\n\t * Paints content as drag.\n\t * @param gui - The GUI which requested the paint.\n\t * @param output - The display list into which the drawn commands are pushed.\n\t * @param x - The x-position on the GUI's canvas at which to paint.\n\t * @param y - The y-position on the GUI's canvas at which to paint.\n\t * @param data - The content to paint.\n\t * @param drag - Drag information, it is up to the artist to decide whether to consider drag.dx and drag.dy to shift the display of the element to be dragged.\n\t * @param drop - If drop already determined, drop information, otherwise null.\n\t * @returns - User actions performed during this paint, if any, null otherwise\n\t */\n\tabstract paintDragContent(gui: GUI, output: DisplayList, x: number, y: number, data: unknown, drag: DragFrom, drop: DropTo | null): OptionalUserActions;\n}\n\n/** A drag content artist that doesn't do anything */\nexport class NullDragContentArtist extends DragContentArtist {\n\tconstructor(type: symbol) {\n\t\tsuper(type);\n\t}\n\tpaintDragContent(): OptionalUserActions {\n\t\treturn null;\n\t}\n}\n\n/** A class that can paint elements of a non-mutable list. */\nexport abstract class ListElementArtist extends DragContentArtist {\n\t/** Constructor. Takes the type of the content, to be used for drag and drop comparison. */\n\tconstructor(type: symbol) {\n\t\tsuper(type);\n\t}\n\n\t/** The width of a list element. */\n\tabstract get width(): number;\n\n\t/** The height of a list element. */\n\tabstract get height(): number;\n\n\t/**\n\t * Paints content as list element.\n\t * @param gui - The GUI which requested the paint.\n\t * @param output - The display list into which the drawn commands are pushed.\n\t * @param x - The x-position on the GUI's canvas at which to paint.\n\t * @param y - The y-position on the GUI's canvas at which to paint.\n\t * @param data - The content to paint.\n\t * @param index - The index of the element in the list.\n\t * @param listDirection - The direction of the list.\n\t * @param canDrag - Whether the element can be dragged.\n\t * @param canClick - Whether the element can be clicked.\n\t * @param getTooltip - Whether the painter should return a tooltip\n\t * @param prevData - data of the previous element in list, if any\n\t * @param nextData - data of the next element in list, if any\n\t * @returns - User actions performed during this paint, if any, null otherwise\n\t */\n\tabstract paintListElement(gui: GUI, output: DisplayList, x: number, y: number, data: T, index: number, listDirection: Direction, canDrag: boolean, canClick: boolean, getTooltip: boolean, prevData?: T, nextData?: T): PaintElementReturn;\n\n\t/**\n\t * Free-form intersection test between a point (px, py) and the content to be painted.\n\t * @param px - The x-coordinate of the point to test.\n\t * @param py - The y-coordinate of the point to test.\n\t * @param x - The x-coordinate of the element to be painted.\n\t * @param y - The y-coordinate of the element to be painted.\n\t * @param data - The content to be painted.\n\t */\n\tabstract isPointIn(px: number, py: number, x: number, y: number, data: T): boolean;\n\n\t/** Whether elements can be cloned (for Ctrl-based copy) */\n\tcanClone(_element: T) { return false; }\n\n\t/** Clone an element, by default throws. */\n\tclone(_element: T) { assertFalse('By default list elements cannot be cloned'); }\n}\n\n/** A class that can paint elements of a mutable list. */\nexport abstract class MutableListElementArtist extends ListElementArtist {\n\t/** Constructor. Takes the type of the content, to be used for drag and drop comparison. */\n\tconstructor(type: symbol) {\n\t\tsuper(type);\n\t}\n\n\t/**\n\t * Paints preview of the content in the place of a potential drop.\n\t * @param gui - The GUI which requested the paint.\n\t * @param output - The display list into which the drawn commands are pushed.\n\t * @param x - The x-position on the GUI's canvas at which to paint.\n\t * @param y - The y-position on the GUI's canvas at which to paint.\n\t * @param data - The content to paint.\n\t */\n\tabstract paintDropPreview(gui: GUI, output: DisplayList, x: number, y: number, data: T): void;\n\n\t/**\n\t * Paints a hint indicating a position for a potential drop.\n\t * @param gui - The GUI which requested the paint.\n\t * @param output - The display list into which the drawn commands are pushed.\n\t * @param x - The x-position on the GUI's canvas at which to paint.\n\t * @param y - The y-position on the GUI's canvas at which to paint.\n\t */\n\tabstract paintDropHint(gui: GUI, output: DisplayList, x: number, y: number): void;\n\n\t/**\n\t * Free-form intersection test between a point (px, py) and the drop hint.\n\t * By default return false.\n\t * @param px - The x-coordinate of the point to test.\n\t * @param py - The y-coordinate of the point to test.\n\t * @param x - The x-coordinate of the drop hint to be painted.\n\t * @param y - The y-coordinate of the drop hint to be painted.\n\t */\n\tisPointInDropHint(_px: number, _py: number, _x: number, _y: number) { return false; }\n}\n\n/** A class that can paint the content of a drop target. */\nexport abstract class DropTargetArtist {\n\t/** Constructor. Takes a list of types that it accepts for drop. */\n\tconstructor(public types: Array) {}\n\n\t/**\n\t * Paints the drop target when there is no drag or the drag contains a type not in types.\n\t * @param gui - The GUI which requested the paint.\n\t * @param output - The display list into which the drawn commands are pushed.\n\t * @param x - The x-position on the GUI's canvas at which to paint the drop target.\n\t * @param y - The y-position on the GUI's canvas at which to paint the drop target.\n\t * @param width - The width of the the drop target on the GUI's canvas.\n\t * @param height - The height of the the drop target on the GUI's canvas.\n\t */\n\tabstract paintIdle(gui: GUI, output: DisplayList, x: number, y: number, width: number, height: number): void;\n\n\t/**\n\t * Paints the drop target when there is a drag that contains a type in types but the pointer is not on the drop target area.\n\t * @param gui - The GUI which requested the paint.\n\t * @param output - The display list into which the drawn commands are pushed.\n\t * @param x - The x-position on the GUI's canvas at which to paint the drop target.\n\t * @param y - The y-position on the GUI's canvas at which to paint the drop target.\n\t * @param width - The width of the the drop target on the GUI's canvas.\n\t * @param height - The height of the the drop target on the GUI's canvas.\n\t * @param type - The type being dragged.\n\t * @param data - The data being dragged.\n\t */\n\tabstract paintDragging(gui: GUI, output: DisplayList, x: number, y: number, width: number, height: number, type: symbol, data: unknown): void;\n\n\t/**\n\t * Paints the drop target when there is a drag that contains a type in types and the pointer is on the drop target area.\n\t * @param gui - The GUI which requested the paint.\n\t * @param output - The display list into which the drawn commands are pushed.\n\t * @param x - The x-position on the GUI's canvas at which to paint the drop target.\n\t * @param y - The y-position on the GUI's canvas at which to paint the drop target.\n\t * @param width - The width of the the drop target on the GUI's canvas.\n\t * @param height - The height of the the drop target on the GUI's canvas.\n\t * @param type - The type being dragged.\n\t * @param data - The data being dragged.\n\t */\n\tabstract paintHovering(gui: GUI, output: DisplayList, x: number, y: number, width: number, height: number, type: symbol, data: unknown): void;\n}\n\nexport class TransparentDropTargetArtist extends DropTargetArtist {\n\tconstructor(types: Array) {\n\t\tsuper(types);\n\t}\n\tpaintIdle() {\n\t\t// do nothing\n\t}\n\tpaintDragging() {\n\t\t// do nothing\n\t}\n\tpaintHovering() {\n\t\t// do nothing\n\t}\n}\n\n// TODO: When performance becomes too slow, use an Artist superclass\n// with a cache from data x draw_type => pre-drawn image\n// and replace the draw with a copy of pre-rendered bitmap.\n// Invalidate cache on scale factor change.\n\n// main GUI class\n\n/**\n * The main class of the immediate-mode GUI. Call methods on this class to draw widgets.\n */\nexport class GUI {\n\t// drag and drop\n\tprotected drag: DragFrom | null = null;\n\tprotected drop: DropTo | null = null;\n\t/** needed because we use single-pass imgui so we cannot simply clear drop in [[begin]] */\n\tprotected nextDrop: DropTo | null = null;\n\n\t// events\n\t/** non-null when touch is being pressed and processed */\n\tprotected touchIdentifier: number | null = null;\n\t/** The physical mouse or its simulated version on touch devices */\n\tprotected virtualMouse = new Pointer();\n\t/** The physical mouse */\n\tprotected mouse = new Pointer();\n\t/** all active touches */\n\tprotected touches = new Map();\n\t/** how much the wheel has scrolled since last end */\n\tprotected deltaWheel = 0;\n\t/** the key modifiers when deltaWheel is set */\n\tprotected wheelModifiers = 0;\n\n\t// repaint and flow\n\t/** true if any widget has requested a repaint as a result of user interactions */\n\tprotected mustRepaint = false;\n\t/** true if scheduleRender() has been called and the rendering has not happened yet */\n\tprotected renderScheduled = false;\n\t/** bound to \"this\" version of [[performRender]] */\n\tprivate boundPerformRender: (currentTime: DOMHighResTimeStamp) => void;\n\n\t// time measurement\n\t/** the duration since last frame in ms, 0 if first frame */\n\tprotected deltaT = 0;\n\t/** last time measurement */\n\tprotected currentT = 0;\n\n\t// internal state\n\t/** scale of the scene, set from scale in begin() */\n\tprotected scale = 1.;\n\t/** inverted scale of the scene, set from scale in begin() */\n\tprotected invScale = 1.;\n\tprotected output: [DisplayList, DisplayList] = [[], []];\n\tprotected renderContext: RenderContext;\n\tprotected scrollStates: WeakMap;\n\tprotected scrolledDuringInteraction = false;\n\tprotected longPressData: [number, any] | null = null;\n\tprotected longPressFired: any = null;\n\tprotected oldTooltip: OptionalTooltip = null;\n\n\t// call backs\n\tprotected _dataChanged = false;\n\n\t// hooks\n\texternalCtrlPressed = () => false;\n\n\t/**\n\t * Constructor.\n\t * @param canvas - The HTML canvas this GUI will draw on. The GUI will register a callback on window.resize to update the Canvas' internal size to its HTML element side, with HiDPI support.\n\t * @param renderFunction - The GUI render function that will be called upon Canvas resize or when a redraw might be necessary. The GUI is conservative and calls this function more than strictly necessary.\n\t */\n\tconstructor(protected canvas: HTMLCanvasElement, protected renderFunction: RenderFunction, private offscreen = false) {\n\t\tconst ctx = nonnull(canvas.getContext('2d', { alpha: false }));\n\t\tthis.renderContext = new CanvasRenderContext(this.canvas, ctx, offscreen);\n\t\tthis.scrollStates = new WeakMap();\n\n\t\t// bind functions\n\t\tthis.boundPerformRender = this.performRender.bind(this);\n\n\t\tthis.setupEvents();\n\t\t// do a first resize to setup canvas\n\t\tthis.resizeCanvas();\n\t}\n\n\t// getters\n\n\t/** Retrieve the rendering context */\n\tget renderCtx(): RenderContext {\n\t\treturn this.renderContext;\n\t}\n\n\t/** Add a new action to the display action queue */\n\taddDisplayAction(action: DisplayAction, queue = DisplayOutput.Main) {\n\t\tthis.output[queue].push(action);\n\t}\n\n\t/** The main output display list */\n\tget mainOutput() {\n\t\treturn this.output[DisplayOutput.Main];\n\t}\n\n\t/** The overlay output display list */\n\tget overlayOutput() {\n\t\treturn this.output[DisplayOutput.Overlay];\n\t}\n\n\t/**\n\t * Return whether there is drag ongoing\n\t * @param type - Optional type to test for, if not given, test for any type.\n\t */\n\tisDragging(type?: symbol): boolean {\n\t\tif (this.drag === null || !this.drag.dragging) {\n\t\t\treturn false;\n\t\t}\n\t\tif (type) {\n\t\t\treturn type === this.drag.artist.type;\n\t\t}\n\t\treturn true;\n\t}\n\n\t/**\n\t * Return whether we are dragging from a given source\n\t */\n\tisDraggingFromSource(source: unknown) {\n\t\treturn this.drag !== null && this.drag.dragging && this.drag.source === source;\n\t}\n\n\t/** Return whether any data passed to widgets were changed since last [[begin]] */\n\tget dataChanged() { return this._dataChanged; }\n\n\t/** Tell the GUI that data has changed, for example if a painter changes them. */\n\tforceDataChanged() { this._dataChanged = true; }\n\n\t// setup\n\n\t/**\n\t * Helper function to setup events, called from the constructor.\n\t */\n\tprivate setupEvents(): void {\n\t\t// Setup mouse events\n\t\tconst mouseEvents = [\n\t\t\t'mouseDown',\n\t\t\t'mouseMove',\n\t\t\t'mouseUp',\n\t\t\t'mouseLeave'\n\t\t] as const;\n\t\tfor (const mouseEvent of mouseEvents) {\n\t\t\t// We need to force the type, maybe one day Typescript will figure it out by itself\n\t\t\tconst eventName = mouseEvent.toLowerCase() as Lowercase;\n\t\t\tthis.canvas.addEventListener(eventName, (event) => {\n\t\t\t\tevent.stopPropagation();\n\t\t\t\tPlatform.mouseInputSeen();\n\t\t\t\tconst handlerName: `${typeof mouseEvent}Event` = `${mouseEvent}Event`;\n\t\t\t\tthis[handlerName](event);\n\t\t\t});\n\t\t}\n\t\t// Setup wheel events\n\t\tconst wheelEvents = [\n\t\t\t'wheel'\n\t\t] as const;\n\t\tfor (const wheelEvent of wheelEvents) {\n\t\t\t// We need to force the type, maybe one day Typescript will figure it out by itself\n\t\t\tconst eventName = wheelEvent.toLowerCase() as Lowercase;\n\t\t\tthis.canvas.addEventListener(eventName, (event) => {\n\t\t\t\tevent.stopPropagation();\n\t\t\t\tPlatform.mouseInputSeen();\n\t\t\t\tconst handlerName: `${typeof wheelEvent}Event` = `${wheelEvent}Event`;\n\t\t\t\tthis[handlerName](event);\n\t\t\t});\n\t\t}\n\t\t// Setup touch events\n\t\tconst touchEvents = [\n\t\t\t'touchStart',\n\t\t\t'touchMove',\n\t\t\t'touchEnd',\n\t\t\t'touchCancel',\n\t\t] as const;\n\t\tfor (const touchEvent of touchEvents) {\n\t\t\t// We need to force the type, maybe one day Typescript will figure it out by itself\n\t\t\tconst eventName = touchEvent.toLowerCase() as Lowercase;\n\t\t\tthis.canvas.addEventListener(eventName, (event) => {\n\t\t\t\tevent.preventDefault();\n\t\t\t\tPlatform.touchInputSeen();\n\t\t\t\tconst handlerName: `${typeof touchEvent}Event` = `${touchEvent}Event`;\n\t\t\t\tthis[handlerName](event);\n\t\t\t});\n\t\t}\n\t}\n\n\t// support\n\n\t/**\n\t * Assemble a bit field of key modifiers from a mouse event\n\t */\n\tprotected mouseEventToModifiers(event: MouseEvent): number {\n\t\tconst bitField: number =\n\t\t\t(KeyModifiers.Default) |\n\t\t\t(event.altKey ? KeyModifiers.Alt : 0) |\n\t\t\t(event.ctrlKey ? KeyModifiers.Ctrl : 0) |\n\t\t\t(event.shiftKey ? KeyModifiers.Shift : 0) |\n\t\t\t(event.metaKey ? KeyModifiers.Meta : 0)\n\t\t;\n\t\treturn bitField;\n\t}\n\n\t// events\n\n\t/**\n\t * Helper function to resize canvas upon a resize event or change of display mode for example.\n\t */\n\tresizeCanvas(): void {\n\t\tif (this.offscreen) {\n\t\t\t// do not resize the offscreen canvas\n\t\t\treturn;\n\t\t}\n\t\tconst canvas = this.canvas;\n\t\tresizeCanvas(canvas);\n\t\t// if canvas is has surface and is not display: none, render\n\t\tif (canvas.offsetParent !== null && canvas.width !== 0 && canvas.height !== 0) {\n\t\t\tthis.renderContext.present();\n\t\t\tthis.scheduleRender();\n\t\t}\n\t}\n\n\t/**\n\t * Handle drag from mouse position.\n\t * @return whether we must repaint GUI\n\t */\n\tprivate handleDrag(): boolean {\n\t\t// are we pressed and have a drag source?\n\t\tif (!(this.virtualMouse.pressed || this.touchIdentifier !== null) || !this.drag) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// we are not dragging, should we start?\n\t\tif (!this.drag.dragging && (this.virtualMouse.motion.norm2() > DragThreshold * DragThreshold)) {\n\t\t\t// is the current direction allowed for dragging?\n\t\t\tconst allowedDirection = this.drag.allowedDirection;\n\t\t\tif (allowedDirection !== null && !allowedDirection(this.virtualMouse.motion.angle)) {\n\t\t\t\t// no, cancel drag\n\t\t\t\tthis.drag = null;\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\t// yes, start effective drag\n\t\t\tthis.drag.dragging = true;\n\t\t\t// and cancel long press\n\t\t\tthis.cancelLongPress();\n\t\t}\n\n\t\t// if we are dragging, force repaint to update a potential drop target\n\t\treturn this.drag.dragging;\n\t}\n\n\t/**\n\t * Handle a mouse or touch getting out of screen\n\t */\n\tprivate handleCancelEvent(): void {\n\t\t// disable drop target\n\t\tthis.drop = null;\n\t\tthis.nextDrop = null;\n\t\t// regardless of previous state, cancel drag\n\t\tthis.drag = null;\n\t\tthis.drop = null;\n\t\t// regardless of previous state, cancel mouse pressed\n\t\tthis.mouse.cancel();\n\t\tthis.virtualMouse.cancel();\n\t\t// regardless of previous state, cancel touch\n\t\tthis.touchIdentifier = null;\n\n\t\t// force a repaint so that widgets can react to the button up\n\t\tthis.scheduleRender();\n\t}\n\n\t/**\n\t * Handle mouse down DOM event on the [[canvas]].\n\t */\n\tprivate mouseDownEvent(event: MouseEvent): void {\n\t\t// store press information\n\t\tconst scaledX = event.offsetX * this.invScale;\n\t\tconst scaledY = event.offsetY * this.invScale;\n\t\tthis.mouse.press(scaledX, scaledY, event.shiftKey, event.ctrlKey, event.metaKey, event.altKey);\n\t\t// if virtual mouse is not being simulated by touch\n\t\tif (this.touchIdentifier === null) {\n\t\t\tthis.virtualMouse.press(scaledX, scaledY, event.shiftKey, event.ctrlKey, event.metaKey, event.altKey);\n\t\t}\n\n\t\t// force a repaint so that widgets can react to the button down\n\t\tthis.scheduleRender();\n\t}\n\n\t/**\n\t * Handle mouse move DOM event on the [[canvas]].\n\t */\n\tprivate mouseMoveEvent(event: MouseEvent): void {\n\t\t// store move information\n\t\tconst scaledX = event.offsetX * this.invScale;\n\t\tconst scaledY = event.offsetY * this.invScale;\n\t\tthis.mouse.move(scaledX, scaledY, event.shiftKey, event.ctrlKey, event.metaKey, event.altKey);\n\t\tthis.virtualMouse.move(scaledX, scaledY, event.shiftKey, event.ctrlKey, event.metaKey, event.altKey);\n\n\t\t// if drag or move while pressed occurred, force a repaint\n\t\t/*let mustRepaint = false;\n\t\tif (this.drag) {\n\t\t\tmustRepaint = this.handleDrag();\n\t\t} else if (this.virtualMouse.pressed) {\n\t\t\tmustRepaint = true;\n\t\t}*/\n\t\t// now repaint all the time in order to get tooltips, but no redraw will actually happen due to display list comparison\n\t\tif (this.drag) {\n\t\t\tthis.handleDrag();\n\t\t}\n\t\tconst mustRepaint = true;\n\t\tif (mustRepaint) {\n\t\t\tthis.scheduleRender();\n\t\t}\n\t}\n\n\t/**\n\t * Handle mouse up DOM event on the [[canvas]].\n\t */\n\tprivate mouseUpEvent(event: MouseEvent): void {\n\t\t// store release information\n\t\tthis.mouse.release(event.shiftKey, event.ctrlKey, event.metaKey, event.altKey);\n\t\tthis.virtualMouse.release(event.shiftKey, event.ctrlKey, event.metaKey, event.altKey);\n\n\t\t// force a repaint so that widgets can react to the button up\n\t\tthis.scheduleRender();\n\t}\n\n\t/**\n\t * Handle mouse leave DOM event on the [[canvas]].\n\t */\n\tprivate mouseLeaveEvent(event: MouseEvent): void {\n\t\t// simulate a mouse up event\n\t\tthis.handleCancelEvent();\n\t}\n\n\t/**\n\t * Handle wheel DOM event on the [[canvas]].\n\t */\n\tprivate wheelEvent(event: WheelEvent): void {\n\t\t// store move information\n\t\tconst scaledX = event.offsetX * this.invScale;\n\t\tconst scaledY = event.offsetY * this.invScale;\n\t\tthis.mouse.move(scaledX, scaledY, event.shiftKey, event.ctrlKey, event.metaKey, event.altKey);\n\t\tthis.virtualMouse.move(scaledX, scaledY, event.shiftKey, event.ctrlKey, event.metaKey, event.altKey);\n\n\t\t// see if scroll occurred\n\t\tlet scrollFactor = 1;\n\t\tif (event.deltaMode === DomDeltaPage) {\n\t\t\t// we only know how to scroll pixels\n\t\t\treturn;\n\t\t} else if (event.deltaMode === DomDeltaLine) {\n\t\t\t// we are scrolling a line\n\t\t\tscrollFactor = 12;\n\t\t}\n\t\tif (event.deltaY === 0) {\n\t\t\t// we are only interested in y scroll\n\t\t\treturn;\n\t\t}\n\n\t\t// force a repaint if scroll occurred\n\t\tconst delta = event.deltaY * scrollFactor;\n\t\tif (delta !== 0) {\n\t\t\tthis.deltaWheel += delta;\n\t\t\tthis.wheelModifiers = this.mouseEventToModifiers(event);\n\t\t\tthis.scheduleRender();\n\t\t}\n\t}\n\n\t/**\n\t * Handle touch start DOM event on the [[canvas]].\n\t */\n\tprivate touchStartEvent(event: TouchEvent): void {\n\t\t// generic processing of touch events\n\t\tfor (const touch of event.targetTouches) {\n\t\t\tconst rect = downcast(Element, touch.target).getBoundingClientRect();\n\t\t\tconst pointer = new Pointer();\n\t\t\tconst localX = touch.clientX - rect.left;\n\t\t\tconst localY = touch.clientY - rect.top;\n\t\t\tpointer.press(localX * this.invScale, localY * this.invScale);\n\t\t\tthis.touches.set(touch.identifier, pointer);\n\t\t}\n\n\t\t// simulate mouse using touch\n\t\tif (event.targetTouches.length > 0 && this.touchIdentifier === null) {\n\t\t\t// note that touch is being pressed\n\t\t\tconst touch = event.targetTouches[0]!;\n\t\t\tthis.touchIdentifier = touch.identifier;\n\n\t\t\t// store press information\n\t\t\tconst rect = downcast(Element, touch.target).getBoundingClientRect();\n\t\t\tconst localX = touch.clientX - rect.left;\n\t\t\tconst localY = touch.clientY - rect.top;\n\t\t\tthis.virtualMouse.press(localX * this.invScale, localY * this.invScale);\n\t\t}\n\n\t\t// force a repaint so that widgets can react to the event\n\t\tthis.scheduleRender();\n\t}\n\n\t/**\n\t * Handle touch move DOM event on the [[canvas]].\n\t */\n\tprivate touchMoveEvent(event: TouchEvent): void {\n\t\t// generic processing of touch events\n\t\tfor (const touch of event.changedTouches) {\n\t\t\tconst rect = downcast(Element, touch.target).getBoundingClientRect();\n\t\t\tconst pointer = this.touches.get(touch.identifier);\n\t\t\tif (pointer === undefined) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst localX = touch.clientX - rect.left;\n\t\t\tconst localY = touch.clientY - rect.top;\n\t\t\tpointer.move(localX * this.invScale, localY * this.invScale);\n\t\t}\n\n\t\t// if mouse is being simulated using touch\n\t\tif (this.touchIdentifier !== null) {\n\t\t\tfor (const touch of event.changedTouches) {\n\t\t\t\tif (touch.identifier !== this.touchIdentifier) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\t// store move information\n\t\t\t\tconst rect = downcast(Element, touch.target).getBoundingClientRect();\n\t\t\t\tconst localX = touch.clientX - rect.left;\n\t\t\t\tconst localY = touch.clientY - rect.top;\n\t\t\t\tthis.virtualMouse.move(localX * this.invScale, localY * this.invScale);\n\t\t\t\tif (this.drag) {\n\t\t\t\t\tthis.handleDrag();\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t// force a repaint so that widgets can react to the event\n\t\tthis.scheduleRender();\n\t}\n\n\t/**\n\t * Handle touch end DOM event on the [[canvas]].\n\t */\n\tprivate touchEndEvent(event: TouchEvent): void {\n\t\t// generic processing of touch events\n\t\tfor (const touch of event.changedTouches) {\n\t\t\tthis.touches.delete(touch.identifier);\n\t\t}\n\n\t\t// if mouse is being simulated using touch\n\t\tif (this.touchIdentifier !== null) {\n\t\t\tfor (const touch of event.changedTouches) {\n\t\t\t\tif (touch.identifier !== this.touchIdentifier) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\t// store release information\n\t\t\t\tthis.virtualMouse.release();\n\t\t\t\t// regardless of previous state, cancel touch\n\t\t\t\tthis.touchIdentifier = null;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t// force a repaint so that widgets can react to the event\n\t\tthis.scheduleRender();\n\t}\n\n\t/**\n\t * Handle touch cancel DOM event on the [[canvas]].\n\t */\n\tprivate touchCancelEvent(event: TouchEvent): void {\n\t\t// generic processing of touch events\n\t\tfor (const touch of event.changedTouches) {\n\t\t\tthis.touches.delete(touch.identifier);\n\t\t}\n\n\t\t// if mouse is being simulated using touch\n\t\tif (this.touchIdentifier !== null) {\n\t\t\tfor (const touch of event.changedTouches) {\n\t\t\t\tif (touch.identifier !== this.touchIdentifier) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\t// process an up\n\t\t\t\tthis.handleCancelEvent();\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// force a repaint so that widgets can react to the event\n\t\tthis.scheduleRender();\n\t}\n\n\t/** a long pressed elapsed */\n\tprivate longPressTimeout() {\n\t\tassertNonNull(this.longPressData, 'longPressData');\n\t\tthis.longPressFired = this.longPressData[1];\n\t\tthis.scheduleRender();\n\t}\n\n\t/** cancel a long press, stop timer if any */\n\tprivate cancelLongPress() {\n\t\tif (this.longPressData !== null) {\n\t\t\twindow.clearTimeout(this.longPressData[0]);\n\t\t\tthis.longPressData = null;\n\t\t}\n\t}\n\n\t// execution flow\n\n\t/**\n\t * Schedule a render call with the proper context, for example when data have changed.\n\t */\n\tscheduleRender(): void {\n\t\tif (this.renderScheduled) {\n\t\t\t// prevent multiple scheduling of rendering\n\t\t\treturn;\n\t\t}\n\t\tthis.renderScheduled = true;\n\t\twindow.requestAnimationFrame(this.boundPerformRender);\n\t}\n\n\t/**\n\t * Measure time, clear render scheduling, and call render function\n\t */\n\tprotected performRender(t: DOMHighResTimeStamp): void {\n\t\tif (this.currentT === 0) {\n\t\t\tthis.deltaT = 0;\n\t\t} else {\n\t\t\tthis.deltaT = t - this.currentT;\n\t\t}\n\t\tthis.currentT = t;\n\t\tthis.renderScheduled = false;\n\t\tthis.renderFunction();\n\t}\n\n\t/**\n\t * Setup the GUI at the start of a repaint.\n\t * Caller must be called at the start of the render function.\n\t * Caller must call [[end]] at the end of the repaint.\n\t * @param scale - The desired scale of the GUI on the canvas\n\t */\n\tbegin(scale = 1): void {\n\t\tthis._dataChanged = false;\n\t\tthis.scale = scale;\n\t\tthis.invScale = 1 / scale;\n\t\tthis.nextDrop = null;\n\t}\n\n\t/**\n\t *\n\t * Complete a repaint.\n\t * Caller must have called [[begin]] at the start of the render function, and call this method at the end.\n\t * @returns whether we must repaint the GUI again.\n\t */\n\tend(): boolean {\n\t\t// render the output\n\t\t// console.log('rendering list:\\n' + this.output.toString());\n\t\tthis.renderContext.render(\n\t\t\t[new SealedDisplayList(this.output[0]), new SealedDisplayList(this.output[1])],\n\t\t\tthis.scale\n\t\t);\n\t\tthis.output = [[], []];\n\t\tconst oldMustRepaint = this.mustRepaint;\n\t\tthis.mustRepaint = false;\n\t\tthis.drop = this.nextDrop;\n\t\tthis.deltaWheel = 0;\n\t\tthis.touches.forEach((pointer) => {\n\t\t\tpointer.step();\n\t\t});\n\t\tif (this.virtualMouse.step()) {\n\t\t\tconst wasDragging = this.drag !== null && this.drag.dragging;\n\t\t\tthis.drag = null;\n\t\t\tthis.drop = null;\n\t\t\tthis.cancelLongPress();\n\t\t\tthis.longPressFired = null;\n\t\t\t// if we just ended a drag, we must repaint\n\t\t\treturn oldMustRepaint || wasDragging;\n\t\t} else {\n\t\t\treturn oldMustRepaint;\n\t\t}\n\t}\n\n\t// widgets\n\n\tbutton(output: DisplayList, x: number, y: number, data: T, artist: ButtonArtist): ButtonStatus {\n\t\tconst isMouseOn = artist.isPointIn(this.virtualMouse.curPos.x, this.virtualMouse.curPos.y, x, y, data);\n\t\tconst [paintUserActions, tooltip] = artist.paint(this, output, x, y, data, isMouseOn);\n\t\tconst userActions = paintUserActions ?? new UserActions();\n\t\tlet clicked = false;\n\t\tif (isMouseOn &&\n\t\t\tthis.virtualMouse.up &&\n\t\t\tartist.isPointIn(this.virtualMouse.pressPos.x, this.virtualMouse.pressPos.y, x, y, data)\n\t\t) {\n\t\t\tclicked = true;\n\t\t\tuserActions.push(new ButtonClicked(data));\n\t\t}\n\t\treturn {\n\t\t\tclicked,\n\t\t\ttooltip,\n\t\t\tuserActions,\n\t\t};\n\t}\n\n\t/**\n\t * A list widget.\n\t * @param output - The display list into which the drawn commands are pushed.\n\t * @param x - The x-position on canvas.\n\t * @param y - The y-position on canvas.\n\t * @param length - The length of the list on screen, either its width or height depending on direction. Pass null to get from element artist.\n\t * @param breadth - The breadth of the list on screen, either its height or width depending on direction. Pass null to get from element artist.\n\t * @param data - The list content.\n\t * @param elementArtist - The artist to draw the list elements.\n\t * @param interactionOptions - Interaction options: (drag and drop, click).\n\t * @param displayOptions - Display options (direction, spacing and margins, position of scrollbars)\n\t * @returns a status indicating if the list is being scrolled\n\t */\n\tlist(output: DisplayList, x: number, y: number, length: number | null, breadth: number | null,\n\t\tdata: T[],\n\t\telementArtist: ListElementArtist,\n\t\tinteractionOptions: ListInteractionOptions | ListInteractionConfig = ListInteractionOptions.Default,\n\t\tdisplayOptions: ListDisplayOptions\n\t): ListStatus {\n\t\t// display options unpacking\n\t\tconst displayOptionWithDefault =\n\t\t\t(\n\t\t\t\tproperty: K,\n\t\t\t\tdef: NonNullable):\n\t\t\tNonNullable =>\n\t\t\t\tgetDisplayOptionWithDefault(displayOptions, property, def)\n\t\t;\n\t\tconst direction = displayOptionWithDefault('direction', Direction.Default);\n\t\tconst isHorizontal = !isBitMaskSet(direction, Direction.Vertical);\n\t\tconst isRightToLeft = isBitMaskSet(direction, Direction.RightToLeft);\n\t\tconst elementSpacing = displayOptionWithDefault('elementSpacing', 16);\n\t\tconst margin = displayOptionWithDefault('margin', 16);\n\t\tconst scrollbarSide = displayOptionWithDefault('scrollbarSide', Side.LeftOrTop);\n\t\tconst scrollMarks = displayOptionWithDefault('scrollMarks', ListScrollMark.Auto);\n\t\tconst scrollMargin = displayOptionWithDefault('scrollMargin', 0);\n\t\tconst extendSide = displayOptionWithDefault('extendSide', ListSide.Tail);\n\t\tconst insertFront = extendSide === ListSide.Front;\n\t\tassert(!(insertFront && isRightToLeft), 'insert front with right to left is not supported yet');\n\n\t\t// interaction options retrieval\n\t\tconst canDrop = typeof interactionOptions === 'object' ?\n\t\t\tinteractionOptions.DndDrop() :\n\t\t\tisBitMaskSet(interactionOptions, ListInteractionOptions.DndDrop);\n\t\tconst canDropOthers = canDrop && (typeof interactionOptions === 'object' ?\n\t\t\tinteractionOptions.DndOthers() :\n\t\t\tisBitMaskSet(interactionOptions, ListInteractionOptions.DndOthers));\n\t\tconst listShiftForInsertFront = insertFront && canDropOthers;\n\n\t\t// tooltip, user actions\n\t\tlet tooltip: string | null = null;\n\t\tconst userActions = new UserActions();\n\n\t\t// helper functions for layout, converting between logical (orientation independent) and\n\t\t// physical (orientation dependant) coordinates\n\t\t// physical to logical\n\t\tconst logicalX = (_x = x, _y = y) => isHorizontal ? _x : _y;\n\t\tconst logicalY = (_x = x, _y = y) => isHorizontal ? _y : _x;\n\t\tconst logicalXY = (_x = x, _y = y) => (isHorizontal ? [_x, _y] as const : [_y, _x] as const);\n\t\tconst logicalV2 = (_x = x, _y = y) => isHorizontal ? new Vector2(_x, _y) : new Vector2(_y, _x);\n\t\t// local logical coordinates\n\t\tlet [drawX, drawY] = logicalXY();\n\t\t// logical to physical\n\t\tconst physicalX = (_x = drawX, _y = drawY) => isHorizontal ? _x : _y;\n\t\tconst physicalY = (_x = drawX, _y = drawY) => isHorizontal ? _y : _x;\n\t\tconst physicalXY = (_x = drawX, _y = drawY) => (isHorizontal ? [_x, _y] as const : [_y, _x] as const);\n\t\tconst physicalV2 = (_x = drawX, _y = drawY) => isHorizontal ? new Vector2(_x, _y) : new Vector2(_y, _x);\n\n\t\t// The list drawing logic assumes the list is horizontal, if it is vertical,\n\t\t// we have to exchange coordinates back and forth.\n\t\tconst [elementWidth, elementHeight] = logicalXY(elementArtist.width, elementArtist.height);\n\t\tconst [mouseX, mouseY] = logicalXY(this.virtualMouse.curPos.x, this.virtualMouse.curPos.y);\n\n\t\t// center on breadth\n\t\tbreadth = breadth !== null ? breadth : elementHeight;\n\t\tdrawY += (breadth - elementHeight) / 2 | 0;\n\n\t\t// compute dimensions\n\t\tconst deltaElementWidth = elementWidth + elementSpacing;\n\t\tconst isDragging = this.drag !== null && this.drag.dragging;\n\t\tconst isListDragSource = isDragging && this.drag !== null && this.drag.source === data;\n\t\tconst dropElementCount = (canDropOthers && !isListDragSource) ? data.length + 1 : data.length;\n\t\tconst dropAreaIdealWidth = dropElementCount * deltaElementWidth - elementSpacing + 2 * (margin + scrollMargin);\n\t\tlength = length !== null ? length : dropAreaIdealWidth;\n\t\tconst dropAreaLimitedWidth = Math.min(dropAreaIdealWidth, length);\n\t\tconst [dropAreaPhysicalWidth, dropAreaPhysicalHeight] = physicalXY(length, breadth);\n\t\tconst needsScroll = dropAreaIdealWidth > dropAreaLimitedWidth;\n\t\tconst showScrollMarks = scrollMarks === ListScrollMark.Always || (scrollMarks === ListScrollMark.Auto && needsScroll);\n\t\tconst isMouseOnList = this.virtualMouse.curPos.isInRect(x, y, dropAreaPhysicalWidth, dropAreaPhysicalHeight);\n\n\t\t// if second finger and not dragging, cancel drag\n\t\tif (isMouseOnList && this.touches.size > 1 && !this.isDragging()) {\n\t\t\tthis.drag = null;\n\t\t\tthis.mustRepaint = true;\n\t\t}\n\n\t\t// handle scroll\n\t\tlet [scrollPos, scrollSpeed] = [0, 0];\n\t\tif (needsScroll) {\n\t\t\t// initialize state if necessary\n\t\t\tif (!this.scrollStates.has(data)) {\n\t\t\t\tconst initialScroll = (dropAreaIdealWidth - dropAreaLimitedWidth) / 2;\n\t\t\t\tthis.scrollStates.set(data, [initialScroll, 0]);\n\t\t\t}\n\n\t\t\t// process scroll inputs\n\t\t\t[scrollPos, scrollSpeed] = defined(this.scrollStates.get(data));\n\t\t\tlet deltaScroll: number | null = null;\n\t\t\tif (isMouseOnList) {\n\t\t\t\tscrollPos += this.deltaWheel;\n\t\t\t\tif (!this.drag && this.virtualMouse.pressed) {\n\t\t\t\t\tif (!this.scrolledDuringInteraction && this.virtualMouse.motion.norm2() > DragThreshold * DragThreshold) {\n\t\t\t\t\t\t// start scrolling\n\t\t\t\t\t\tthis.scrolledDuringInteraction = true;\n\t\t\t\t\t\t// and cancel long press\n\t\t\t\t\t\tthis.cancelLongPress();\n\t\t\t\t\t\tif (isHorizontal) {\n\t\t\t\t\t\t\tdeltaScroll = -this.virtualMouse.motion.x;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tdeltaScroll = -this.virtualMouse.motion.y;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (this.scrolledDuringInteraction) {\n\t\t\t\t\t\tif (isHorizontal) {\n\t\t\t\t\t\t\tdeltaScroll = -this.virtualMouse.deltaPos.x;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tdeltaScroll = -this.virtualMouse.deltaPos.y;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// process scroll physics\n\t\t\tif (deltaScroll !== null) {\n\t\t\t\t// scroll active, override value and speed\n\t\t\t\tscrollPos += deltaScroll;\n\t\t\t\tif (this.deltaT > 0) {\n\t\t\t\t\tscrollSpeed = deltaScroll / this.deltaT;\n\t\t\t\t} else {\n\t\t\t\t\tscrollSpeed = 0;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// scroll passive, break and stop when too slow\n\t\t\t\tscrollPos += scrollSpeed * this.deltaT;\n\t\t\t\tscrollSpeed *= Math.exp(-this.deltaT / ScrollBreakTimeConstantMs);\n\t\t\t\tif (Math.abs(scrollSpeed) >= 1) {\n\t\t\t\t\tthis.scheduleRender();\n\t\t\t\t} else {\n\t\t\t\t\tscrollSpeed = 0;\n\t\t\t\t\tscrollPos = Math.round(scrollPos);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// bound scroll in any case\n\t\t\tconst boundedScrollPos = clamp(scrollPos, 0, dropAreaIdealWidth - dropAreaLimitedWidth);\n\t\t\tif (boundedScrollPos !== scrollPos) {\n\t\t\t\tscrollPos = boundedScrollPos;\n\t\t\t\tscrollSpeed = 0;\n\t\t\t}\n\n\t\t\tthis.scrollStates.set(data, [scrollPos, scrollSpeed]);\n\t\t} else {\n\t\t\t// center\n\t\t\tscrollPos = -(length - dropAreaIdealWidth) / 2 | 0;\n\t\t}\n\t\t// implement margin by shifting scroll\n\t\tscrollPos -= margin + scrollMargin;\n\t\t// shift drawing according to scroll\n\t\tdrawX -= scrollPos;\n\n\t\t// can we drop on this list, is it the right type, and if so, what is the drop target?\n\t\tconst canDropOnList =\n\t\t\tcanDrop &&\n\t\t\tisDragging &&\n\t\t\tisMouseOnList &&\n\t\t\tthis.drag!.artist.type === elementArtist.type &&\n\t\t\t(canDropOthers || isListDragSource)\n\t\t;\n\t\tif (canDropOnList) {\n\t\t\t// we can drop on this list, update drop information\n\t\t\tconst listPosX = isRightToLeft ? dropAreaLimitedWidth - (mouseX - drawX) : mouseX - drawX;\n\t\t\tlet dropIndex = Math.trunc((listPosX + elementSpacing / 2) / deltaElementWidth) | 0;\n\t\t\tif (isListDragSource) {\n\t\t\t\t// we are self-dragging from this list, so we insert to the left\n\t\t\t\tif (listShiftForInsertFront) {\n\t\t\t\t\tdropIndex -= 1;\n\t\t\t\t}\n\t\t\t\tdropIndex = Math.min(Math.max(dropIndex, 0), data.length - 1);\n\t\t\t} else {\n\t\t\t\tdropIndex = Math.min(Math.max(dropIndex, 0), data.length);\n\t\t\t}\n\t\t\tthis.nextDrop = this.drop = new DropTo(data, dropIndex);\n\t\t} else {\n\t\t\t// we cannot drop on this list, if we could before, disable drop\n\t\t\tif (this.drop !== null && this.drop.target === data) {\n\t\t\t\tthis.nextDrop = this.drop = null;\n\t\t\t}\n\t\t}\n\n\t\t// if right to left, start from the right\n\t\tdrawX += isRightToLeft ? dropAreaLimitedWidth - elementWidth : 0;\n\t\tconst dirFactor = isRightToLeft ? -1 : 1;\n\t\t// in normal conditions with insert front, shift the list\n\t\tif (listShiftForInsertFront) {\n\t\t\tif (!(canDropOnList && !isListDragSource)) {\n\t\t\t\tdrawX += elementWidth + elementSpacing;\n\t\t\t}\n\t\t\t// in addition, if the mouse is left of the first element, further shift\n\t\t\tif (\n\t\t\t\tcanDropOnList &&\n\t\t\t\tisListDragSource &&\n\t\t\t\tmouseX < drawX + elementWidth + elementSpacing / 2\n\t\t\t) {\n\t\t\t\tdrawX += deltaElementWidth * dirFactor;\n\t\t\t}\n\t\t}\n\t\t// do we have to pre-shift elements to make place for insert at top?\n\t\tif (canDropOnList) {\n\t\t\tif (!isRightToLeft && mouseX < drawX - elementSpacing / 2) {\n\t\t\t\t// we only need to pre-shift if we do not insert on the front\n\t\t\t\tif (!listShiftForInsertFront) {\n\t\t\t\t\tdrawX += deltaElementWidth * dirFactor;\n\t\t\t\t}\n\t\t\t} else if (isRightToLeft && mouseX >= drawX + elementWidth + elementSpacing / 2) {\n\t\t\t\t//drawX += deltaElementWidth * dirFactor;\n\t\t\t}\n\t\t}\n\t\t// paint all elements, possibly making space for drop or skipping an element being reordered\n\t\tdata.forEach((element, i) => {\n\t\t\t// interaction options retrieval\n\t\t\tconst canDrag = typeof interactionOptions === 'object' ?\n\t\t\t\tinteractionOptions.DndDrag(element) :\n\t\t\t\tisBitMaskSet(interactionOptions, ListInteractionOptions.DndDrag);\n\t\t\tconst canClick = !(typeof interactionOptions === 'object' ?\n\t\t\t\tinteractionOptions.ClickDisabled(element) :\n\t\t\t\tisBitMaskSet(interactionOptions, ListInteractionOptions.ClickDisabled));\n\t\t\tconst canLongPress = !(typeof interactionOptions === 'object' ?\n\t\t\t\tinteractionOptions.LongPressDisabled(element) :\n\t\t\t\tisBitMaskSet(interactionOptions, ListInteractionOptions.LongPressDisabled));\n\t\t\tconst isElementDragSource = isListDragSource && this.drag!.index === i;\n\t\t\tif (\n\t\t\t\tcanDropOnList &&\n\t\t\t\tmouseX >= drawX - elementSpacing / 2 &&\n\t\t\t\tmouseX < drawX + elementWidth + elementSpacing / 2\n\t\t\t) {\n\t\t\t\tdrawX += deltaElementWidth * dirFactor;\n\t\t\t}\n\n\t\t\tif (!(isElementDragSource && canDropOnList)) {\n\t\t\t\tconst isVirtualMouseOn = elementArtist.isPointIn(this.virtualMouse.curPos.x, this.virtualMouse.curPos.y, physicalX(), physicalY(), element);\n\n\t\t\t\t// paint either the element itself or a drop preview\n\t\t\t\tif (isElementDragSource && canDrop) {\n\t\t\t\t\tconst artist = downcast(MutableListElementArtist, elementArtist);\n\t\t\t\t\tartist.paintDropPreview(this, output, physicalX(), physicalY(), element);\n\t\t\t\t} else {\n\t\t\t\t\tconst painterReturn = elementArtist.paintListElement(this, output, physicalX(), physicalY(), element, i, direction, canDrag, canClick, isVirtualMouseOn, data[i-1], data[i+1]);\n\t\t\t\t\tuserActions.append(painterReturn[0]);\n\t\t\t\t\ttooltip = tooltip ?? painterReturn[1];\n\t\t\t\t}\n\n\t\t\t\tif (isVirtualMouseOn) {\n\t\t\t\t\t// is this block a source drag?\n\t\t\t\t\tif (\n\t\t\t\t\t\tcanDrag &&\n\t\t\t\t\t\tthis.virtualMouse.down &&\n\t\t\t\t\t\tthis.touches.size <= 1\n\t\t\t\t\t) {\n\t\t\t\t\t\t// start a drag from this list\n\t\t\t\t\t\tconst delta = this.virtualMouse.curPos.sub(physicalV2());\n\t\t\t\t\t\t// console.log('delta drag', delta);\n\t\t\t\t\t\t// let allowedFunction = null;\n\t\t\t\t\t\t// if (needsScroll) {\n\t\t\t\t\t\t// \tallowedFunction = isHorizontal ? isAngleVertical : isAngleHorizontal;\n\t\t\t\t\t\t// }\n\t\t\t\t\t\tconst copy = this.virtualMouse.ctrlOrMetaKey || this.externalCtrlPressed();\n\t\t\t\t\t\tif (copy && elementArtist.canClone(element)) {\n\t\t\t\t\t\t\tconst clonedElement = elementArtist.clone(element);\n\t\t\t\t\t\t\tthis.drag = new DragFrom(elementArtist, delta, clonedElement);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthis.drag = new DragFrom(elementArtist, delta, data, i);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// is it the start of a long press?\n\t\t\t\t\tif (\n\t\t\t\t\t\tcanLongPress &&\n\t\t\t\t\t\tthis.virtualMouse.down &&\n\t\t\t\t\t\tthis.touches.size <= 1\n\t\t\t\t\t) {\n\t\t\t\t\t\tif (this.longPressData === null) {\n\t\t\t\t\t\t\tconst timer = window.setTimeout(this.longPressTimeout.bind(this), LongPressDuration);\n\t\t\t\t\t\t\tthis.longPressData = [timer, element];\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthis.longPressData[1] = element;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// we started a long press\n\t\t\t\t\tif (this.longPressData !== null) {\n\t\t\t\t\t\t// did we canceled it by touching another element?\n\t\t\t\t\t\tif (this.longPressData[1] !== element) {\n\t\t\t\t\t\t\tthis.cancelLongPress();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// did a long press fired on this item?\n\t\t\t\t\tif (this.longPressFired === element) {\n\t\t\t\t\t\tuserActions.push(new ListItemLongPressed(element, data, i));\n\t\t\t\t\t\tthis.longPressFired = true;\n\t\t\t\t\t}\n\n\t\t\t\t\t// did we click the element?\n\t\t\t\t\tif (\n\t\t\t\t\t\tcanClick &&\n\t\t\t\t\t\t!this.isDragging() &&\n\t\t\t\t\t\t!this.scrolledDuringInteraction &&\n\t\t\t\t\t\tthis.virtualMouse.up &&\n\t\t\t\t\t\tthis.longPressFired === null\n\t\t\t\t\t) {\n\t\t\t\t\t\tuserActions.push(new ListItemClicked(element, data, i));\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tdrawX += deltaElementWidth * dirFactor;\n\t\t\t}\n\n\t\t\t// show scroll marks if requested\n\t\t\tif (showScrollMarks && i + 1 < data.length) {\n\t\t\t\tconst markX = drawX - (elementSpacing - 4) / 2 - 4;\n\t\t\t\tconst markY = drawY + (elementHeight - 20) / 2;\n\t\t\t\tfor (let j = 0; j < 3; ++j) {\n\t\t\t\t\tconst [px, py] = physicalXY(markX, markY + j * 8);\n\t\t\t\t\toutput.push(new FillCircle(new Vector2(px + 2, py + 2), 2, ScrollMarkColor));\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\t// paint drop preview or drop hint\n\t\tif (this.drop !== null && this.drop.target === data) {\n\t\t\tconst shiftByOne = listShiftForInsertFront && isListDragSource;\n\t\t\tconst shiftX = ((this.drop.userData as number) + (shiftByOne ? 1 : 0)) * deltaElementWidth;\n\t\t\tconst dx = logicalX() + (isRightToLeft ? dropAreaLimitedWidth - elementWidth - shiftX : shiftX) - scrollPos;\n\t\t\tconst [px, py] = physicalXY(dx);\n\t\t\tconst artist = downcast(MutableListElementArtist, elementArtist);\n\t\t\tartist.paintDropPreview(this, output, px, py, this.drag!.data);\n\t\t}\n\t\tif (canDropOthers && !canDropOnList && !isListDragSource) {\n\t\t\tconst shiftX = listShiftForInsertFront ? 0 : data.length * deltaElementWidth;\n\t\t\tconst dx = logicalX() + (isRightToLeft ? dropAreaLimitedWidth - elementWidth - shiftX : shiftX) - scrollPos;\n\t\t\tconst [px, py] = physicalXY(dx);\n\t\t\tconst artist = downcast(MutableListElementArtist, elementArtist);\n\t\t\tartist.paintDropHint(this, output, px, py);\n\t\t\tconst isVirtualMouseOn = artist.isPointInDropHint(this.virtualMouse.curPos.x, this.virtualMouse.curPos.y, px, py);\n\t\t\t// did we click the drop hint?\n\t\t\tif (\n\t\t\t\tisVirtualMouseOn &&\n\t\t\t\t!this.isDragging() &&\n\t\t\t\t!this.scrolledDuringInteraction &&\n\t\t\t\tthis.virtualMouse.up &&\n\t\t\t\tthis.longPressFired === null\n\t\t\t) {\n\t\t\t\tuserActions.push(new ListDropHintClicked(data));\n\t\t\t}\n\t\t}\n\n\t\t// draw scroll bar\n\t\tconst isBeingScrolled = needsScroll && (this.virtualMouse.pressed || this.touchIdentifier !== null) && (this.drag === null) && isMouseOnList;\n\t\tif (isBeingScrolled) {\n\t\t\tconst visibleRatio = dropAreaLimitedWidth / dropAreaIdealWidth;\n\t\t\tconst scrollBarLength = length * visibleRatio;\n\t\t\tconst scrollWidth = dropAreaIdealWidth - dropAreaLimitedWidth;\n\t\t\tconst scrollProgress = (scrollPos + margin + scrollMargin) / scrollWidth;\n\t\t\tconst scrollBarPos = scrollProgress * (length - scrollBarLength);\n\t\t\tconst scrollBarY = scrollbarSide === Side.LeftOrTop ? 2 : breadth - 6;\n\t\t\tconst [x1, y1] = physicalXY(logicalX() + scrollBarPos, logicalY() + scrollBarY);\n\t\t\tconst [x2, y2] = physicalXY(logicalX() + scrollBarPos + scrollBarLength, logicalY() + scrollBarY + 4);\n\t\t\toutput.push(FillRect.fromRect(x1, y1, x2 - x1, y2 - y1, ScrollBarColor));\n\t\t}\n\n\t\t// if mouse is released, clear scrolling state\n\t\tif (this.virtualMouse.up) {\n\t\t\tthis.scrolledDuringInteraction = false;\n\t\t}\n\n\t\t// is a drag and drop just completed?\n\t\tlet removedAction: ListItemRemoved | null = null;\n\t\tif (this.virtualMouse.up && isDragging && this.drop !== null) {\n\t\t\t// TODO: detect null move and do not mark data as changed\n\t\t\t// is this the source?\n\t\t\tif (this.drag!.source === data) {\n\t\t\t\tconst index = this.drag!.index;\n\t\t\t\tconst element = data[index];\n\t\t\t\tconst canDragRemove = typeof interactionOptions === 'object' ?\n\t\t\t\t\tinteractionOptions.DndRemove(element) :\n\t\t\t\t\tisBitMaskSet(interactionOptions, ListInteractionOptions.DndRemove);\n\t\t\t\tif (canDragRemove) {\n\t\t\t\t\tconst removed = data.splice(index, 1)[0];\n\t\t\t\t\tremovedAction = new ListItemRemoved(removed, data, index);\n\t\t\t\t\tuserActions.push(removedAction);\n\t\t\t\t\tthis._dataChanged = true;\n\t\t\t\t\tthis.mustRepaint = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// is this the destination?\n\t\t\tif (this.drop.target === data) {\n\t\t\t\tconst index = this.drop.userData as number;\n\t\t\t\tconst element = this.drag!.data as T;\n\t\t\t\tdata.splice(index, 0, element);\n\t\t\t\tif (removedAction) {\n\t\t\t\t\tuserActions.pop();\n\t\t\t\t\tif (removedAction.index !== index) {\n\t\t\t\t\t\tuserActions.push(new ListItemMoved(element, data, removedAction.index, index));\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tuserActions.push(new ListItemAdded(element, data, index));\n\t\t\t\t}\n\t\t\t\tthis._dataChanged = true;\n\t\t\t\tthis.mustRepaint = true;\n\t\t\t}\n\t\t}\n\n\t\t// return the list's status\n\t\treturn {\n\t\t\tisBeingScrolled,\n\t\t\ttooltip,\n\t\t\tuserActions\n\t\t};\n\t}\n\n\t/**\n\t * Return the physical position of an element in the list.\n\t * @param x - The x-position on canvas.\n\t * @param y - The y-position on canvas.\n\t * @param length - The length of the list on screen, either its width or height depending on direction. Pass null to get from element artist.\n\t * @param breadth - The breadth of the list on screen, either its height or width depending on direction. Pass null to get from element artist.\n\t * @param data - The list content.\n\t * @param index - The index of the element.\n\t * @param elementArtist - The artist to draw the list elements.\n\t * @param displayOptions - Display options (direction, spacing and margins, position of scrollbars)\n\t * @param canDropOthers - Whether the list can accept elements from other lists.\n\t * @returns the position of the start of the element\n\t */\n\tlistElementPosition(x: number, y: number, length: number | null, breadth: number | null,\n\t\tdata: T[],\n\t\tindex: number,\n\t\telementArtist: ListElementArtist,\n\t\tdisplayOptions: ListDisplayOptions,\n\t\tcanDropOthers = false\n\t) {\n\t\t// display options unpacking\n\t\tconst displayOptionWithDefault =\n\t\t\t(\n\t\t\t\tproperty: K,\n\t\t\t\tdef: NonNullable):\n\t\t\tNonNullable =>\n\t\t\t\tgetDisplayOptionWithDefault(displayOptions, property, def)\n\t\t;\n\t\tconst direction = displayOptionWithDefault('direction', Direction.Default);\n\t\tconst isHorizontal = !isBitMaskSet(direction, Direction.Vertical);\n\t\tconst isRightToLeft = isBitMaskSet(direction, Direction.RightToLeft);\n\t\tconst elementSpacing = displayOptionWithDefault('elementSpacing', 16);\n\t\tconst margin = displayOptionWithDefault('margin', 16);\n\t\tconst scrollMargin = displayOptionWithDefault('scrollMargin', 0);\n\t\tconst extendSide = displayOptionWithDefault('extendSide', ListSide.Tail);\n\t\tconst insertFront = extendSide === ListSide.Front;\n\t\tassert(!(insertFront && isRightToLeft), 'insert front with right to left is not supported yet');\n\n\t\tconst listShiftForInsertFront = insertFront && canDropOthers;\n\n\t\t// helper functions for layout, converting between logical (orientation independent)\n\t\t// physical and (orientation dependant) coordinates\n\t\t// physical to logical\n\t\tconst logicalXY = (_x = x, _y = y) => (isHorizontal ? [_x, _y] : [_y, _x]) as [number, number];\n\t\t// local logical coordinates\n\t\tlet [drawX, drawY] = logicalXY();\n\t\t// logical to physical\n\t\tconst physicalV2 = (_x = drawX, _y = drawY) => isHorizontal ? new Vector2(_x, _y) : new Vector2(_y, _x);\n\n\t\t// The list drawing logic assumes the list is horizontal, if it is vertical,\n\t\t// we have to exchange coordinates back and forth.\n\t\tconst [elementWidth, elementHeight] = logicalXY(elementArtist.width, elementArtist.height);\n\n\t\t// center on breadth\n\t\tbreadth = breadth !== null ? breadth : elementHeight;\n\t\tdrawY += (breadth - elementHeight) / 2 | 0;\n\n\t\t// compute dimensions\n\t\tconst deltaElementWidth = elementWidth + elementSpacing;\n\t\tconst dropElementCount = canDropOthers ? data.length + 1 : data.length;\n\t\tconst dropAreaIdealWidth = dropElementCount * deltaElementWidth - elementSpacing + 2 * (margin + scrollMargin);\n\t\tlength = length !== null ? length : dropAreaIdealWidth;\n\t\tconst dropAreaLimitedWidth = Math.min(dropAreaIdealWidth, length);\n\t\tconst needsScroll = dropAreaIdealWidth > dropAreaLimitedWidth;\n\n\t\t// scroll position\n\t\tlet scrollPos = 0;\n\t\tif (needsScroll) {\n\t\t\tconst scrollStates = this.scrollStates.get(data);\n\t\t\tif (scrollStates !== undefined) {\n\t\t\t\tscrollPos = scrollStates[0];\n\t\t\t}\n\t\t} else {\n\t\t\t// center\n\t\t\tscrollPos = -(length - dropAreaIdealWidth) / 2 | 0;\n\t\t}\n\t\t// implement margin by shifting scroll\n\t\tscrollPos -= margin + scrollMargin;\n\t\t// shift drawing according to scroll\n\t\tdrawX -= scrollPos;\n\n\t\t// if right to left, start from the right\n\t\tdrawX += isRightToLeft ? dropAreaLimitedWidth - elementWidth : 0;\n\t\tconst dirFactor = isRightToLeft ? -1 : 1;\n\n\t\t// compute position\n\t\tdrawX += (deltaElementWidth * dirFactor) * index;\n\t\tif (listShiftForInsertFront) {\n\t\t\tdrawX += elementWidth + elementSpacing;\n\t\t}\n\n\t\treturn physicalV2();\n\t}\n\n\t/**\n\t * A drop target widget.\n\t * If the current drag type matches artist and mouse is over area, clear drop target.\n\t * @param output - The display list into which the drawn commands are pushed.\n\t * @param x - The x-position on canvas.\n\t * @param y - The y-position on canvas.\n\t * @param artist - The artist to draw the target.\n\t */\n\tdropTarget(output: DisplayList, x: number, y: number, width: number, height: number, artist: DropTargetArtist): void {\n\t\tif (this.drag !== null && this.drag.dragging && artist.types.indexOf(this.drag.artist.type) > -1) {\n\t\t\tif (this.virtualMouse.curPos.isInRect(x, y, width, height)) {\n\t\t\t\tif (this.drop) {\n\t\t\t\t\tthis.drop.target = null;\n\t\t\t\t} else {\n\t\t\t\t\tthis.drop = new DropTo(null);\n\t\t\t\t}\n\t\t\t\tthis.nextDrop = this.drop;\n\t\t\t\tartist.paintHovering(this, output, x, y, width, height, this.drag.artist.type, this.drag.data);\n\t\t\t} else {\n\t\t\t\tartist.paintDragging(this, output, x, y, width, height, this.drag.artist.type, this.drag.data);\n\t\t\t}\n\t\t} else {\n\t\t\tartist.paintIdle(this, output, x, y, width, height);\n\t\t}\n\t}\n\n\t/**\n\t * Paint the currently-dragged content, if any.\n\t */\n\tpaintDrag(): void {\n\t\tif (this.drag !== null && this.drag.dragging) {\n\t\t\tthis.drag.artist.paintDragContent(this, this.output[DisplayOutput.Overlay], this.virtualMouse.curPos.x, this.virtualMouse.curPos.y, this.drag.data, this.drag, this.drop);\n\t\t}\n\t}\n\n\t/**\n\t * Update the canvas' HTML tooltip, if it is different than the current one\n\t * @param newTooltip new tooltip\n\t */\n\tupdateTooltip(newTooltip: OptionalTooltip) {\n\t\tif (newTooltip !== this.oldTooltip) {\n\t\t\tif (newTooltip !== null) {\n\t\t\t\tthis.canvas.setAttribute('title', newTooltip);\n\t\t\t} else {\n\t\t\t\tthis.canvas.removeAttribute('title');\n\t\t\t}\n\t\t\tthis.oldTooltip = newTooltip;\n\t\t}\n\t}\n}\n\n// support functions\n\nfunction getDisplayOptionWithDefault(displayOptions: ListDisplayOptions, property: K, def: NonNullable): NonNullable {\n\tconst value = displayOptions[property];\n\tif (value !== undefined && value !== null) {\n\t\treturn value;\n\t} else {\n\t\treturn def;\n\t}\n}\n","/**\n * Limits for the different plans\n * @module limits\n * @preferred\n */\n/** comment to work-around limitation of typedoc module plugin */\n\n// Copyright 2018-2024 Enlightware GmbH, Switzerland\n\nimport { qsT } from 'translator/translator';\nimport { iterConstFixedSizeArray } from 'utils/array-types';\n\nconst LimitNamesAndUserText = {\n\t'ObjectTypesPerGame': qsT('object types'),\n\t'ObjectInstancesPerLevel': qsT('objects in the level'),\n\t'RulesPerObjectType': qsT('rules per object type'),\n\t'MaxConditionsPerRow': qsT('conditions per row'),\n\t'MaxActionsPerRow': qsT('actions per row'),\n\t'Dialogs': qsT('dialogs'),\n\t'Variables': qsT('variables'),\n\t'Sounds': qsT('sounds'),\n\t'ImageSize': 'image size', // text is not translated because it is never shown to the user\n} as const;\n\nexport const LimitNames = Object.keys(LimitNamesAndUserText) as LimitName[];\nexport type LimitName = keyof typeof LimitNamesAndUserText;\n\nexport type Limits = {\n\t[_ in LimitName]: number;\n};\n\nexport function toLimitName(givenName?: string): LimitName | undefined {\n\tlet limit: LimitName | undefined;\n\titerConstFixedSizeArray(LimitNames, (limitName) => {\n\t\tif (limitName === givenName) {\n\t\t\tlimit = limitName;\n\t\t}\n\t});\n\treturn limit;\n}\n\nexport function getLimitUserText(limit: LimitName) {\n\treturn LimitNamesAndUserText[limit];\n}\n","/**\n * @module math\n */\n/** comment to work-around limitation of typedoc module plugin */\n\n// Copyright 2018-2024 Enlightware GmbH, Switzerland\n\nimport { assert, assertNonNull } from 'utils/assert';\nimport { Vector2, SimilarityTransform } from './linalg';\n\nexport interface Margin {\n\ttop: number,\n\tright: number,\n\tbottom: number,\n\tleft: number,\n}\n\nexport class Rect {\n\ttopLeft: Vector2;\n\tsize: Vector2;\n\n\tconstructor(x: number, y: number, width: number, height: number) {\n\t\tthis.topLeft = new Vector2(x, y);\n\t\tthis.size = new Vector2(width, height);\n\t}\n\n\tstatic fromTopLeftAndSize(topLeft: Vector2, size: Vector2 | number) {\n\t\tconst w = size instanceof Vector2 ? size.x : size;\n\t\tconst h = size instanceof Vector2 ? size.y : size;\n\t\treturn new Rect(topLeft.x, topLeft.y, w, h);\n\t}\n\n\tstatic fromCenterAndSize(center: Vector2, size: Vector2 | number) {\n\t\tconst w = size instanceof Vector2 ? size.x : size;\n\t\tconst h = size instanceof Vector2 ? size.y : size;\n\t\treturn new Rect(center.x - w * 0.5, center.y - h * 0.5, w, h);\n\t}\n\n\tstatic fromCenterAndHalfSize(center: Vector2, halfSize: Vector2 | number) {\n\t\tconst halfW = halfSize instanceof Vector2 ? halfSize.x : halfSize;\n\t\tconst halfH = halfSize instanceof Vector2 ? halfSize.y : halfSize;\n\t\treturn new Rect(center.x - halfW, center.y - halfH, halfW * 2, halfH * 2);\n\t}\n\n\tstatic fromExtremePoints(extreme1: Vector2, extreme2: Vector2) {\n\t\tconst lowX = Math.min(extreme1.x, extreme2.x);\n\t\tconst lowY = Math.min(extreme1.y, extreme2.y);\n\t\tconst highX = Math.max(extreme1.x, extreme2.x);\n\t\tconst highY = Math.max(extreme1.y, extreme2.y);\n\t\treturn new Rect(lowX, lowY, highX - lowX, highY - lowY);\n\t}\n\n\tstatic fromPoints(points: Vector2[]) {\n\t\ttype Extremes = [number, number, number, number];\n\t\tconst optionalExtremes = (points.reduce((acc: null | Extremes, point) => {\n\t\t\tconst pX = point.x;\n\t\t\tconst pY = point.y;\n\t\t\tif (acc === null) {\n\t\t\t\treturn [pX, pY, pX, pY] as Extremes;\n\t\t\t} else {\n\t\t\t\treturn [\n\t\t\t\t\tMath.min(acc[0], pX),\n\t\t\t\t\tMath.min(acc[1], pY),\n\t\t\t\t\tMath.max(acc[2], pX),\n\t\t\t\t\tMath.max(acc[3], pY)\n\t\t\t\t] as Extremes;\n\t\t\t}\n\t\t}, null));\n\t\tassertNonNull(optionalExtremes, 'getting a rectangle from an empty list of points');\n\t\tconst [lowX, lowY, highX, highY] = optionalExtremes;\n\t\treturn new Rect(lowX, lowY, highX - lowX, highY - lowY);\n\t}\n\n\tstatic fromPointsAsFloat32Array(points: Float32Array) {\n\t\tassert(points.length >= 2, 'must have at least one point');\n\t\tlet lowX = points[0]!;\n\t\tlet lowY = points[1]!;\n\t\tlet highX = lowX;\n\t\tlet highY = lowY;\n\t\tfor (let i = 2; i < points.length; i += 2) {\n\t\t\tlowX = Math.min(lowX, points[i]!);\n\t\t\thighX = Math.max(highX, points[i]!);\n\t\t\tlowY = Math.min(lowY, points[i + 1]!);\n\t\t\thighY = Math.max(highY, points[i + 1]!);\n\t\t}\n\t\treturn new Rect(lowX, lowY, highX - lowX, highY - lowY);\n\t}\n\n\tstatic fromTopLeftAndBottomRight(topLeft: Vector2, bottomRight: Vector2) {\n\t\tconst size = bottomRight.sub(topLeft);\n\t\treturn new Rect(topLeft.x, topLeft.y, size.x, size.y);\n\t}\n\n\tstatic fromDomRect(rect: DOMRectReadOnly) {\n\t\treturn new Rect(rect.x, rect.y, rect.width, rect.height);\n\t}\n\n\tstatic boundingRect(rects: Rect[]) {\n\t\treturn rects.reduce((prev, cur) => prev.union(cur));\n\t}\n\n\tstatic null() {\n\t\treturn new Rect(0, 0, 0, 0);\n\t}\n\n\tget topRight() {\n\t\treturn new Vector2(this.topLeft.x + this.size.x, this.topLeft.y);\n\t}\n\tget bottomLeft() {\n\t\treturn new Vector2(this.topLeft.x, this.topLeft.y + this.size.y);\n\t}\n\tget bottomRight() {\n\t\treturn this.topLeft.add(this.size);\n\t}\n\tset bottomRight(point: Vector2) {\n\t\tthis.size = point.sub(this.topLeft);\n\t}\n\tget center() {\n\t\treturn this.topLeft.add(this.size.multScalar(0.5));\n\t}\n\n\tget x() { return this.topLeft.x; }\n\tget y() { return this.topLeft.y; }\n\tget width() { return this.size.x; }\n\tget height() { return this.size.y; }\n\n\tget left() { return this.x; }\n\tget top() { return this.y; }\n\tget right() { return this.x + this.width; }\n\tget bottom() { return this.y + this.height; }\n\n\tget maxSide() {\n\t\treturn Math.max(this.width, this.height);\n\t}\n\n\tget maxAbsCoord() {\n\t\treturn Math.max(\n\t\t\tMath.abs(this.left),\n\t\t\tMath.abs(this.top),\n\t\t\tMath.abs(this.right),\n\t\t\tMath.abs(this.bottom)\n\t\t);\n\t}\n\n\tget extremePoints() {\n\t\treturn [this.topLeft, this.topRight, this.bottomRight, this.bottomLeft];\n\t}\n\n\tget edges() {\n\t\treturn [\n\t\t\t[this.topLeft, this.topRight],\n\t\t\t[this.topRight, this.bottomRight],\n\t\t\t[this.bottomRight, this.bottomLeft],\n\t\t\t[this.bottomLeft, this.topLeft]\n\t\t] as [Vector2, Vector2][];\n\t}\n\n\tisEqual(that: Rect) {\n\t\treturn this.topLeft.isEqual(that.topLeft) && this.size.isEqual(that.size);\n\t}\n\n\tcontains(point: Vector2) {\n\t\tconst bottomRight = this.bottomRight;\n\t\treturn point.x >= this.topLeft.x &&\n\t\t\t\tpoint.x < bottomRight.x &&\n\t\t\t\tpoint.y >= this.topLeft.y &&\n\t\t\t\tpoint.y < bottomRight.y;\n\t}\n\n\tcontainsRect(rect: Rect) {\n\t\treturn this.contains(rect.topLeft) && this.contains(rect.bottomRight);\n\t}\n\n\tintersectsRect(that: Rect) {\n\t\tif (that.x >= this.x + this.width) {\n\t\t\treturn false;\n\t\t}\n\t\tif (that.y >= this.y + this.height) {\n\t\t\treturn false;\n\t\t}\n\t\tif (this.x >= that.x + that.width) {\n\t\t\treturn false;\n\t\t}\n\t\tif (this.y >= that.y + that.height) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t}\n\n\tscale(factor: number) {\n\t\treturn Rect.fromTopLeftAndSize(\n\t\t\tthis.topLeft.multScalar(factor),\n\t\t\tthis.size.multScalar(factor)\n\t\t);\n\t}\n\n\tunion(that: Rect) {\n\t\treturn Rect.fromTopLeftAndBottomRight(\n\t\t\tthis.topLeft.min(that.topLeft),\n\t\t\tthis.bottomRight.max(that.bottomRight)\n\t\t);\n\t}\n\n\tintersection(that: Rect) {\n\t\tconst result = Rect.fromTopLeftAndBottomRight(\n\t\t\tthis.topLeft.max(that.topLeft),\n\t\t\tthis.bottomRight.min(that.bottomRight)\n\t\t);\n\t\tif (result.size.minimum() <= 0) {\n\t\t\treturn null;\n\t\t}\n\t\treturn result;\n\t}\n\n\ttransform(simtrafo: SimilarityTransform): [Vector2, Vector2, Vector2, Vector2] {\n\t\treturn [\n\t\t\tsimtrafo.apply(this.topLeft),\n\t\t\tsimtrafo.apply(this.topRight),\n\t\t\tsimtrafo.apply(this.bottomLeft),\n\t\t\tsimtrafo.apply(this.bottomRight)\n\t\t];\n\t}\n\n\ttransformAsAABB(simtrafo: SimilarityTransform) {\n\t\tif (simtrafo.rotationAngle === 0 && simtrafo.scaleFactor === 1) {\n\t\t\t// fast path for translation only\n\t\t\treturn Rect.fromTopLeftAndSize(this.topLeft.add(simtrafo.translation), this.size);\n\t\t} else {\n\t\t\t// generic path, transform corners and take bounding rectangle\n\t\t\treturn Rect.fromPoints(this.transform(simtrafo));\n\t\t}\n\t}\n\n\tboundingIntegerCoordRect() {\n\t\tconst bottomRight = this.bottomRight.ceil();\n\t\tconst topLeft = this.topLeft.floor();\n\t\tconst size = bottomRight.sub(topLeft);\n\t\treturn Rect.fromTopLeftAndSize(topLeft, size);\n\t}\n\n\tdilate(amount: number | Margin) {\n\t\treturn Rect.fromTopLeftAndBottomRight(\n\t\t\tthis.topLeft.sub(\n\t\t\t\ttypeof amount === 'number' ?\n\t\t\t\t\tnew Vector2(amount, amount) :\n\t\t\t\t\tnew Vector2(amount.left, amount.top)\n\t\t\t),\n\t\t\tthis.bottomRight.add(\n\t\t\t\ttypeof amount === 'number' ?\n\t\t\t\t\tnew Vector2(amount, amount) :\n\t\t\t\t\tnew Vector2(amount.right, amount.bottom)\n\t\t\t)\n\t\t);\n\t}\n\n\terode(amount: number | Margin) {\n\t\treturn this.dilate(\n\t\t\ttypeof amount === 'number' ?\n\t\t\t\t-amount :\n\t\t\t\t{\n\t\t\t\t\ttop: -amount.top,\n\t\t\t\t\tright: -amount.right,\n\t\t\t\t\tbottom: -amount.bottom,\n\t\t\t\t\tleft: -amount.left,\n\t\t\t\t}\n\t\t);\n\t}\n\n\tcenterScale(ratio: number) {\n\t\treturn Rect.fromCenterAndSize(this.center, this.size.multScalar(ratio));\n\t}\n\n\treplaceX(x: number) {\n\t\treturn new Rect(x, this.y, this.width, this.height);\n\t}\n\n\treplaceY(y: number) {\n\t\treturn new Rect(this.x, y, this.width, this.height);\n\t}\n\n\treplaceWidth(width: number) {\n\t\treturn new Rect(this.x, this.y, width, this.height);\n\t}\n\n\treplaceHeight(height: number) {\n\t\treturn new Rect(this.x, this.y, this.width, height);\n\t}\n\n\ttoString() {\n\t\treturn `Rect(${this.x}, ${this.y}, ${this.width}, ${this.height})`;\n\t}\n}\n\nexport function calcLeftNormalOfArrow(from: Vector2, to: Vector2) {\n\treturn to.sub(from).normalized().rotate90deg();\n}\n\nexport function projectOntoHalfSpace(p: Vector2, boundaryPoint: Vector2, normal: Vector2) {\n\tconst d = Math.max(p.sub(boundaryPoint).dot(normal), 0);\n\treturn d > 0 ? p.sub(normal.multScalar(d)) : p;\n}\n\nexport function projectOntoArrowRightHalfSpace(p: Vector2, from: Vector2, to: Vector2) {\n\treturn projectOntoHalfSpace(p, from, calcLeftNormalOfArrow(from, to));\n}\n\nexport function segmentsIntersect(first: [Vector2, Vector2], second: [Vector2, Vector2]) {\n\tconst A = first[0];\n\tconst B = first[1];\n\tconst C = second[0];\n\tconst D = second[1];\n\n\t// Compute vectors\n\tconst AB = B.sub(A);\n\tconst AC = C.sub(A);\n\tconst AD = D.sub(A);\n\tconst CD = D.sub(C);\n\tconst CA = A.sub(C);\n\tconst CB = B.sub(C);\n\n\t// Check cross products for intersection\n\tconst cross1 = AB.cross(AC);\n\tconst cross2 = AB.cross(AD);\n\tconst cross3 = CD.cross(CA);\n\tconst cross4 = CD.cross(CB);\n\n\t// Segments intersect if they straddle each other's endpoints\n\tconst straddle1 = cross1 * cross2 < 0;\n\tconst straddle2 = cross3 * cross4 < 0;\n\n\treturn straddle1 && straddle2;\n}","/**\n * @module utils\n */\n/** comment to work-around limitation of typedoc module plugin */\n\n// Copyright 2018-2024 Enlightware GmbH, Switzerland\n\nimport { dynamicCast, nonnull } from './types';\nimport { createOffscreenCanvasAnd2DContext } from './canvas';\nimport { AnyCanvas, AnyCanvasRenderingContext2D } from 'imgui/imgui-types';\n\nexport function imageDataToCanvas(imageData: ImageData) {\n\tconst { canvas, ctx } = createOffscreenCanvasAnd2DContext(imageData.width, imageData.height);\n\tctx.putImageData(imageData, 0, 0);\n\treturn canvas;\n}\n\nexport function canvasToImageData(canvas: AnyCanvas) {\n\t// The \"as\" is to work around buggy typescript dependency tracking between the 2d argument and the return type\n\tconst ctx = nonnull(canvas.getContext('2d')) as AnyCanvasRenderingContext2D;\n\treturn ctx.getImageData(0, 0, canvas.width, canvas.height);\n}\n\nexport function anyErrorAsString(e: any): string {\n\treturn dynamicCast(Error, e)?.message ?? String(e);\n}","/**\n * @module utils\n */\n/** comment to work-around limitation of typedoc module plugin */\n\n// Copyright 2018-2024 Enlightware GmbH, Switzerland\n\nimport { assert } from './assert';\n\nexport function randUInt(range: number) {\n\tassert(range !== 0);\n\treturn Math.floor(Math.random() * Math.floor(range));\n}\n\n/// Inclusive integer range\nexport function randIntInclusiveRange(min: number, max: number) {\n\tconst range = max - min + 1;\n\treturn min + randUInt(range);\n}\n\nexport function randPositiveFloat(range: number) {\n\treturn Math.random() * range;\n}\n\nexport function randFloatRange(min: number, max: number) {\n\tconst delta = max - min;\n\treturn min + randPositiveFloat(delta);\n}\n\nexport function randBoolean() {\n\treturn randUInt(2) === 0;\n}\n\nexport function randFloatAngle() {\n\treturn randPositiveFloat(Math.PI * 2);\n}\n\nexport function randUInt8() {\n\treturn randUInt(256);\n}\n\nexport function randInt8() {\n\treturn randUInt(256) - 128;\n}\n\nexport function randUInt16() {\n\treturn randUInt(65536);\n}\n\nexport function randInt16() {\n\treturn randUInt(65536) - 32768;\n}\n\nexport function randFixed88() {\n\treturn randInt16() / 256;\n}\n\nexport function randUnitInclusive8() {\n\treturn randUInt(256) / 255;\n}\n\nexport function randP(pSelect: number) {\n\treturn Math.random() < pSelect;\n}\n\nexport function randElement(elements: T[]) {\n\tassert(elements.length !== 0);\n\treturn elements[randUInt(elements.length)]!;\n}\n\nexport function randSet(elements: T[], pSelect = 0.5): Set {\n\tconst result: Set = new Set();\n\tfor (const element of elements) {\n\t\tif (Math.random() < pSelect) {\n\t\t\tresult.add(element);\n\t\t}\n\t}\n\treturn result;\n}\n\nexport function randString(length: number) {\n\treturn [...Array(length)].map(_ => randUInt(36).toString(36)).join('');\n}","/**\n * @module utils\n */\n/** comment to work-around limitation of typedoc module plugin */\n\n// Copyright 2018-2024 Enlightware GmbH, Switzerland\n\nimport { nonnull } from './types';\n\nexport function isInStringUnion(unionValues: T, value: string): value is T[number] {\n\treturn unionValues.includes(value);\n}\n\nexport function dynamicStringUnionCast(unionValues: T, value: string): T[number] | null {\n\treturn isInStringUnion(unionValues, value) ? value : null;\n}\n\nexport function stringUnionCast(unionValues: T, value: string): T[number] {\n\treturn nonnull(dynamicStringUnionCast(unionValues, value));\n}","/**\n * @module vpl\n */\n/** comment to work-around limitation of typedoc module plugin */\n\n// Copyright 2018-2024 Enlightware GmbH, Switzerland\n\nimport { Block, BlockKind, EffectDefs, OuterUserContext } from './block';\nimport { assert, assertBoolean, assertMemberArrayEqualM, assertMemberEqual, assertMemberEqualM, assertNonNegativeInteger } from 'utils/assert';\nimport { defined, nonnull } from 'utils/types';\nimport { qsT, qsTr } from 'translator/translator';\nimport { forEach } from 'lodash-es';\nimport { Not, SpacedAnd } from 'translator/common-texts';\n\ninterface HasBlock, ConfigCtx> {\n\tblock: Block;\n}\n\n/** A condition block and whether its test is inverted */\nexport class Condition, ConfigCtx> {\n\tconstructor(public block: Block, public inverted = false) {\n\t}\n\n\tclone(): Condition {\n\t\treturn new Condition(this.block.clone(), this.inverted);\n\t}\n\n\tassertEqual(that: Condition, ctx: string) {\n\t\tassertMemberEqualM(this, that, 'block', ctx);\n\t\tassertMemberEqual(this, that, 'inverted', ctx);\n\t}\n\n\tvalidate() {\n\t\tthis.block.validate();\n\t\tassertBoolean(this.inverted, 'inverted');\n\t}\n};\n\n/** An action block */\nexport class Action, ConfigCtx> {\n\tconstructor(public block: Block) {\n\t}\n\n\tclone(): Action {\n\t\treturn new Action(this.block.clone());\n\t}\n\n\tassertEqual(that: Action, ctx: string) {\n\t\tassertMemberEqualM(this, that, 'block', ctx);\n\t}\n\n\tvalidate() {\n\t\tthis.block.validate();\n\t}\n};\n\nexport type EffectSuppressedBy = [number, (keyof Effects)[]];\n\nexport const enum RowFormatPart {\n\tIntro,\n\tGenericBlock,\n\tNotCondition,\n\tCondition,\n\tAndCondition,\n\tCenterSeparator,\n\tAction,\n\tAndAction,\n}\n\nexport type RowFormatAddTextCB = (text: string, part: RowFormatPart, instant: boolean, continuous: boolean) => void;\n\nexport class Row, ConfigCtx> {\n\tconstructor(\n\t\tpublic conditions: Condition[] = [],\n\t\tpublic actions: Action[] = [],\n\t\t/** whether the row itself, but not its elements, is locked in the editor */\n\t\tpublic movementLocked = false,\n\t\tpublic conditionsExtendLocked = false,\n\t\tpublic actionsExtendLocked = false\n\t)\n\t{\n\t}\n\n\tclone(): Row {\n\t\treturn new Row(\n\t\t\tthis.conditions.map((condition) => condition.clone()),\n\t\t\tthis.actions.map((action) => action.clone()),\n\t\t\tthis.movementLocked,\n\t\t\tthis.conditionsExtendLocked,\n\t\t\tthis.actionsExtendLocked\n\t\t);\n\t}\n\n\tisEmpty() {\n\t\treturn this.conditions.length === 0 && this.actions.length === 0;\n\t}\n\n\tisInit() {\n\t\treturn this.conditions.every(\n\t\t\t(condition) =>\n\t\t\t\tcondition.block.isGeneric ||\n\t\t\t\t(condition.block.isInit && !condition.inverted)\n\t\t);\n\t}\n\n\tformat(summary: boolean, addText: RowFormatAddTextCB, userContext: OuterCtx | null) {\n\t\tconst conditions = this.conditions;\n\t\tconst actions = this.actions;\n\n\t\t// what kind of action block do we have?\n\t\tconst instantCount = actions.filter((action) => action.block.isInstantaneousAction).length;\n\t\tconst continuousCount = actions.filter((action) => action.block.isContinuousAction).length;\n\t\tconst genericCount = actions.length - instantCount - continuousCount;\n\n\t\t// conditions\n\t\tconst noCondition = conditions.length === 0;\n\t\tif (noCondition) {\n\t\t\taddText(qsT('Continuously'), RowFormatPart.Intro, false, true);\n\t\t\taddText(qsT('When created'), RowFormatPart.Intro, true, false);\n\t\t} else {\n\t\t\taddText(qsT('When '), RowFormatPart.Intro, true, false);\n\t\t\taddText(qsT('While '), RowFormatPart.Intro, false, true);\n\t\t\tforEach(conditions, (condition, i) => {\n\t\t\t\tif (condition.inverted) {\n\t\t\t\t\taddText(Not + ' ', RowFormatPart.NotCondition, true, true);\n\t\t\t\t}\n\t\t\t\tconst prevData = conditions[i - 1];\n\t\t\t\tconst valueIn = prevData !== undefined && prevData.block.outputValuePossible;\n\t\t\t\tconst nextData = conditions[i + 1];\n\t\t\t\tconst valueOut = nextData !== undefined && nextData.block.inputValuePossible;\n\t\t\t\tconst block = condition.block;\n\t\t\t\tconst text = summary ?\n\t\t\t\t\tblock.summaryText(userContext, valueIn, valueOut) :\n\t\t\t\t\tblock.detailedText(userContext, valueIn, valueOut, false);\n\t\t\t\tconst blockKind = block.kind === BlockKind.Generic ? RowFormatPart.GenericBlock : RowFormatPart.Condition;\n\t\t\t\taddText(text, blockKind, true, true);\n\t\t\t\tif (i < conditions.length - 1) {\n\t\t\t\t\taddText(' & ', RowFormatPart.AndCondition, true, true);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\t// center\n\t\taddText(' : ', RowFormatPart.CenterSeparator, true, true);\n\n\t\t// actions\n\t\tif (actions.length === 0) {\n\t\t\taddText(qsT('no action'), RowFormatPart.Action, true, true);\n\t\t} else {\n\t\t\tconst seenOfKind: [number, number] = [0, 0];\n\t\t\tconst countOfKind: [number, number] = [instantCount + genericCount, continuousCount + genericCount];\n\t\t\tactions.forEach((action, i) => {\n\t\t\t\tconst prevData = actions[i - 1]?.block;\n\t\t\t\tconst valueIn = prevData !== undefined && prevData.outputValuePossible;\n\t\t\t\tconst nextData = actions[i + 1]?.block;\n\t\t\t\tconst valueOut = nextData !== undefined && nextData.inputValuePossible;\n\t\t\t\tconst block = action.block;\n\t\t\t\tconst text = summary ?\n\t\t\t\t\tblock.summaryText(userContext, valueIn, valueOut) :\n\t\t\t\t\tblock.detailedText(userContext, valueIn, valueOut, false);\n\t\t\t\tconst blockKind = block.kind === BlockKind.Generic ? RowFormatPart.GenericBlock : RowFormatPart.Action;\n\t\t\t\taddText(text, blockKind, block.isInstantaneousAction, block.isContinuousAction);\n\t\t\t\tif (block.kind !== BlockKind.Generic) {\n\t\t\t\t\tconst kind = block.kind - 1;\n\t\t\t\t\tassert(kind === 0 || kind === 1, 'block.kind');\n\t\t\t\t\tseenOfKind[kind] += 1;\n\t\t\t\t} else {\n\t\t\t\t\tseenOfKind[0] += 1;\n\t\t\t\t\tseenOfKind[1] += 1;\n\t\t\t\t}\n\t\t\t\tif (i + 1 !== actions.length) {\n\t\t\t\t\tconst instantAnd = (block.isInstantaneousAction || block.isGeneric) && seenOfKind[0] < countOfKind[0];\n\t\t\t\t\tconst continuousAnd = (block.isContinuousAction || block.isGeneric) && seenOfKind[1] < countOfKind[1];\n\t\t\t\t\taddText(', ', RowFormatPart.AndAction, instantAnd, continuousAnd);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\teffectSuppressedActions(configCtx: ConfigCtx | null): [number, EffectSuppressedBy[]][] {\n\t\t// type and helpers\n\t\ttype EffectSet = Set;\n\t\t// Extend set with elements\n\t\tconst extend = (elements: readonly (keyof Effects)[], set: EffectSet) => {\n\t\t\tfor (const element of elements) {\n\t\t\t\tset.add(element);\n\t\t\t}\n\t\t};\n\t\t// Remove elements from set and add them to bys\n\t\tconst removeAndExtendBys = (elements: readonly (keyof Effects)[], set: EffectSet, bys: EffectSuppressedBy[], index: number) => {\n\t\t\tconst removed: (keyof Effects)[] = [];\n\t\t\tfor (const element of elements) {\n\t\t\t\tif (set.has(element)) {\n\t\t\t\t\tset.delete(element);\n\t\t\t\t\tremoved.push(element);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (removed.length > 0) {\n\t\t\t\tbys.push([index, removed]);\n\t\t\t}\n\t\t};\n\t\tconst frozen: Map = new Map();\n\t\t// Filter out effects that are frozen and collect these in suppressedBys\n\t\tconst filterFrozen = (effects: readonly (keyof Effects)[], suppressedBys: EffectSuppressedBy[]) => {\n\t\t\treturn effects.filter((effect) => {\n\t\t\t\tconst frozenBy = frozen.get(effect);\n\t\t\t\tif (frozenBy !== undefined) {\n\t\t\t\t\tfor (const [index, bys] of suppressedBys) {\n\t\t\t\t\t\tif (index === frozenBy) {\n\t\t\t\t\t\t\tbys.push(effect);\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tsuppressedBys.push([frozenBy, [effect]]);\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t});\n\t\t};\n\n\t\t// compute freezes and overrides\n\t\tconst possibleSuppressed: [number, EffectSet, EffectSuppressedBy[]][] = [];\n\t\tthis.actions.forEach((action, index) => {\n\t\t\tconst effects = action.block.actionEffects(configCtx);\n\t\t\t// do we cancel anything that is not frozen?\n\t\t\tif (effects.overrides) {\n\t\t\t\tconst overrides = effects.overrides.filter((effect) => !frozen.has(effect));\n\t\t\t\tfor (const [_, otherEffects, bys] of possibleSuppressed) {\n\t\t\t\t\tremoveAndExtendBys(overrides, otherEffects, bys, index);\n\t\t\t\t}\n\t\t\t}\n\t\t\t// add ourselves\n\t\t\tconst suppressedBys: EffectSuppressedBy[] = [];\n\t\t\tconst ours: EffectSet = new Set();\n\t\t\tif (effects.freezes) {\n\t\t\t\tconst ourFrozen = filterFrozen(effects.freezes, suppressedBys);\n\t\t\t\tfor (const [_, otherEffects, bys] of possibleSuppressed) {\n\t\t\t\t\tremoveAndExtendBys(ourFrozen, otherEffects, bys, index);\n\t\t\t\t}\n\t\t\t\tfor (const effect of ourFrozen) {\n\t\t\t\t\tfrozen.set(effect, index);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (effects.modifies) {\n\t\t\t\textend(filterFrozen(effects.modifies, suppressedBys), ours);\n\t\t\t}\n\t\t\tif (effects.overrides) {\n\t\t\t\textend(filterFrozen(effects.overrides, suppressedBys), ours);\n\t\t\t}\n\t\t\tif ((ours.size > 0 || suppressedBys.length > 0) && action.block.userModifiable) {\n\t\t\t\tpossibleSuppressed.push([index, ours, suppressedBys]);\n\t\t\t}\n\t\t});\n\n\t\t// keep only blocks whose effects that have been fully suppressed\n\t\treturn possibleSuppressed\n\t\t\t.filter((entry) => entry[1].size === 0)\n\t\t\t.map(([index, _, suppressedBys]) => [index, suppressedBys]);\n\t}\n\n\tissues(userContext: OuterCtx | null, effectDefs: Effects) {\n\t\tconst issues: string[] = [];\n\t\t// rule-level configuration issue\n\t\tif (this.conditions.length > 0 && this.actions.length === 0) {\n\t\t\tissues.push(\n\t\t\t\tqsT('This rule has no action, and thus has no effect.') + '
' +\n\t\t\t\tqsT('Solution: add one or more actions.')\n\t\t\t);\n\t\t}\n\t\t// blocks needing configuration\n\t\tconst configContext = userContext?.configContext() ?? null;\n\t\tconst clickHelpText = qsTr('Solution: Press on the block and %1');\n\t\tfor (const [index, condition] of this.conditions.entries()) {\n\t\t\tconst block = condition.block;\n\t\t\tif (!block.userModifiable) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (block.needsConfiguration(configContext)) {\n\t\t\t\tissues.push(qsTr('Condition #%1 (%2) is always false.').args(index, block.name)\n\t\t\t\t\t+ '
' + clickHelpText.args(block.needsConfigurationFix(configContext)) + '.'\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (block.inputValueMandatory && !this.blockHasValueOut(this.conditions, index - 1)) {\n\t\t\t\tissues.push(qsTr('The input of condition #%1 (%2) must be connected.').args(index, block.name));\n\t\t\t}\n\t\t\tif (block.outputValueMandatory && !this.blockHasValueIn(this.conditions, index + 1)) {\n\t\t\t\tissues.push(qsTr('The output of condition #%1 (%2) must be connected.').args(index, block.name));\n\t\t\t}\n\t\t}\n\t\tfor (const [index, action] of this.actions.entries()) {\n\t\t\tconst block = action.block;\n\t\t\tif (!block.userModifiable) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (block.needsConfiguration(configContext)) {\n\t\t\t\tissues.push(qsTr('Action #%1 (%2) has no effect.').args(index, block.name)\n\t\t\t\t\t+ '
' + clickHelpText.args(block.needsConfigurationFix(configContext)) + '.'\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (block.inputValueMandatory && !this.blockHasValueOut(this.actions, index - 1)) {\n\t\t\t\tissues.push(qsTr('The input of action #%1 (%2) must be connected.').args(index, block.name));\n\t\t\t}\n\t\t\tif (block.outputValueMandatory && !this.blockHasValueIn(this.actions, index + 1)) {\n\t\t\t\tissues.push(qsTr('The output of action #%1 (%2) must be connected.').args(index, block.name));\n\t\t\t}\n\t\t}\n\t\t// action blocks having no effects in initial state\n\t\tif (this.isInit()) {\n\t\t\tfor (const [index, action] of this.actions.entries()) {\n\t\t\t\tconst block = action.block;\n\t\t\t\tif (!block.userModifiable) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (block.isEffectlessOnInit) {\n\t\t\t\t\tissues.push(qsTr('Action #%1 (%2) has no effect when used during initialisation.').args(index, block.name));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// effect suppression issues\n\t\tconst suppressedIssues = this.effectSuppressedActions(configContext);\n\t\tconst actionDetailedText = (index: number) => {\n\t\t\tconst action = defined(this.actions[index]);\n\t\t\tconst prevData = this.actions[index - 1];\n\t\t\tconst valueIn = prevData !== undefined && prevData.block.outputValuePossible;\n\t\t\tconst nextData = this.actions[index + 1];\n\t\t\tconst valueOut = nextData !== undefined && nextData.block.inputValuePossible;\n\t\t\treturn action.block.detailedText(userContext, valueIn, valueOut, false);\n\t\t};\n\t\tfor (const [index, bys] of suppressedIssues) {\n\t\t\tissues.push(\n\t\t\t\tqsTr('The effects of action #%1 (%2) have been cancelled by other actions.').args(index, actionDetailedText(index))\n\t\t\t\t+ '
' + qsTr('Solution: change this action (#%1) or one of the actions below:').args(index) + '
    '\n\t\t\t\t+ bys.map(\n\t\t\t\t\t([index, effects]) => '
  • ' + qsTr('#%1 (%2) that sets %3.').args(\n\t\t\t\t\t\tindex,\n\t\t\t\t\t\tactionDetailedText(index),\n\t\t\t\t\t\teffects.map((effect) => effectDefs[effect]).join(SpacedAnd)\n\t\t\t\t\t) + '
  • '\n\t\t\t\t).join('')\n\t\t\t\t+ '
'\n\t\t\t);\n\t\t}\n\t\treturn issues;\n\t}\n\n\tblockHasValueIn>(array: T[], index: number) {\n\t\tconst item = array[index];\n\t\treturn item !== undefined && item.block.inputValuePossible;\n\t}\n\n\tblockHasValueOut>(array: T[], index: number) {\n\t\tconst item = array[index];\n\t\treturn item !== undefined && item.block.outputValuePossible;\n\t}\n\n\t/**\n\t * Ensure that the integrity of the row, asserts if invalid\n\t */\n\tvalidate() {\n\t\tfor (const condition of this.conditions) {\n\t\t\tcondition.validate();\n\t\t}\n\t\tfor (const action of this.actions) {\n\t\t\taction.validate();\n\t\t}\n\t\tassertBoolean(this.movementLocked, 'movementLocked');\n\t\tassertBoolean(this.conditionsExtendLocked, 'conditionsExtendLocked');\n\t\tassertBoolean(this.actionsExtendLocked, 'actionsExtendLocked');\n\t}\n\n\t/**\n\t * Compare this to that, and aborts if they are different\n\t * @param that other to compare to\n\t * @param ctx debug context\n\t */\n\tassertEqual(that: Row, ctx: string) {\n\t\tassertMemberArrayEqualM(this, that, 'conditions', ctx);\n\t\tassertMemberArrayEqualM(this, that, 'actions', ctx);\n\t\tassertMemberEqual(this, that, 'movementLocked', ctx);\n\t\tassertMemberEqual(this, that, 'conditionsExtendLocked', ctx)\n\t\tassertMemberEqual(this, that, 'actionsExtendLocked', ctx)\n\t}\n}\n\nexport function castBlock, ConfigCtx>(data: unknown) {\n\treturn nonnull(dynamicCastBlock(data));\n}\n\nexport function dynamicCastBlock, ConfigCtx>(data: unknown): Block | null {\n\tif (data instanceof Condition) {\n\t\treturn data.block;\n\t} else if (data instanceof Action) {\n\t\treturn data.block;\n\t} else {\n\t\treturn null;\n\t}\n}\n","/**\n * @module vpl\n */\n/** comment to work-around limitation of typedoc module plugin */\n\n// Copyright 2018-2024 Enlightware GmbH, Switzerland\n\nexport const CanvasTextFamily = 'Roboto, Noto Sans Thai';\n\nexport function canvasTextFont(size: number, weight = 'normal') {\n\treturn `${weight} ${size}px ${CanvasTextFamily}`;\n}"],"names":["FlipText","OrientText","FlipBlock","flipX","flipY","relative","constructor","flipXOrFbFlip","lockState","super","this","validate","clone","name","summaryText","detailedTextIfConfigured","horizontally","vertically","args","horizontal","vertical","serialise","builder","createFlip","fbActionType","Flip","kind","getAbsoluteFlip","oldFlipX","oldFlipY","getMiniatureKey","actionEffects","modifies","overrides","execFns","Map","getCode","codeOrFb","code","ScriptActionBlock","continuous","scriptCtx","rebuildCompiler","action_block_script_compiler","createScriptAction","createString","ScriptAction","premium","assertEqual","that","ctx","AddAngularVelocityText","AddTorqueText","AngularSpeedBlock","amount","mode","intensityOrFbAction","inputValuePortPresence","_userContext","valueIn","modeText","dirText","createAddAngularVelocity","createAddAngularAcceleration","AddAngularVelocity","AddAngularAcceleration","AddVelocityText","AddForceText","SpeedBlock","vector","compatFixedMagnitude","vectorOrFbAction","modeOrFromVersion","x","y","relativeText","createAddVelocity","createAddAcceleration","AddVelocity","AddAcceleration","DefaultTransformPartsObject","translation","rotation","scaling","DefaultTransformPartsCamera","TeleportBlock","transform","transformComponentsBits","moveCamera","beacon","moveCameraOrFbTeleport","transformOrObjectTypes","target","transformComponents","toBeaconTransform","transformParts","userContext","self","thisObject","game","objectOfType","dx","translationX","dy","translationY","trTexts","doRotation","push","rotationDegrees","toFixed","doScaling","scaleFactor","doTranslation","length","what","join","objectTypes","startTeleport","addToBeaconTransform","addBeacon","addMoveCamera","addTransformParts","endTeleport","Teleport","_that","releaseReferencesToObjectType","objectType","beaconText","id","effects","components","AnimationIdleText","AnimWithIndexText","quotedAnimNameOrIndex","index","animName","fallbackExecFn","_compiler","_name","_input","FnMainNotFound","FnMainWrongSignature","ScriptAbstractBlock","execFn","input","output","compiler","compilationError","type","compile","setupCompiler","errors","undefined","map","error","text","mainSig","fn_signature_without_effects","get","validSigs","keys","outputValuePortPresence","len","split","detailedText","needsConfiguration","needsConfigurationFix","run","lastValue","logCtx","console","result","value","cont","e","renameVariable","oldName","newName","ScriptConditionBlock","condition_block_script_compiler","createScriptCondition","fbConditionType","ScriptCondition","ReadTextArg","ReadVariableText","ReadVariableBlock","address","addressOrFbVariable","createReadVariable","fbGenericType","ReadVariable","strokeShape","shape","color","lineWidth","dashed","Array","forEach","point","i","set","computeObjectTransform","object","worldToCanvas","after","pose","drawObjectInstance","ctxOrGUI","alpha","selected","outlined","clipRect","firstFrame","gui","guiSprite","renderCtx","addSprite","sprite","canvas","drawSprite","zeros","spriteTransformList","partFromPixelTransform","opacity","movementLocked","list","secondaryColor","fillShape","polygonShapeOrRadius","width","transformList","extent","intersectsRect","addDisplayAction","spriteTransform","globalAlpha","oldTransform","getTransform","translate","rotate","rotationAngle","scale","size","draw","setTransform","drawLevelObjects","worldToScreen","level","draggedObjects","selectedObjects","outlinedObject","editableLayers","layers","objects","layer","entries","layerAlpha","has","objectAlpha","transformedShape","polygonShape","white","setAlpha","areFloat32ArrayEqual","a","b","pointFloat32ArrayToString","points","s","FillRect","rect","fromRect","height","isEqual","other","toString","rgbaHexString","StrokeRect","dilate","FillCircle","center","radius","fromCenterAndHalfSize","fromScalar","StrokeCircle","LineListBuilder","count","Float32Array","startX","startY","endX","endY","DrawLineList","fromPointsAsFloat32Array","fromSegment","start","end","PointListBuilder","DrawLineStrip","FillConvexPolygon","DrawText","position","font","textSize","baseline","DrawSprite","fromTopLeftAndSize","TransformedList","listOrAction","innerRect","transformAsAABB","thisActions","getActions","thatActions","indent","Math","PI","ScrollMarkColor","ScrollBarColor","DragFrom","artist","delta","source","allowedDirection","data","dragging","explicitData","DropTo","userData","Pointer","_down","_up","_pressed","_shiftKey","_ctrlKey","_metaKey","_altKey","pressPos","lastPos","curPos","down","up","pressed","deltaPos","sub","motion","shiftKey","ctrlKey","metaKey","altKey","ctrlOrMetaKey","press","move","release","cancel","step","wasUp","UserAction","ButtonClicked","item","ListDropHintClicked","ListItemClicked","ListItemLongPressed","ListItemAdded","ListItemRemoved","ListItemMoved","from","to","UserActions","single","action","userActions","append","forFirstAction","callback","forEachAction","once","removeActionsOfType","splice","containsType","DragContentArtist","ListElementArtist","canClone","_element","MutableListElementArtist","isPointInDropHint","_px","_py","_x","_y","GUI","renderFunction","offscreen","drag","drop","nextDrop","touchIdentifier","virtualMouse","mouse","touches","deltaWheel","wheelModifiers","mustRepaint","renderScheduled","boundPerformRender","deltaT","currentT","invScale","renderContext","scrollStates","scrolledDuringInteraction","longPressData","longPressFired","oldTooltip","_dataChanged","externalCtrlPressed","getContext","WeakMap","performRender","bind","setupEvents","resizeCanvas","queue","mainOutput","overlayOutput","isDragging","isDraggingFromSource","dataChanged","forceDataChanged","mouseEvents","mouseEvent","eventName","toLowerCase","addEventListener","event","stopPropagation","wheelEvents","wheelEvent","touchEvents","touchEvent","preventDefault","mouseEventToModifiers","offsetParent","present","scheduleRender","handleDrag","norm2","DragThreshold","angle","cancelLongPress","handleCancelEvent","mouseDownEvent","scaledX","offsetX","scaledY","offsetY","mouseMoveEvent","mouseUpEvent","mouseLeaveEvent","scrollFactor","deltaMode","deltaY","touchStartEvent","touch","targetTouches","Element","getBoundingClientRect","pointer","localX","clientX","left","localY","clientY","top","identifier","touchMoveEvent","changedTouches","touchEndEvent","delete","touchCancelEvent","longPressTimeout","window","clearTimeout","requestAnimationFrame","t","begin","render","oldMustRepaint","wasDragging","button","isMouseOn","isPointIn","paintUserActions","tooltip","paint","clicked","breadth","elementArtist","interactionOptions","displayOptions","displayOptionWithDefault","property","def","getDisplayOptionWithDefault","direction","isHorizontal","isRightToLeft","elementSpacing","margin","scrollbarSide","scrollMarks","scrollMargin","insertFront","canDrop","DndDrop","canDropOthers","DndOthers","listShiftForInsertFront","logicalX","logicalY","logicalXY","drawX","drawY","physicalX","physicalY","physicalXY","elementWidth","elementHeight","mouseX","mouseY","deltaElementWidth","isListDragSource","dropAreaIdealWidth","dropAreaLimitedWidth","min","dropAreaPhysicalWidth","dropAreaPhysicalHeight","needsScroll","showScrollMarks","isMouseOnList","isInRect","scrollPos","scrollSpeed","initialScroll","deltaScroll","exp","abs","round","boundedScrollPos","canDropOnList","listPosX","dropIndex","trunc","max","dirFactor","element","canDrag","DndDrag","canClick","ClickDisabled","canLongPress","LongPressDisabled","isElementDragSource","isVirtualMouseOn","paintDropPreview","painterReturn","paintListElement","physicalV2","clonedElement","timer","setTimeout","markX","markY","j","px","py","shiftByOne","shiftX","paintDropHint","isBeingScrolled","scrollBarLength","scrollBarPos","scrollBarY","x1","y1","x2","y2","removedAction","DndRemove","removed","pop","listElementPosition","dropTarget","types","indexOf","paintHovering","paintDragging","paintIdle","paintDrag","paintDragContent","updateTooltip","newTooltip","setAttribute","removeAttribute","LimitNamesAndUserText","LimitNames","Object","toLimitName","givenName","limit","limitName","Rect","topLeft","w","h","fromCenterAndSize","halfSize","halfW","halfH","fromExtremePoints","extreme1","extreme2","lowX","lowY","highX","highY","fromPoints","optionalExtremes","reduce","acc","pX","pY","fromTopLeftAndBottomRight","bottomRight","fromDomRect","boundingRect","rects","prev","cur","union","topRight","bottomLeft","add","multScalar","right","bottom","maxSide","maxAbsCoord","extremePoints","edges","contains","containsRect","factor","intersection","minimum","simtrafo","apply","boundingIntegerCoordRect","ceil","floor","erode","centerScale","ratio","replaceX","replaceY","replaceWidth","replaceHeight","imageDataToCanvas","imageData","putImageData","canvasToImageData","getImageData","randUInt","range","random","randIntInclusiveRange","stringUnionCast","unionValues","includes","isInStringUnion","dynamicStringUnionCast","Condition","block","inverted","Action","Row","conditions","actions","conditionsExtendLocked","actionsExtendLocked","condition","isEmpty","isInit","every","isGeneric","format","summary","addText","instantCount","filter","isInstantaneousAction","continuousCount","isContinuousAction","genericCount","prevData","outputValuePossible","nextData","valueOut","inputValuePossible","blockKind","seenOfKind","countOfKind","instantAnd","continuousAnd","effectSuppressedActions","configCtx","extend","elements","removeAndExtendBys","bys","frozen","filterFrozen","suppressedBys","effect","frozenBy","possibleSuppressed","_","otherEffects","ours","Set","freezes","ourFrozen","userModifiable","entry","issues","effectDefs","configContext","clickHelpText","inputValueMandatory","blockHasValueOut","outputValueMandatory","blockHasValueIn","isEffectlessOnInit","suppressedIssues","actionDetailedText","array","CanvasTextFamily","canvasTextFont","weight"],"sourceRoot":""}