[{"data":1,"prerenderedAt":1439},["ShallowReactive",2],{"navigation":3,"reference-navigation":62,"\u002Fdocs\u002Fdefining-bundle-visuals":365,"\u002Fdocs\u002Fdefining-bundle-visuals-surround":1434},[4,22,26,30,34,38,42,46,50,54,58],{"title":5,"path":6,"stem":7,"children":8},"Bundle Developer","\u002Fdocs\u002Fbundle-developer","1.docs\u002F1.bundle-developer\u002Findex",[9,10,14,18],{"title":5,"path":6,"stem":7},{"title":11,"path":12,"stem":13},"Terminology","\u002Fdocs\u002Fbundle-developer\u002Fterminology","1.docs\u002F1.bundle-developer\u002F1.terminology",{"title":15,"path":16,"stem":17},"Prerequisites","\u002Fdocs\u002Fbundle-developer\u002Fprerequisites","1.docs\u002F1.bundle-developer\u002F2.prerequisites",{"title":19,"path":20,"stem":21},"Bundle Layout","\u002Fdocs\u002Fbundle-developer\u002Flayout","1.docs\u002F1.bundle-developer\u002F3.layout",{"title":23,"path":24,"stem":25},"Custom Registry Developer Guide","\u002Fdocs\u002Fcustom-registries","1.docs\u002Fcustom-registries",{"title":27,"path":28,"stem":29},"Defining Bundle Entities","\u002Fdocs\u002Fdefining-bundle-entities","1.docs\u002Fdefining-bundle-entities",{"title":31,"path":32,"stem":33},"Defining Bundle Sounds","\u002Fdocs\u002Fdefining-bundle-sounds","1.docs\u002Fdefining-bundle-sounds",{"title":35,"path":36,"stem":37},"Defining Bundle Tile Transitions","\u002Fdocs\u002Fdefining-bundle-tile-transitions","1.docs\u002Fdefining-bundle-tile-transitions",{"title":39,"path":40,"stem":41},"Defining Bundle Tiles","\u002Fdocs\u002Fdefining-bundle-tiles","1.docs\u002Fdefining-bundle-tiles",{"title":43,"path":44,"stem":45},"Defining Bundle Visuals","\u002Fdocs\u002Fdefining-bundle-visuals","1.docs\u002Fdefining-bundle-visuals",{"title":47,"path":48,"stem":49},"Bundle Event System Developer Guide","\u002Fdocs\u002Fevent-system","1.docs\u002Fevent-system",{"title":51,"path":52,"stem":53},"Getting Started with Selene Bundles","\u002Fdocs\u002Fgetting-started-bundles","1.docs\u002Fgetting-started-bundles",{"title":55,"path":56,"stem":57},"Making Resource Packs","\u002Fdocs\u002Fmaking-resource-packs","1.docs\u002Fmaking-resource-packs",{"title":59,"path":60,"stem":61},"Bundle Network API Developer Guide","\u002Fdocs\u002Fnetwork-apis","1.docs\u002Fnetwork-apis",[63,212,253],{"title":64,"path":65,"stem":66,"children":67,"page":121},"Modules","\u002Freference\u002Fmodules","2.reference\u002F1.modules",[68,122,167],{"title":69,"path":70,"stem":71,"children":72,"page":121},"Common","\u002Freference\u002Fmodules\u002Fcommon","2.reference\u002F1.modules\u002F1.common",[73,77,81,85,89,93,97,101,105,109,113,117],{"title":74,"path":75,"stem":76},"debug","\u002Freference\u002Fmodules\u002Fcommon\u002Fdebug","2.reference\u002F1.modules\u002F1.common\u002Fdebug",{"title":78,"path":79,"stem":80},"mathx","\u002Freference\u002Fmodules\u002Fcommon\u002Fmathx","2.reference\u002F1.modules\u002F1.common\u002Fmathx",{"title":82,"path":83,"stem":84},"os","\u002Freference\u002Fmodules\u002Fcommon\u002Fos","2.reference\u002F1.modules\u002F1.common\u002Fos",{"title":86,"path":87,"stem":88},"package","\u002Freference\u002Fmodules\u002Fcommon\u002Fpackage","2.reference\u002F1.modules\u002F1.common\u002Fpackage",{"title":90,"path":91,"stem":92},"selene.grid","\u002Freference\u002Fmodules\u002Fcommon\u002Fselene.grid","2.reference\u002F1.modules\u002F1.common\u002Fselene.grid",{"title":94,"path":95,"stem":96},"selene.http","\u002Freference\u002Fmodules\u002Fcommon\u002Fselene.http","2.reference\u002F1.modules\u002F1.common\u002Fselene.http",{"title":98,"path":99,"stem":100},"selene.i18n","\u002Freference\u002Fmodules\u002Fcommon\u002Fselene.i18n","2.reference\u002F1.modules\u002F1.common\u002Fselene.i18n",{"title":102,"path":103,"stem":104},"selene.registries","\u002Freference\u002Fmodules\u002Fcommon\u002Fselene.registries","2.reference\u002F1.modules\u002F1.common\u002Fselene.registries",{"title":106,"path":107,"stem":108},"selene.resources","\u002Freference\u002Fmodules\u002Fcommon\u002Fselene.resources","2.reference\u002F1.modules\u002F1.common\u002Fselene.resources",{"title":110,"path":111,"stem":112},"selene.schedules","\u002Freference\u002Fmodules\u002Fcommon\u002Fselene.schedules","2.reference\u002F1.modules\u002F1.common\u002Fselene.schedules",{"title":114,"path":115,"stem":116},"stringx","\u002Freference\u002Fmodules\u002Fcommon\u002Fstringx","2.reference\u002F1.modules\u002F1.common\u002Fstringx",{"title":118,"path":119,"stem":120},"tablex","\u002Freference\u002Fmodules\u002Fcommon\u002Ftablex","2.reference\u002F1.modules\u002F1.common\u002Ftablex",false,{"title":123,"path":124,"stem":125,"children":126,"page":121},"Server","\u002Freference\u002Fmodules\u002Fserver","2.reference\u002F1.modules\u002F2.server",[127,131,135,139,143,147,151,155,159,163],{"title":128,"path":129,"stem":130},"selene.attributes","\u002Freference\u002Fmodules\u002Fserver\u002Fselene.attributes","2.reference\u002F1.modules\u002F2.server\u002Fselene.attributes",{"title":132,"path":133,"stem":134},"selene.config","\u002Freference\u002Fmodules\u002Fserver\u002Fselene.config","2.reference\u002F1.modules\u002F2.server\u002Fselene.config",{"title":136,"path":137,"stem":138},"selene.dimensions","\u002Freference\u002Fmodules\u002Fserver\u002Fselene.dimensions","2.reference\u002F1.modules\u002F2.server\u002Fselene.dimensions",{"title":140,"path":141,"stem":142},"selene.entities","\u002Freference\u002Fmodules\u002Fserver\u002Fselene.entities","2.reference\u002F1.modules\u002F2.server\u002Fselene.entities",{"title":144,"path":145,"stem":146},"selene.map","\u002Freference\u002Fmodules\u002Fserver\u002Fselene.map","2.reference\u002F1.modules\u002F2.server\u002Fselene.map",{"title":148,"path":149,"stem":150},"selene.network","\u002Freference\u002Fmodules\u002Fserver\u002Fselene.network","2.reference\u002F1.modules\u002F2.server\u002Fselene.network",{"title":152,"path":153,"stem":154},"selene.players","\u002Freference\u002Fmodules\u002Fserver\u002Fselene.players","2.reference\u002F1.modules\u002F2.server\u002Fselene.players",{"title":156,"path":157,"stem":158},"selene.saves","\u002Freference\u002Fmodules\u002Fserver\u002Fselene.saves","2.reference\u002F1.modules\u002F2.server\u002Fselene.saves",{"title":160,"path":161,"stem":162},"selene.server","\u002Freference\u002Fmodules\u002Fserver\u002Fselene.server","2.reference\u002F1.modules\u002F2.server\u002Fselene.server",{"title":164,"path":165,"stem":166},"selene.sounds","\u002Freference\u002Fmodules\u002Fserver\u002Fselene.sounds","2.reference\u002F1.modules\u002F2.server\u002Fselene.sounds",{"title":168,"path":169,"stem":170,"children":171,"page":121},"Client","\u002Freference\u002Fmodules\u002Fclient","2.reference\u002F1.modules\u002F3.client",[172,176,179,183,187,190,194,197,200,204,208],{"title":173,"path":174,"stem":175},"selene.camera","\u002Freference\u002Fmodules\u002Fclient\u002Fselene.camera","2.reference\u002F1.modules\u002F3.client\u002Fselene.camera",{"title":140,"path":177,"stem":178},"\u002Freference\u002Fmodules\u002Fclient\u002Fselene.entities","2.reference\u002F1.modules\u002F3.client\u002Fselene.entities",{"title":180,"path":181,"stem":182},"selene.game","\u002Freference\u002Fmodules\u002Fclient\u002Fselene.game","2.reference\u002F1.modules\u002F3.client\u002Fselene.game",{"title":184,"path":185,"stem":186},"selene.input","\u002Freference\u002Fmodules\u002Fclient\u002Fselene.input","2.reference\u002F1.modules\u002F3.client\u002Fselene.input",{"title":144,"path":188,"stem":189},"\u002Freference\u002Fmodules\u002Fclient\u002Fselene.map","2.reference\u002F1.modules\u002F3.client\u002Fselene.map",{"title":191,"path":192,"stem":193},"selene.movement.grid","\u002Freference\u002Fmodules\u002Fclient\u002Fselene.movement.grid","2.reference\u002F1.modules\u002F3.client\u002Fselene.movement.grid",{"title":148,"path":195,"stem":196},"\u002Freference\u002Fmodules\u002Fclient\u002Fselene.network","2.reference\u002F1.modules\u002F3.client\u002Fselene.network",{"title":164,"path":198,"stem":199},"\u002Freference\u002Fmodules\u002Fclient\u002Fselene.sounds","2.reference\u002F1.modules\u002F3.client\u002Fselene.sounds",{"title":201,"path":202,"stem":203},"selene.textures","\u002Freference\u002Fmodules\u002Fclient\u002Fselene.textures","2.reference\u002F1.modules\u002F3.client\u002Fselene.textures",{"title":205,"path":206,"stem":207},"selene.ui.lml","\u002Freference\u002Fmodules\u002Fclient\u002Fselene.ui.lml","2.reference\u002F1.modules\u002F3.client\u002Fselene.ui.lml",{"title":209,"path":210,"stem":211},"selene.visuals","\u002Freference\u002Fmodules\u002Fclient\u002Fselene.visuals","2.reference\u002F1.modules\u002F3.client\u002Fselene.visuals",{"title":213,"path":214,"stem":215,"children":216,"page":121},"Data","\u002Freference\u002Fdata","2.reference\u002F2.data",[217,241],{"title":69,"path":218,"stem":219,"children":220,"page":121},"\u002Freference\u002Fdata\u002Fcommon","2.reference\u002F2.data\u002F1.common",[221,225,229,233,237],{"title":222,"path":223,"stem":224},"Component Definition","\u002Freference\u002Fdata\u002Fcommon\u002Fcomponentdefinition","2.reference\u002F2.data\u002F1.common\u002FComponentDefinition",{"title":226,"path":227,"stem":228},"Entity Definition","\u002Freference\u002Fdata\u002Fcommon\u002Fentitydefinition","2.reference\u002F2.data\u002F1.common\u002FEntityDefinition",{"title":230,"path":231,"stem":232},"Sound Definition","\u002Freference\u002Fdata\u002Fcommon\u002Fsounddefinition","2.reference\u002F2.data\u002F1.common\u002FSoundDefinition",{"title":234,"path":235,"stem":236},"Tile Definition","\u002Freference\u002Fdata\u002Fcommon\u002Ftiledefinition","2.reference\u002F2.data\u002F1.common\u002FTileDefinition",{"title":238,"path":239,"stem":240},"Transition Definition","\u002Freference\u002Fdata\u002Fcommon\u002Ftransitiondefinition","2.reference\u002F2.data\u002F1.common\u002FTransitionDefinition",{"title":168,"path":242,"stem":243,"children":244,"page":121},"\u002Freference\u002Fdata\u002Fclient","2.reference\u002F2.data\u002F3.client",[245,249],{"title":246,"path":247,"stem":248},"Audio Definition","\u002Freference\u002Fdata\u002Fclient\u002Faudiodefinition","2.reference\u002F2.data\u002F3.client\u002FAudioDefinition",{"title":250,"path":251,"stem":252},"Visual Definition","\u002Freference\u002Fdata\u002Fclient\u002Fvisualdefinition","2.reference\u002F2.data\u002F3.client\u002FVisualDefinition",{"title":254,"path":255,"stem":256,"children":257,"page":121},"Classes","\u002Freference\u002Fclasses","2.reference\u002F3.classes",[258,286,318],{"title":69,"path":259,"stem":260,"children":261,"page":121},"\u002Freference\u002Fclasses\u002Fcommon","2.reference\u002F3.classes\u002F1.common",[262,266,270,274,278,282],{"title":263,"path":264,"stem":265},"Coordinate","\u002Freference\u002Fclasses\u002Fcommon\u002Fcoordinate","2.reference\u002F3.classes\u002F1.common\u002FCoordinate",{"title":267,"path":268,"stem":269},"CustomRegistryObject","\u002Freference\u002Fclasses\u002Fcommon\u002Fcustomregistryobject","2.reference\u002F3.classes\u002F1.common\u002FCustomRegistryObject",{"title":271,"path":272,"stem":273},"LuaReference","\u002Freference\u002Fclasses\u002Fcommon\u002Fluareference","2.reference\u002F3.classes\u002F1.common\u002FLuaReference",{"title":275,"path":276,"stem":277},"Observable","\u002Freference\u002Fclasses\u002Fcommon\u002Fobservable","2.reference\u002F3.classes\u002F1.common\u002FObservable",{"title":279,"path":280,"stem":281},"RegistryObject","\u002Freference\u002Fclasses\u002Fcommon\u002Fregistryobject","2.reference\u002F3.classes\u002F1.common\u002FRegistryObject",{"title":283,"path":284,"stem":285},"Signal","\u002Freference\u002Fclasses\u002Fcommon\u002Fsignal","2.reference\u002F3.classes\u002F1.common\u002FSignal",{"title":123,"path":287,"stem":288,"children":289,"page":121},"\u002Freference\u002Fclasses\u002Fserver","2.reference\u002F3.classes\u002F2.server",[290,294,298,302,306,310,314],{"title":291,"path":292,"stem":293},"Dimension","\u002Freference\u002Fclasses\u002Fserver\u002Fdimension","2.reference\u002F3.classes\u002F2.server\u002FDimension",{"title":295,"path":296,"stem":297},"Entity","\u002Freference\u002Fclasses\u002Fserver\u002Fentity","2.reference\u002F3.classes\u002F2.server\u002FEntity",{"title":299,"path":300,"stem":301},"LoginQueueEntry","\u002Freference\u002Fclasses\u002Fserver\u002Floginqueueentry","2.reference\u002F3.classes\u002F2.server\u002FLoginQueueEntry",{"title":303,"path":304,"stem":305},"MapTree","\u002Freference\u002Fclasses\u002Fserver\u002Fmaptree","2.reference\u002F3.classes\u002F2.server\u002FMapTree",{"title":307,"path":308,"stem":309},"Player","\u002Freference\u002Fclasses\u002Fserver\u002Fplayer","2.reference\u002F3.classes\u002F2.server\u002FPlayer",{"title":311,"path":312,"stem":313},"ScopedChunkView","\u002Freference\u002Fclasses\u002Fserver\u002Fscopedchunkview","2.reference\u002F3.classes\u002F2.server\u002FScopedChunkView",{"title":315,"path":316,"stem":317},"TransientTile","\u002Freference\u002Fclasses\u002Fserver\u002Ftransienttile","2.reference\u002F3.classes\u002F2.server\u002FTransientTile",{"title":168,"path":319,"stem":320,"children":321,"page":121},"\u002Freference\u002Fclasses\u002Fclient","2.reference\u002F3.classes\u002F3.client",[322,326,330,334,337,341,345,349,353,357,361],{"title":323,"path":324,"stem":325},"Actor","\u002Freference\u002Fclasses\u002Fclient\u002Factor","2.reference\u002F3.classes\u002F3.client\u002FActor",{"title":327,"path":328,"stem":329},"Drawable","\u002Freference\u002Fclasses\u002Fclient\u002Fdrawable","2.reference\u002F3.classes\u002F3.client\u002FDrawable",{"title":331,"path":332,"stem":333},"DrawableVisual2D","\u002Freference\u002Fclasses\u002Fclient\u002Fdrawablevisual2d","2.reference\u002F3.classes\u002F3.client\u002FDrawableVisual2D",{"title":295,"path":335,"stem":336},"\u002Freference\u002Fclasses\u002Fclient\u002Fentity","2.reference\u002F3.classes\u002F3.client\u002FEntity",{"title":338,"path":339,"stem":340},"IsoVisualComponent","\u002Freference\u002Fclasses\u002Fclient\u002Fisovisualcomponent","2.reference\u002F3.classes\u002F3.client\u002FIsoVisualComponent",{"title":342,"path":343,"stem":344},"LuaTexture","\u002Freference\u002Fclasses\u002Fclient\u002Fluatexture","2.reference\u002F3.classes\u002F3.client\u002FLuaTexture",{"title":346,"path":347,"stem":348},"Skin","\u002Freference\u002Fclasses\u002Fclient\u002Fskin","2.reference\u002F3.classes\u002F3.client\u002FSkin",{"title":350,"path":351,"stem":352},"TextFieldTextFieldClickListener","\u002Freference\u002Fclasses\u002Fclient\u002Ftextfield.textfieldclicklistener","2.reference\u002F3.classes\u002F3.client\u002FTextField.TextFieldClickListener",{"title":354,"path":355,"stem":356},"Tile","\u002Freference\u002Fclasses\u002Fclient\u002Ftile","2.reference\u002F3.classes\u002F3.client\u002FTile",{"title":358,"path":359,"stem":360},"Visual2D","\u002Freference\u002Fclasses\u002Fclient\u002Fvisual2d","2.reference\u002F3.classes\u002F3.client\u002FVisual2D",{"title":362,"path":363,"stem":364},"Visual2DComponent","\u002Freference\u002Fclasses\u002Fclient\u002Fvisual2dcomponent","2.reference\u002F3.classes\u002F3.client\u002FVisual2DComponent",{"id":366,"title":43,"body":367,"description":1429,"extension":1430,"meta":1431,"navigation":1296,"path":44,"seo":1432,"stem":45,"__hash__":1433},"docs\u002F1.docs\u002Fdefining-bundle-visuals.md",{"type":368,"value":369,"toc":1415},"minimark",[370,374,383,386,391,402,405,415,418,424,435,514,524,528,535,541,554,557,561,564,570,573,577,584,664,667,714,717,748,752,758,814,820,824,830,908,929,934,938,944,1112,1115,1142,1145,1149,1154,1200,1218,1222,1225,1268,1271,1275,1280,1303,1306,1310,1313,1321,1327,1333,1339,1346,1350,1411],[371,372,43],"h1",{"id":373},"defining-bundle-visuals",[375,376,377,378,382],"p",{},"Visual definitions describe how Selene turns bundle assets into renderable client visuals. They live in client-side bundle data, usually next to the textures they reference, and are loaded into the ",[379,380,381],"code",{},"visuals"," registry.",[375,384,385],{},"Use this guide when you are creating a new bundle that provides graphics, adding visuals for tiles or entities, or overriding existing visuals in a resource pack.",[387,388,390],"h2",{"id":389},"where-visuals-live","Where visuals live",[375,392,393,394,397,398,401],{},"Visuals are client data. Put them under ",[379,395,396],{},"client\u002Fdata\u002F\u003Cnamespace>\u002F",", where ",[379,399,400],{},"\u003Cnamespace>"," becomes the namespace part of each visual identifier.",[375,403,404],{},"You can define multiple visuals in one registry file:",[406,407,413],"pre",{"className":408,"code":410,"language":411,"meta":412},[409],"language-text","my-bundle\u002F\n  bundle.json\n  client\u002F\n    data\u002F\n      myworld\u002F\n        visuals.json\n    textures\u002F\n      myworld\u002F\n        terrain\u002F\n          grass.png\n","text","",[379,414,410],{"__ignoreMap":412},[375,416,417],{},"Or split each visual into its own JSON file:",[406,419,422],{"className":420,"code":421,"language":411,"meta":412},[409],"my-bundle\u002F\n  client\u002F\n    data\u002F\n      myworld\u002F\n        visuals\u002F\n          terrain\u002F\n            grass.json\n",[379,423,421],{"__ignoreMap":412},[375,425,426,427,430,431,434],{},"The merged ",[379,428,429],{},"visuals.json"," form stores entries by local name. This defines ",[379,432,433],{},"myworld:terrain\u002Fgrass",":",[406,436,440],{"className":437,"code":438,"language":439,"meta":412,"style":412},"language-json shiki shiki-themes github-light github-dark","{\n  \"entries\": {\n    \"terrain\u002Fgrass\": {\n      \"type\": \"simple\",\n      \"texture\": \"client\u002Ftextures\u002Fmyworld\u002Fterrain\u002Fgrass.png\"\n    }\n  }\n}\n","json",[379,441,442,451,461,469,485,496,502,508],{"__ignoreMap":412},[443,444,447],"span",{"class":445,"line":446},"line",1,[443,448,450],{"class":449},"sVt8B","{\n",[443,452,454,458],{"class":445,"line":453},2,[443,455,457],{"class":456},"sj4cs","  \"entries\"",[443,459,460],{"class":449},": {\n",[443,462,464,467],{"class":445,"line":463},3,[443,465,466],{"class":456},"    \"terrain\u002Fgrass\"",[443,468,460],{"class":449},[443,470,472,475,478,482],{"class":445,"line":471},4,[443,473,474],{"class":456},"      \"type\"",[443,476,477],{"class":449},": ",[443,479,481],{"class":480},"sZZnC","\"simple\"",[443,483,484],{"class":449},",\n",[443,486,488,491,493],{"class":445,"line":487},5,[443,489,490],{"class":456},"      \"texture\"",[443,492,477],{"class":449},[443,494,495],{"class":480},"\"client\u002Ftextures\u002Fmyworld\u002Fterrain\u002Fgrass.png\"\n",[443,497,499],{"class":445,"line":498},6,[443,500,501],{"class":449},"    }\n",[443,503,505],{"class":445,"line":504},7,[443,506,507],{"class":449},"  }\n",[443,509,511],{"class":445,"line":510},8,[443,512,513],{"class":449},"}\n",[375,515,516,517,520,521,523],{},"The split-file form uses the file path as the local name. For example, ",[379,518,519],{},"client\u002Fdata\u002Fmyworld\u002Fvisuals\u002Fterrain\u002Fgrass.json"," also defines ",[379,522,433],{},".",[387,525,527],{"id":526},"visual-identifiers","Visual identifiers",[375,529,530,531,534],{},"Visual identifiers use the same ",[379,532,533],{},"namespace:name"," format as other Selene registries:",[406,536,539],{"className":537,"code":538,"language":411,"meta":412},[409],"myworld:terrain\u002Fgrass\nmyworld:characters\u002Fguard\nillarion:tile_cursor\n",[379,540,538],{"__ignoreMap":412},[375,542,543,544,547,548,550,551,523],{},"The namespace comes from the directory below ",[379,545,546],{},"client\u002Fdata\u002F",". The name comes from either the key inside ",[379,549,429],{}," or the relative path of a file below ",[379,552,553],{},"visuals\u002F",[375,555,556],{},"Use stable, descriptive names. Tiles, entities, and scripts refer to these identifiers, so renaming a visual means updating every reference to it.",[387,558,560],{"id":559},"texture-paths","Texture paths",[375,562,563],{},"Texture paths are bundle-relative paths, such as:",[406,565,568],{"className":566,"code":567,"language":411,"meta":412},[409],"client\u002Ftextures\u002Fmyworld\u002Fterrain\u002Fgrass.png\n",[379,569,567],{"__ignoreMap":412},[375,571,572],{},"The path is resolved from the loaded bundle files. If you are overriding an existing texture in a resource pack, keep the same internal path as the original bundle. If you are defining a new visual, choose a path that matches your bundle's own texture layout.",[387,574,576],{"id":575},"simple-visuals","Simple visuals",[375,578,579,580,583],{},"Use ",[379,581,582],{},"simple"," for one static texture.",[406,585,587],{"className":437,"code":586,"language":439,"meta":412,"style":412},"{\n  \"type\": \"simple\",\n  \"texture\": \"client\u002Ftextures\u002Fmyworld\u002Fterrain\u002Fgrass.png\",\n  \"offsetX\": 0,\n  \"offsetY\": 0,\n  \"surfaceOffsetY\": 0,\n  \"sortLayerOffset\": 0\n}\n",[379,588,589,593,604,616,628,639,650,660],{"__ignoreMap":412},[443,590,591],{"class":445,"line":446},[443,592,450],{"class":449},[443,594,595,598,600,602],{"class":445,"line":453},[443,596,597],{"class":456},"  \"type\"",[443,599,477],{"class":449},[443,601,481],{"class":480},[443,603,484],{"class":449},[443,605,606,609,611,614],{"class":445,"line":463},[443,607,608],{"class":456},"  \"texture\"",[443,610,477],{"class":449},[443,612,613],{"class":480},"\"client\u002Ftextures\u002Fmyworld\u002Fterrain\u002Fgrass.png\"",[443,615,484],{"class":449},[443,617,618,621,623,626],{"class":445,"line":471},[443,619,620],{"class":456},"  \"offsetX\"",[443,622,477],{"class":449},[443,624,625],{"class":456},"0",[443,627,484],{"class":449},[443,629,630,633,635,637],{"class":445,"line":487},[443,631,632],{"class":456},"  \"offsetY\"",[443,634,477],{"class":449},[443,636,625],{"class":456},[443,638,484],{"class":449},[443,640,641,644,646,648],{"class":445,"line":498},[443,642,643],{"class":456},"  \"surfaceOffsetY\"",[443,645,477],{"class":449},[443,647,625],{"class":456},[443,649,484],{"class":449},[443,651,652,655,657],{"class":445,"line":504},[443,653,654],{"class":456},"  \"sortLayerOffset\"",[443,656,477],{"class":449},[443,658,659],{"class":456},"0\n",[443,661,662],{"class":445,"line":510},[443,663,513],{"class":449},[375,665,666],{},"Common fields:",[668,669,670,677,687,693,699,708],"ul",{},[671,672,673,676],"li",{},[379,674,675],{},"texture"," is the PNG or other supported texture asset to draw.",[671,678,679,682,683,686],{},[379,680,681],{},"offsetX"," and ",[379,684,685],{},"offsetY"," move the texture relative to its render position.",[671,688,689,692],{},[379,690,691],{},"surfaceOffsetY"," raises the visual surface for isometric stacking.",[671,694,695,698],{},[379,696,697],{},"sortLayerOffset"," adjusts render order when the default sort is not enough.",[671,700,701,682,704,707],{},[379,702,703],{},"flipX",[379,705,706],{},"flipY"," mirror the texture.",[671,709,710,713],{},[379,711,712],{},"metadata"," stores custom data that systems or Lua code can inspect.",[375,715,716],{},"Most numeric and boolean fields have defaults in the engine, so you can omit them when the default value is correct:",[406,718,720],{"className":437,"code":719,"language":439,"meta":412,"style":412},"{\n  \"type\": \"simple\",\n  \"texture\": \"client\u002Ftextures\u002Fmyworld\u002Fterrain\u002Fgrass.png\"\n}\n",[379,721,722,726,736,744],{"__ignoreMap":412},[443,723,724],{"class":445,"line":446},[443,725,450],{"class":449},[443,727,728,730,732,734],{"class":445,"line":453},[443,729,597],{"class":456},[443,731,477],{"class":449},[443,733,481],{"class":480},[443,735,484],{"class":449},[443,737,738,740,742],{"class":445,"line":463},[443,739,608],{"class":456},[443,741,477],{"class":449},[443,743,495],{"class":480},[443,745,746],{"class":445,"line":471},[443,747,513],{"class":449},[387,749,751],{"id":750},"variant-visuals","Variant visuals",[375,753,579,754,757],{},[379,755,756],{},"variants"," when several textures are equivalent alternatives. Selene picks a variant from the render context, which is useful for repeating terrain where identical tiles should not all look the same.",[406,759,761],{"className":437,"code":760,"language":439,"meta":412,"style":412},"{\n  \"type\": \"variants\",\n  \"textures\": [\n    \"client\u002Ftextures\u002Fmyworld\u002Fterrain\u002Fgrass_0.png\",\n    \"client\u002Ftextures\u002Fmyworld\u002Fterrain\u002Fgrass_1.png\",\n    \"client\u002Ftextures\u002Fmyworld\u002Fterrain\u002Fgrass_2.png\"\n  ]\n}\n",[379,762,763,767,778,786,793,800,805,810],{"__ignoreMap":412},[443,764,765],{"class":445,"line":446},[443,766,450],{"class":449},[443,768,769,771,773,776],{"class":445,"line":453},[443,770,597],{"class":456},[443,772,477],{"class":449},[443,774,775],{"class":480},"\"variants\"",[443,777,484],{"class":449},[443,779,780,783],{"class":445,"line":463},[443,781,782],{"class":456},"  \"textures\"",[443,784,785],{"class":449},": [\n",[443,787,788,791],{"class":445,"line":471},[443,789,790],{"class":480},"    \"client\u002Ftextures\u002Fmyworld\u002Fterrain\u002Fgrass_0.png\"",[443,792,484],{"class":449},[443,794,795,798],{"class":445,"line":487},[443,796,797],{"class":480},"    \"client\u002Ftextures\u002Fmyworld\u002Fterrain\u002Fgrass_1.png\"",[443,799,484],{"class":449},[443,801,802],{"class":445,"line":498},[443,803,804],{"class":480},"    \"client\u002Ftextures\u002Fmyworld\u002Fterrain\u002Fgrass_2.png\"\n",[443,806,807],{"class":445,"line":504},[443,808,809],{"class":449},"  ]\n",[443,811,812],{"class":445,"line":510},[443,813,513],{"class":449},[375,815,816,817,819],{},"Variant visuals support the same offset, sorting, flipping, and metadata fields as ",[379,818,582],{}," visuals.",[387,821,823],{"id":822},"animated-visuals","Animated visuals",[375,825,579,826,829],{},[379,827,828],{},"animated"," for a fixed sequence of frames.",[406,831,833],{"className":437,"code":832,"language":439,"meta":412,"style":412},"{\n  \"type\": \"animated\",\n  \"textures\": [\n    \"client\u002Ftextures\u002Fmyworld\u002Feffects\u002Fsparkle_0.png\",\n    \"client\u002Ftextures\u002Fmyworld\u002Feffects\u002Fsparkle_1.png\",\n    \"client\u002Ftextures\u002Fmyworld\u002Feffects\u002Fsparkle_2.png\"\n  ],\n  \"duration\": 0.1,\n  \"instanced\": true\n}\n",[379,834,835,839,850,856,863,870,875,880,892,903],{"__ignoreMap":412},[443,836,837],{"class":445,"line":446},[443,838,450],{"class":449},[443,840,841,843,845,848],{"class":445,"line":453},[443,842,597],{"class":456},[443,844,477],{"class":449},[443,846,847],{"class":480},"\"animated\"",[443,849,484],{"class":449},[443,851,852,854],{"class":445,"line":463},[443,853,782],{"class":456},[443,855,785],{"class":449},[443,857,858,861],{"class":445,"line":471},[443,859,860],{"class":480},"    \"client\u002Ftextures\u002Fmyworld\u002Feffects\u002Fsparkle_0.png\"",[443,862,484],{"class":449},[443,864,865,868],{"class":445,"line":487},[443,866,867],{"class":480},"    \"client\u002Ftextures\u002Fmyworld\u002Feffects\u002Fsparkle_1.png\"",[443,869,484],{"class":449},[443,871,872],{"class":445,"line":498},[443,873,874],{"class":480},"    \"client\u002Ftextures\u002Fmyworld\u002Feffects\u002Fsparkle_2.png\"\n",[443,876,877],{"class":445,"line":504},[443,878,879],{"class":449},"  ],\n",[443,881,882,885,887,890],{"class":445,"line":510},[443,883,884],{"class":456},"  \"duration\"",[443,886,477],{"class":449},[443,888,889],{"class":456},"0.1",[443,891,484],{"class":449},[443,893,895,898,900],{"class":445,"line":894},9,[443,896,897],{"class":456},"  \"instanced\"",[443,899,477],{"class":449},[443,901,902],{"class":456},"true\n",[443,904,906],{"class":445,"line":905},10,[443,907,513],{"class":449},[375,909,910,913,914,917,918,921,922,924,925,928],{},[379,911,912],{},"duration"," is the frame duration in seconds. If ",[379,915,916],{},"instanced"," is ",[379,919,920],{},"false"," or omitted, Selene may share the animation state between visuals with the same identifier. Set ",[379,923,916],{}," to ",[379,926,927],{},"true"," when each visual should animate independently.",[375,930,931,932,819],{},"Animated visuals support the same offset, sorting, flipping, and metadata fields as ",[379,933,582],{},[387,935,937],{"id":936},"animator-visuals","Animator visuals",[375,939,579,940,943],{},[379,941,942],{},"animator"," when a visual has named animations controlled by an animator component, such as idle, walk, attack, or death.",[406,945,947],{"className":437,"code":946,"language":439,"meta":412,"style":412},"{\n  \"type\": \"animator\",\n  \"animator\": \"character\",\n  \"offsetX\": 0,\n  \"offsetY\": -24,\n  \"animations\": {\n    \"idle\": {\n      \"textures\": [\n        \"client\u002Ftextures\u002Fmyworld\u002Fcharacters\u002Fguard_idle_0.png\",\n        \"client\u002Ftextures\u002Fmyworld\u002Fcharacters\u002Fguard_idle_1.png\"\n      ],\n      \"duration\": 0.2\n    },\n    \"walk_south\": {\n      \"textures\": [\n        \"client\u002Ftextures\u002Fmyworld\u002Fcharacters\u002Fguard_walk_south_0.png\",\n        \"client\u002Ftextures\u002Fmyworld\u002Fcharacters\u002Fguard_walk_south_1.png\"\n      ],\n      \"duration\": 0.08\n    }\n  }\n}\n",[379,948,949,953,964,976,986,997,1004,1011,1018,1025,1030,1036,1047,1053,1061,1068,1076,1082,1087,1097,1102,1107],{"__ignoreMap":412},[443,950,951],{"class":445,"line":446},[443,952,450],{"class":449},[443,954,955,957,959,962],{"class":445,"line":453},[443,956,597],{"class":456},[443,958,477],{"class":449},[443,960,961],{"class":480},"\"animator\"",[443,963,484],{"class":449},[443,965,966,969,971,974],{"class":445,"line":463},[443,967,968],{"class":456},"  \"animator\"",[443,970,477],{"class":449},[443,972,973],{"class":480},"\"character\"",[443,975,484],{"class":449},[443,977,978,980,982,984],{"class":445,"line":471},[443,979,620],{"class":456},[443,981,477],{"class":449},[443,983,625],{"class":456},[443,985,484],{"class":449},[443,987,988,990,992,995],{"class":445,"line":487},[443,989,632],{"class":456},[443,991,477],{"class":449},[443,993,994],{"class":456},"-24",[443,996,484],{"class":449},[443,998,999,1002],{"class":445,"line":498},[443,1000,1001],{"class":456},"  \"animations\"",[443,1003,460],{"class":449},[443,1005,1006,1009],{"class":445,"line":504},[443,1007,1008],{"class":456},"    \"idle\"",[443,1010,460],{"class":449},[443,1012,1013,1016],{"class":445,"line":510},[443,1014,1015],{"class":456},"      \"textures\"",[443,1017,785],{"class":449},[443,1019,1020,1023],{"class":445,"line":894},[443,1021,1022],{"class":480},"        \"client\u002Ftextures\u002Fmyworld\u002Fcharacters\u002Fguard_idle_0.png\"",[443,1024,484],{"class":449},[443,1026,1027],{"class":445,"line":905},[443,1028,1029],{"class":480},"        \"client\u002Ftextures\u002Fmyworld\u002Fcharacters\u002Fguard_idle_1.png\"\n",[443,1031,1033],{"class":445,"line":1032},11,[443,1034,1035],{"class":449},"      ],\n",[443,1037,1039,1042,1044],{"class":445,"line":1038},12,[443,1040,1041],{"class":456},"      \"duration\"",[443,1043,477],{"class":449},[443,1045,1046],{"class":456},"0.2\n",[443,1048,1050],{"class":445,"line":1049},13,[443,1051,1052],{"class":449},"    },\n",[443,1054,1056,1059],{"class":445,"line":1055},14,[443,1057,1058],{"class":456},"    \"walk_south\"",[443,1060,460],{"class":449},[443,1062,1064,1066],{"class":445,"line":1063},15,[443,1065,1015],{"class":456},[443,1067,785],{"class":449},[443,1069,1071,1074],{"class":445,"line":1070},16,[443,1072,1073],{"class":480},"        \"client\u002Ftextures\u002Fmyworld\u002Fcharacters\u002Fguard_walk_south_0.png\"",[443,1075,484],{"class":449},[443,1077,1079],{"class":445,"line":1078},17,[443,1080,1081],{"class":480},"        \"client\u002Ftextures\u002Fmyworld\u002Fcharacters\u002Fguard_walk_south_1.png\"\n",[443,1083,1085],{"class":445,"line":1084},18,[443,1086,1035],{"class":449},[443,1088,1090,1092,1094],{"class":445,"line":1089},19,[443,1091,1041],{"class":456},[443,1093,477],{"class":449},[443,1095,1096],{"class":456},"0.08\n",[443,1098,1100],{"class":445,"line":1099},20,[443,1101,501],{"class":449},[443,1103,1105],{"class":445,"line":1104},21,[443,1106,507],{"class":449},[443,1108,1110],{"class":445,"line":1109},22,[443,1111,513],{"class":449},[375,1113,1114],{},"Each animation entry has:",[668,1116,1117,1123,1128,1135],{},[671,1118,1119,1122],{},[379,1120,1121],{},"textures"," for the animation frames.",[671,1124,1125,1127],{},[379,1126,912],{}," for frame duration in seconds. If omitted, Selene uses a fast default.",[671,1129,1130,682,1132,1134],{},[379,1131,681],{},[379,1133,685],{}," to override the base visual offsets for that animation.",[671,1136,1137,682,1139,1141],{},[379,1138,703],{},[379,1140,706],{}," to mirror that animation's frames.",[375,1143,1144],{},"Animator visuals require a render context with an animator controller. They are usually attached through entity rendering components rather than created as standalone decorative visuals.",[387,1146,1148],{"id":1147},"text-visuals","Text visuals",[375,1150,579,1151,1153],{},[379,1152,411],{}," for a visual backed by rendered text instead of a texture.",[406,1155,1157],{"className":437,"code":1156,"language":439,"meta":412,"style":412},"{\n  \"type\": \"text\",\n  \"text\": \"Hello\",\n  \"align\": \"CENTER\"\n}\n",[379,1158,1159,1163,1174,1186,1196],{"__ignoreMap":412},[443,1160,1161],{"class":445,"line":446},[443,1162,450],{"class":449},[443,1164,1165,1167,1169,1172],{"class":445,"line":453},[443,1166,597],{"class":456},[443,1168,477],{"class":449},[443,1170,1171],{"class":480},"\"text\"",[443,1173,484],{"class":449},[443,1175,1176,1179,1181,1184],{"class":445,"line":463},[443,1177,1178],{"class":456},"  \"text\"",[443,1180,477],{"class":449},[443,1182,1183],{"class":480},"\"Hello\"",[443,1185,484],{"class":449},[443,1187,1188,1191,1193],{"class":445,"line":471},[443,1189,1190],{"class":456},"  \"align\"",[443,1192,477],{"class":449},[443,1194,1195],{"class":480},"\"CENTER\"\n",[443,1197,1198],{"class":445,"line":487},[443,1199,513],{"class":449},[375,1201,1202,1205,1206,1209,1210,1213,1214,1217],{},[379,1203,1204],{},"align"," can be ",[379,1207,1208],{},"LEFT",", ",[379,1211,1212],{},"CENTER",", or ",[379,1215,1216],{},"RIGHT",". Entity visual components can override the text value through their visual creation context.",[387,1219,1221],{"id":1220},"referencing-visuals-from-data","Referencing visuals from data",[375,1223,1224],{},"Bundle data refers to visuals by identifier. For example, a tile definition can point at a visual:",[406,1226,1228],{"className":437,"code":1227,"language":439,"meta":412,"style":412},"{\n  \"entries\": {\n    \"terrain\u002Fgrass\": {\n      \"visual\": \"myworld:terrain\u002Fgrass\"\n    }\n  }\n}\n",[379,1229,1230,1234,1240,1246,1256,1260,1264],{"__ignoreMap":412},[443,1231,1232],{"class":445,"line":446},[443,1233,450],{"class":449},[443,1235,1236,1238],{"class":445,"line":453},[443,1237,457],{"class":456},[443,1239,460],{"class":449},[443,1241,1242,1244],{"class":445,"line":463},[443,1243,466],{"class":456},[443,1245,460],{"class":449},[443,1247,1248,1251,1253],{"class":445,"line":471},[443,1249,1250],{"class":456},"      \"visual\"",[443,1252,477],{"class":449},[443,1254,1255],{"class":480},"\"myworld:terrain\u002Fgrass\"\n",[443,1257,1258],{"class":445,"line":487},[443,1259,501],{"class":449},[443,1261,1262],{"class":445,"line":498},[443,1263,507],{"class":449},[443,1265,1266],{"class":445,"line":504},[443,1267,513],{"class":449},[375,1269,1270],{},"Entity definitions and components follow the same pattern when they need a client visual. Keep the visual identifier in client-safe data when possible, and keep server-only gameplay data separate from client assets.",[387,1272,1274],{"id":1273},"creating-visuals-from-lua","Creating visuals from Lua",[375,1276,1277,1278,434],{},"Client Lua can create a visual by identifier through ",[379,1279,209],{},[406,1281,1285],{"className":1282,"code":1283,"language":1284,"meta":412,"style":412},"language-lua shiki shiki-themes github-light github-dark","local visuals = require(\"selene.visuals\")\n\nlocal cursor = visuals.Create(\"illarion:tile_cursor\")\n","lua",[379,1286,1287,1292,1298],{"__ignoreMap":412},[443,1288,1289],{"class":445,"line":446},[443,1290,1291],{},"local visuals = require(\"selene.visuals\")\n",[443,1293,1294],{"class":445,"line":453},[443,1295,1297],{"emptyLinePlaceholder":1296},true,"\n",[443,1299,1300],{"class":445,"line":463},[443,1301,1302],{},"local cursor = visuals.Create(\"illarion:tile_cursor\")\n",[375,1304,1305],{},"This is useful for UI cursors, overlays, and custom client effects. For tiles and entities, prefer data-driven visual references so reloads and resource-pack overrides remain straightforward.",[387,1307,1309],{"id":1308},"resource-pack-overrides","Resource pack overrides",[375,1311,1312],{},"Resource packs can override visuals in two ways:",[668,1314,1315,1318],{},[671,1316,1317],{},"Replace the texture file at the same internal path.",[671,1319,1320],{},"Replace the visual definition JSON and point it to a different texture or change offsets, animation frames, or sorting.",[375,1322,1323,1324,1326],{},"For example, to override ",[379,1325,433],{}," from a merged registry file, mirror the original path:",[406,1328,1331],{"className":1329,"code":1330,"language":411,"meta":412},[409],"global_client_bundles\u002F\n  my-resource-pack\u002F\n    client\u002F\n      data\u002F\n        myworld\u002F\n          visuals.json\n",[379,1332,1330],{"__ignoreMap":412},[375,1334,1335,1336,1338],{},"If the original visual was split into ",[379,1337,519],{},", mirror that file path instead.",[375,1340,1341,1342,1345],{},"See ",[1343,1344,55],"a",{"href":56}," for the broader override workflow.",[387,1347,1349],{"id":1348},"checklist","Checklist",[668,1351,1352,1362,1368,1385,1388,1401],{},[671,1353,1354,1355,1358,1359,523],{},"Put visual definitions under ",[379,1356,1357],{},"client\u002Fdata\u002F\u003Cnamespace>\u002Fvisuals.json"," or ",[379,1360,1361],{},"client\u002Fdata\u002F\u003Cnamespace>\u002Fvisuals\u002F",[671,1363,1364,1365,523],{},"Put referenced texture assets under ",[379,1366,1367],{},"client\u002Ftextures\u002F",[671,1369,579,1370,1372,1373,1375,1376,1378,1379,1381,1382,1384],{},[379,1371,582],{}," for static textures, ",[379,1374,756],{}," for interchangeable texture choices, ",[379,1377,828],{}," for fixed frame loops, ",[379,1380,942],{}," for named controlled animations, and ",[379,1383,411],{}," for rendered text.",[671,1386,1387],{},"Keep visual identifiers stable once other data references them.",[671,1389,1390,1391,1209,1393,1209,1395,1397,1398,1400],{},"Tune ",[379,1392,681],{},[379,1394,685],{},[379,1396,691],{},", and ",[379,1399,697],{}," in game, because these fields depend on the asset's pixel dimensions and the intended isometric footprint.",[671,1402,1403,1404,1358,1407,1410],{},"Test reload behavior with ",[379,1405,1406],{},"F5",[379,1408,1409],{},"hotReload=true"," when iterating on bundle assets.",[1412,1413,1414],"style",{},"html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":412,"searchDepth":453,"depth":453,"links":1416},[1417,1418,1419,1420,1421,1422,1423,1424,1425,1426,1427,1428],{"id":389,"depth":453,"text":390},{"id":526,"depth":453,"text":527},{"id":559,"depth":453,"text":560},{"id":575,"depth":453,"text":576},{"id":750,"depth":453,"text":751},{"id":822,"depth":453,"text":823},{"id":936,"depth":453,"text":937},{"id":1147,"depth":453,"text":1148},{"id":1220,"depth":453,"text":1221},{"id":1273,"depth":453,"text":1274},{"id":1308,"depth":453,"text":1309},{"id":1348,"depth":453,"text":1349},"Learn how to define client visual entries in Selene bundles and reference them from tiles, entities, and Lua code.","md",{},{"title":43,"description":1429},"g0pMiGiaRYuoF5Brd2VvTl9C-sVJgjnuf3-t5j4PF48",[1435,1437],{"title":39,"path":40,"stem":41,"description":1436,"children":-1},"Define tile registry entries in Selene bundles, connect them to visuals, and use tile flags for map collision.",{"title":47,"path":48,"stem":49,"description":1438,"children":-1},"Register Lua callbacks for Selene bundle events and understand the common, server, and client events currently exposed by the engine.",1792747966453]