From a8d6f4fd01fd7f7988ec1365050248c9a20c94aa Mon Sep 17 00:00:00 2001 From: RampantDespair Date: Fri, 21 Jul 2023 18:54:55 -0400 Subject: [PATCH] Added Automatic / Manual root positioning --- Aseprite-Exporter.lua | 115 +++++++++++++++++++++++++----------- README.md | 2 +- example/SpineTest.spine | Bin 839 -> 849 bytes example/SpriteTest.aseprite | Bin 859 -> 925 bytes example/SpriteTest.json | 2 +- media/showcase-v2.6.png | Bin 0 -> 24017 bytes 6 files changed, 83 insertions(+), 36 deletions(-) create mode 100644 media/showcase-v2.6.png diff --git a/Aseprite-Exporter.lua b/Aseprite-Exporter.lua index 771f995..689cd0a 100644 --- a/Aseprite-Exporter.lua +++ b/Aseprite-Exporter.lua @@ -37,6 +37,16 @@ function Export(activeSprite, rootLayer, fileName, fileNameTemplate, dlgData) ExportSpineJsonStart(fileName, dlgData) end + if dlgData.setRootPostion == true and dlgData.rootPostionMethod == "automatic" then + for _, layer in ipairs(rootLayer.layers) do + if layer.name == "root" then + RootPositon = layer.cels[1].position + break + end + end + app.alert("Automatic RootPosition is x:" .. RootPositon.x .. " y:" .. RootPositon.y) + end + ExportSpriteLayers(activeSprite, rootLayer, fileName, fileNameTemplate, dlgData) if dlgData.exportSpineSheet == true then @@ -49,42 +59,44 @@ function ExportSpriteLayers(activeSprite, rootLayer, fileName, fileNameTemplate, local _fileNameTemplate = fileNameTemplate local layerName = layer.name - if layer.isGroup then - local previousVisibility = layer.isVisible - layer.isVisible = true + if layerName ~= "root" then + if layer.isGroup then + local previousVisibility = layer.isVisible + layer.isVisible = true - if dlgData.groupsAsSkins == true then - _fileNameTemplate = app.fs.joinPath(layerName, _fileNameTemplate) - end - - ExportSpriteLayers(activeSprite, layer, fileName, _fileNameTemplate, dlgData) + if dlgData.groupsAsSkins == true then + _fileNameTemplate = app.fs.joinPath(layerName, _fileNameTemplate) + end - layer.isVisible = previousVisibility - else - layer.isVisible = true + ExportSpriteLayers(activeSprite, layer, fileName, _fileNameTemplate, dlgData) - local layerParentName - if pcall(function () layerParentName = layer.parent.name end) then - _fileNameTemplate = _fileNameTemplate:gsub("{layergroup}", layerParentName) + layer.isVisible = previousVisibility else - _fileNameTemplate = _fileNameTemplate:gsub("{layergroup}", "default") - end - - _fileNameTemplate = _fileNameTemplate:gsub("{layername}", layerName) + layer.isVisible = true - if #layer.cels ~= 0 then - if dlgData.exportSpriteSheet then - ExportSpriteSheet(activeSprite, layer, _fileNameTemplate, dlgData) + local layerParentName + if pcall(function () layerParentName = layer.parent.name end) then + _fileNameTemplate = _fileNameTemplate:gsub("{layergroup}", layerParentName) + else + _fileNameTemplate = _fileNameTemplate:gsub("{layergroup}", "default") end - if dlgData.exportSpineSheet == true then - ExportSpineJsonParse(activeSprite, layer, _fileNameTemplate, dlgData) + _fileNameTemplate = _fileNameTemplate:gsub("{layername}", layerName) + + if #layer.cels ~= 0 then + if dlgData.exportSpriteSheet then + ExportSpriteSheet(activeSprite, layer, _fileNameTemplate, dlgData) + end + + if dlgData.exportSpineSheet == true then + ExportSpineJsonParse(activeSprite, layer, _fileNameTemplate, dlgData) + end + + LayerCount = LayerCount + 1 end - LayerCount = LayerCount + 1 + layer.isVisible = false end - - layer.isVisible = false end end end @@ -139,8 +151,21 @@ function ExportSpineJsonParse(activeSprite, layer, fileNameTemplate, dlgData) local realPostionX = layerCelX + layerCelWidth / 2 local realPositionY = layerCelY + layerCelHeight / 2 - local spriteX = realPostionX - dlgData.rootPositionX - local spriteY = dlgData.rootPositionY - realPositionY + local spriteX + local spriteY + + if dlgData.setRootPostion == true then + if dlgData.rootPostionMethod == "automatic" then + spriteX = realPostionX - RootPositon.x + spriteY = RootPositon.y - realPositionY + else + spriteX = realPostionX - dlgData.rootPositionX + spriteY = dlgData.rootPositionY - realPositionY + end + else + spriteX = realPostionX + spriteY = realPositionY + end if dlgData.groupsAsSkins == true then fileNameTemplate = fileNameTemplate:gsub("\\", "/") @@ -341,9 +366,13 @@ dlg:check{ } dlg:check{ id = "setRootPostion", - label = "Set Root position", + label = "Set Root position:", selected = true, onclick = function() + dlg:modify{ + id = "rootPostionMethod", + visible = dlg.data.setRootPostion + } dlg:modify{ id = "rootPositionX", visible = dlg.data.setRootPostion @@ -354,17 +383,35 @@ dlg:check{ } end } +dlg:combobox{ + id = "rootPostionMethod", + label = " Root position method:", + option = "automatic", + options = {"manual", "automatic"}, + onchange = function() + dlg:modify{ + id = "rootPositionX", + visible = dlg.data.rootPostionMethod == "manual" + } + dlg:modify{ + id = "rootPositionY", + visible = dlg.data.rootPostionMethod == "manual" + } + end +} dlg:number{ id = "rootPositionX", - label = " Root Postion X:", + label = " Root Postion X:", text = "0", - decimals = 0 + decimals = 0, + visible = false } dlg:number{ id = "rootPositionY", - label = " Root Postion Y:", + label = " Root Postion Y:", text = "0", - decimals = 0 + decimals = 0, + visible = false } dlg:separator{ id = "separator4", @@ -444,7 +491,7 @@ dlg:button{id = "confirm", text = "Confirm"} dlg:button{id = "cancel", text = "Cancel"} dlg:show() -if not dlg.data.confirm then +if not dlg.data.confirm then app.alert("Settings were not confirmed, script aborted.") return end diff --git a/README.md b/README.md index 70c28bd..c9f6e14 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Aseprite-Exporter --- ### Showcase -![showcase](media/showcase-v2.3.png) +![showcase](media/showcase-v2.6.png) ### Features - Configurable output path diff --git a/example/SpineTest.spine b/example/SpineTest.spine index e53f61d6cd2769fa0acd6ed56c4c1fcb58cc29a6..c7078e54e0d70fbf8416651f29ac1c9636d31eb2 100644 GIT binary patch literal 849 zcmV-X1Frn7R@+WfK@{EV^iFSpaw|~UiWMvrHNN9VA z5fkGd=nIJ^#+Zl?5cvSb5AX|owDFA?@zH>LrUh&{B?_KoCNul&y=TqLS~GKEC9o1W z8$BI8v#P)sy0Adx4?{6Qoy%%^{$lFK7!*?A1+K$Hhz{hksf@ae*Ds%adp@a<3CWbc zvF)Ttr^ncQyRx**e=B3&eEK3|Y`uszP_$tE-k%NnrwiR0T69bqZ{T@j0Yx1#1G`|6%u;UQZm++++1X51QrCvx)3m$)l+#j zuIBRnlj(xmUy9j5^>OGxsDcKdx*b%8q`v=aOiA^2qL9w_m*WnyS^>kvcXUp8&KXX_YT-R*j**F!MlsQlV5?ThB$q3K#;?Y&jEu$mFY8(%n~UW}@1`;vZYHWb z;tr4!q;Aep$HgaE+b-))S=-p^;o_G)JGYJ-jN1y!T9)VoPe9BnCS}njLwXF{O;S_> z-m-#b{t=L_E!=A3G7kd*H6L6&@tWfC?XMln;j}Zp%hLFtEbW8+A=qj&{WGStxDKs70Hq0ozRst|p1E&1}Pn0vK0m<2c8YBkptBI_Zk;ZjF3^T8- z-H*)|BU|(I|9}*DtJUOyA?tTQ=<3%!5Xu~ji)E7_Ztb}9(No;x4~P?KpvDQMMdl87 zO4Zu`$P*m;oa&njr)Tz&yMfl9!ac!apZ*823x1_Tg(}I%t0lj%ujJ#^k|zVnQ+Jqe zGR)+(^&4>H^m)YJc`m= zpuSfOx$`Np@4Rs`cMm+3|Bg_D*uJhxYp<(Q!b#1_XG9{OxRgp4E1wC`KX@ZS;g`X) bVUN?R@+;yv1uMt24=zQ{c?B3acdfqx$SJ0x literal 839 zcmV-N1GxOHR!eA8K@`2`<=_0;`fH<2leCT2wh4;cVk6>jQ=w52M4Bc~n;P@t%L}@( zeim+A>!zR};zAcK3L@e{UAk~Dh$t9zC1PD0?@VHvG>O#42XmRZ@7_D-&73oDwl4*i z0(&C6BD46?SMjz!=fUguGRHQIeU?wxU(uUq#LocC6c97-RKm0k#ATcaY&!}N znR#Lte0}Vn(XvHA*R-ED5!@kC?V{%rJ*O}hVH9-vv9PdEvWk&MeiEqLAx36l`n@2x zaBmT#tze8k(d!kaN0@mGb4({Us~6@GbU9<}wN7x3LnON0F5&R_QR2t;@@fT%w~T6l z2%RQ)#~(g?q-?SQP6j|!qHZ_LFgQ7*DG01JX*SvY1Yr>6}y zuI7!gnM^?)E9X=}#U|DTD%b?mU=@=3c+Hqn>X}3#V~kbu*0WfFriIVys+wK>wQX0` z)l{WsI0LJNx0oqLCQ`b^hlT`MwL&(vSeJC-aQx8ZvG~|QT`T1BvHaAzbavUzJavz_ z1Ed6LkZW{s^GVWfm9|e>8+$$6{BmUH-cXZydmyP>`wXC8rtD}EZjzc3@D>%?%r62m zbPM--xy@4({cK*pcH%9y<7<=-)kw$Eo^(#EuryxF(oxtigCnO`cDTHyEd@22tgts3 zfP;aNrM#-9&}`_BV@~0wJG~5{)g6>tW5JMEK RpVL16?z!O=VBlQw{syJgqn-c& diff --git a/example/SpriteTest.aseprite b/example/SpriteTest.aseprite index 9b45f2c0d6a8ab26f6c503ec73cfe78999eb9648..f902a4b4c7443a259a327342b64c974c99e3dff3 100644 GIT binary patch delta 95 zcmcc3HkX}o?nK6VURh=ahF>2A7*ZG*7z8%5EI4*=a-6=47X delta 31 ncmbQsew&RkdLm;z?`4~7*ZG*82C2!YB5c|%(MgmnU4v+ diff --git a/example/SpriteTest.json b/example/SpriteTest.json index b26b11d..c76c8db 100644 --- a/example/SpriteTest.json +++ b/example/SpriteTest.json @@ -1 +1 @@ -{ "skeleton": { "images": "./sprite/", "audio": "./sound/" }, "bones": [ { "name": "root" } ], "slots": [ { "name": "square2", "bone": "root", "attachment": "square2" }, { "name": "square", "bone": "root", "attachment": "square" }], "skins": [ { "name": "default", "attachments": { "square2": { "SpriteTest-default-square2": { "x": 12.00, "y": -4.00, "width": 8, "height": 8 } } } }, { "name": "weapon-blue", "attachments": { "square": { "square": { "name": "blue/SpriteTest-blue-square", "x": 4.00, "y": -4.00, "width": 8, "height": 8 } } } }, { "name": "weapon-green", "attachments": { "square": { "square": { "name": "green/SpriteTest-green-square", "x": 4.00, "y": -4.00, "width": 8, "height": 8 } } } }, { "name": "weapon-red", "attachments": { "square": { "square": { "name": "red/SpriteTest-red-square", "x": 4.00, "y": -4.00, "width": 8, "height": 8 } } } }] } \ No newline at end of file +{ "skeleton": { "images": "./sprite/", "audio": "./sound/" }, "bones": [ { "name": "root" } ], "slots": [ { "name": "square2", "bone": "root", "attachment": "square2" }, { "name": "square", "bone": "root", "attachment": "square" }], "skins": { "default": { "square2": { "SpriteTest-default-square2": { "x": -3.00, "y": 3.00, "width": 8, "height": 8 } } , "square": { "SpriteTest-green-square": { "x": -11.00, "y": 3.00, "width": 8, "height": 8 } } , "square": { "SpriteTest-red-square": { "x": -11.00, "y": 3.00, "width": 8, "height": 8 } } , "square": { "SpriteTest-blue-square": { "x": -11.00, "y": 3.00, "width": 8, "height": 8 } } } } } \ No newline at end of file diff --git a/media/showcase-v2.6.png b/media/showcase-v2.6.png new file mode 100644 index 0000000000000000000000000000000000000000..dcaffe762dcebf06400719c7e92d45178d3350b7 GIT binary patch literal 24017 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