git repos / saland

commit 29b46a4d

sago007 · 2017-04-29 12:45
29b46a4d763f37465b74d31041c924d9301c6f39 patch · browse files
parent 62f52c51f2bb66c86bb9401cd40b01f7ad744d7f

Added the sagotmx lib

Changed files

A data/maps/Attribution.txt
A data/maps/sample1.tmx
A data/maps/terrain.tsx
A src/sagotmx/tmx_struct.h
diff --git a/data/maps/Attribution.txt b/data/maps/Attribution.txt new file mode 100644 index 0000000..52d5bd0 --- /dev/null +++ b/data/maps/Attribution.txt
@@ -0,0 +1,156 @@
+License
+-------
+
+CC-BY-SA 3.0:
+ - http://creativecommons.org/licenses/by-sa/3.0/
+ - See the file: cc-by-sa-3.0.txt
+GNU GPL 3.0:
+ - http://www.gnu.org/licenses/gpl-3.0.html
+ - See the file: gpl-3.0.txt
+
+Note the file is based on the LCP contest readme so don't expect the exact little pieces used like the base one.
+*Additional license information.
+
+Assets from:
+
+LPC contributors:
+----------------
+
+
+Matthew Nash
+ http://opengameart.org/content/misc-32x32-tiles
+ - Road
+
+Nushio
+ http://opengameart.org/content/lpc-colorful-sand-deep-water
+ - Snow and ice recolor
+
+William.Thompsonj
+ http://opengameart.org/content/lpc-sandrock-alt-colors
+ - Sand and dirt recolor
+
+Adrix89
+
+ - Recolor Nushio snow
+
+Casper Nilsson
+ *GNU GPL 3.0 or later
+ email: casper.nilsson@gmail.com
+ Freenode: CasperN
+ OpenGameArt.org: C.Nilsson
+
+ - LPC C.Nilsson (2D art)
+
+Daniel Eddeland
+ *GNU GPL 3.0 or later
+ - Tilesets of plants, props, food and environments, suitable for farming / fishing sims and other games.
+ - Includes wheat, grass, sand tilesets, fence tilesets and plants such as corn and tomato.
+
+
+Johann CHARLOT
+ *GNU LGPL Version 3.
+ *Later versions are permitted.
+ Homepage http://poufpoufproduction.fr
+ Email johannc@poufpoufproduction.fr
+
+ - Shoot'em up graphic kit
+
+Skyler Robert Colladay
+
+ - FeralFantom's Entry (2D art)
+
+BASE assets:
+------------
+
+Lanea Zimmerman (AKA Sharm)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ - barrel.png
+ - brackish.png
+ - buckets.png
+ - bridges.png
+ - cabinets.png
+ - cement.png
+ - cementstair.png
+ - chests.png
+ - country.png
+ - cup.png
+ - dirt2.png
+ - dirt.png
+ - dungeon.png
+ - grassalt.png
+ - grass.png
+ - holek.png
+ - holemid.png
+ - hole.png
+ - house.png
+ - inside.png
+ - kitchen.png
+ - lava.png
+ - lavarock.png
+ - mountains.png
+ - rock.png
+ - shadow.png
+ - signs.png
+ - stairs.png
+ - treetop.png
+ - trunk.png
+ - waterfall.png
+ - watergrass.png
+ - water.png
+ - princess.png and princess.xcf
+
+
+Stephen Challener (AKA Redshrike)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ - female_walkcycle.png
+ - female_hurt.png
+ - female_slash.png
+ - female_spellcast.png
+ - male_walkcycle.png
+ - male_hurt.png
+ - male_slash.png
+ - male_spellcast.png
+ - male_pants.png
+ - male_hurt_pants.png
+ - male_fall_down_pants.png
+ - male_slash_pants.png
+
+
+Charles Sanchez (AKA CharlesGabriel)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ - bat.png
+ - bee.png
+ - big_worm.png
+ - eyeball.png
+ - ghost.png
+ - man_eater_flower.png
+ - pumpking.png
+ - slime.png
+ - small_worm.png
+ - snake.png
+
+
+Manuel Riecke (AKA MrBeast)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ - hairfemale.png and hairfemale.xcf
+ - hairmale.png and hairmale.xcf
+ - soldier.png
+ - soldier_altcolor.png
+
+
+Daniel Armstrong (AKA HughSpectrum)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Castle work:
+
+ - castlewalls.png
+ - castlefloors.png
+ - castle_outside.png
+ - castlefloors_outside.png
+ - castle_lightsources.png
+
+
diff --git a/data/maps/sample1.tmx b/data/maps/sample1.tmx new file mode 100644 index 0000000..a2a9f1c --- /dev/null +++ b/data/maps/sample1.tmx
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<map version="1.0" orientation="orthogonal" renderorder="right-down" width="100" height="100" tilewidth="32" tileheight="32" nextobjectid="1">
+ <tileset firstgid="1" source="terrain.tsx"/>
+ <layer name="ground_1" width="100" height="100">
+ <data encoding="base64" compression="zlib">
+ eJzt0aENADAMA8Hsv0U7aXkVHks5cNzy36q6AAAAAABDTmN602ZdD33ym+iS2USb3Ca66LLd/7ku2TQBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAGQ9zDLk7
+ </data>
+ </layer>
+ <layer name="ground_2" width="100" height="100">
+ <data encoding="base64" compression="zlib">
+ eJztmztvE0EURseh4Q0JUEIBDY8ECIgSJKDgFSBJTZAgBaEj1AgJKAgFzxpo7UgohIgy5A8QkQL4FTikAHrulfey15Nd74y9u0mY70if7F2vYmuO7p2ZtWNMa6YqxjynvKtkXAhKgX0swUfpfKXx/kb5bo07+/gJH6Xzi8b7N+Wj5YR9LMJH6bCP413GnKD8sXwswEfpSH0k+UC/Kp8d5GFnlF1d8fnVtL46TTmTkrMr+LnKpJ35Y5AylJLhNj8Hu9hHuZmSvSYMJ+34uEOZUZlW6Tf+TrJcSEY9/+5aROaPecrWruzrGfYxbpJ9fKDc9fwMN0y2i5B81D3nEF0f4mA8Cnx0Rh/VxDPy8N6jRqQ+pEb4cdrEjorwwR/rkeffXavIPRPX+ybsQ2pCHmei5+ylCB8h1IYgNeLq4wWlx8S1oXtVN+WV5/trH1wH60y4tSH4zuvs5GVCfF0wD0zsYDQ6fqgSmgvGt2fljdRIKPuMLKRnLXquffNC1wicNPCdR/JGzyMhzd+taGd/mBd2jYR03yqNdueRjXTtpiibO6gte+0buhe9P8zyoR3U6fhQpZEfpn03sray17wh968px/36wUrsIC3ipl0vIa95Bb3WalUjLj60l076WOi41IiPDzjpDPlepNV367aPz3TuUiXOvEl3soU9U7bBjxMu931tH72U7ZRuSk8luX7Y2QA99lEO89rawIkrshepp9RIko+jlH7KsRQfvVFtLJmGDzhxJ2u/nuRjkDJEGW7hQ2pDh52gf2Uj80hSz7pozRF632HvSbJ82F7gJhn5vVxajdhOspLlw3YDJ81Iz2r1/To7SVtPdeIDTpKRe1pZ+3UXL74+4GQ5ss5y/Z1WKy/s4zL3QOPn5Ah8/EN61oJDjWiS5hbZD7KTKx5e4KMZ+Z2vy31fTSsnTFatfDENb1fho4lOvs9NctKrxldqJSnwkI6eR9pxou9tDWCcO0avfdPuoYByWenfoYDlyNzuu94CxSA1Uq/gf91WC67f6YLykPso8FEM5yjnKRccr+caecr7NswfHSNjL2EHtyhjlP3G3QnIBxn7ahR2cIAySalFxz614sM1ygjlesK5kYTXQkB8yPhXo2NJLXqtCC/3KHOUkyYedz43G0VeC8nLY8oG0xh37YEdVE3sSJ7n6UXG/pOJndg+5tTroXjhGpk0sQN5PqaOa9bx7Rze9zVlj2mMN48/j/kpE3uYM81utLf/GakRu0/pfqXrROaZPGpEOxEvevyTzt/P4X1XO+JE+pK40HPKpDrHx3nUCMNO3piGF+lfOrpW+DgEHwz3rbS6mFSRa/JeD0ut6HlDfMyq5yH5kDlEasKeN7QTPpdXjQi6f2kv8sheQvMxph61j1rCa3n7YHSdiAPds0LzIb3KrhVxUlPXFOGD0XOK7lu7KW8Les/VBvuQvqTHvmod63VxUT4E8SIJxQWj94Z6HWX74KynTFCerMgnDQd2MuEQeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARfIXqGm/kQ==
+ </data>
+ </layer>
+</map>
diff --git a/data/maps/terrain.tsx b/data/maps/terrain.tsx new file mode 100644 index 0000000..c3ec9d7 --- /dev/null +++ b/data/maps/terrain.tsx
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<tileset name="Terrain" tilewidth="32" tileheight="32" tilecount="400">
+ <image source="../textures/terrain.png" width="1024" height="1024"/>
+ <terraintypes>
+ <terrain name="Dark Dirt" tile="100"/>
+ <terrain name="Red Dirt" tile="103"/>
+ <terrain name="Black Dirt" tile="106"/>
+ <terrain name="Grey Dirt" tile="109"/>
+ <terrain name="Lava" tile="112"/>
+ <terrain name="Hole" tile="115"/>
+ <terrain name="Red Hole" tile="118"/>
+ <terrain name="Black Hole" tile="121"/>
+ <terrain name="Water" tile="124"/>
+ <terrain name="Full Dirt" tile="537"/>
+ <terrain name="Clean Dirt" tile="537"/>
+ <terrain name="Trans Dirt" tile="97"/>
+ <terrain name="Grass" tile="289"/>
+ <terrain name="Dark Grass" tile="295"/>
+ <terrain name="Short Grass" tile="298"/>
+ <terrain name="Long Grass" tile="301"/>
+ <terrain name="Wheat" tile="304"/>
+ <terrain name="Earth" tile="676"/>
+ <terrain name="Sand" tile="307"/>
+ <terrain name="Sand Water" tile="310"/>
+ <terrain name="Snow" tile="499"/>
+ <terrain name="Snow Water" tile="662"/>
+ <terrain name="Snow Ice" tile="502"/>
+ <terrain name="Ice" tile="496"/>
+ <terrain name="Brick Road" tile="491"/>
+ <terrain name="Sewer" tile="484"/>
+ <terrain name="Sewer Water" tile="481"/>
+ </terraintypes>
+ <tile id="1" terrain="11,11,11,"/>
+ <tile id="2" terrain="11,11,,11"/>
+ <tile id="4" terrain="0,0,0,"/>
+ <tile id="5" terrain="0,0,,0"/>
+ <tile id="7" terrain="1,1,1,"/>
+ <tile id="8" terrain="1,1,,1"/>
+ <tile id="13" terrain="3,3,3,"/>
+ <tile id="14" terrain="3,3,,3"/>
+ <tile id="16" terrain="4,4,4,"/>
+ <tile id="17" terrain="4,4,,4"/>
+ <tile id="19" terrain="5,5,5,"/>
+ <tile id="20" terrain="5,5,,5"/>
+ <tile id="22" terrain="6,6,6,"/>
+ <tile id="23" terrain="6,6,,6"/>
+ <tile id="25" terrain="7,7,7,"/>
+ <tile id="26" terrain="7,7,,7"/>
+ <tile id="28" terrain="8,8,8,"/>
+ <tile id="29" terrain="8,8,,8"/>
+ <tile id="33" terrain="11,,11,11"/>
+ <tile id="34" terrain=",11,11,11"/>
+ <tile id="36" terrain="0,,0,0"/>
+ <tile id="37" terrain=",0,0,0"/>
+ <tile id="39" terrain="1,,1,1"/>
+ <tile id="40" terrain=",1,1,1"/>
+ <tile id="45" terrain="3,,3,3"/>
+ <tile id="46" terrain=",3,3,3"/>
+ <tile id="48" terrain="4,,4,4"/>
+ <tile id="49" terrain=",4,4,4"/>
+ <tile id="51" terrain="5,,5,5"/>
+ <tile id="52" terrain=",5,5,5"/>
+ <tile id="54" terrain="6,,6,6"/>
+ <tile id="55" terrain=",6,6,6"/>
+ <tile id="57" terrain="7,,7,7"/>
+ <tile id="58" terrain=",7,7,7"/>
+ <tile id="60" terrain="8,,8,8"/>
+ <tile id="61" terrain=",8,8,8"/>
+ <tile id="64" terrain=",,,11"/>
+ <tile id="65" terrain=",,11,11"/>
+ <tile id="66" terrain=",,11,"/>
+ <tile id="67" terrain=",,,0"/>
+ <tile id="68" terrain=",,0,0"/>
+ <tile id="69" terrain=",,0,"/>
+ <tile id="70" terrain=",,,1"/>
+ <tile id="71" terrain=",,1,1"/>
+ <tile id="72" terrain=",,1,"/>
+ <tile id="73" terrain=",,,2"/>
+ <tile id="74" terrain=",,2,2"/>
+ <tile id="75" terrain=",,2,"/>
+ <tile id="76" terrain=",,,3"/>
+ <tile id="77" terrain=",,3,3"/>
+ <tile id="78" terrain=",,3,"/>
+ <tile id="79" terrain=",,,4"/>
+ <tile id="80" terrain=",,4,4"/>
+ <tile id="81" terrain=",,4,"/>
+ <tile id="82" terrain=",,,5"/>
+ <tile id="83" terrain=",,5,5"/>
+ <tile id="84" terrain=",,5,"/>
+ <tile id="85" terrain=",,,6"/>
+ <tile id="86" terrain=",,6,6"/>
+ <tile id="87" terrain=",,6,"/>
+ <tile id="88" terrain=",,,7"/>
+ <tile id="89" terrain=",,7,7"/>
+ <tile id="90" terrain=",,7,"/>
+ <tile id="91" terrain=",,,8"/>
+ <tile id="92" terrain=",,8,8"/>
+ <tile id="93" terrain=",,8,"/>
+ <tile id="96" terrain=",11,,11"/>
+ <tile id="97" terrain="11,11,11,11"/>
+ <tile id="98" terrain="11,,11,"/>
+ <tile id="99" terrain=",0,,0"/>
+ <tile id="100" terrain="0,0,0,0"/>
+ <tile id="101" terrain="0,,0,"/>
+ <tile id="102" terrain=",1,,1"/>
+ <tile id="103" terrain="1,1,1,1"/>
+ <tile id="104" terrain="1,,1,"/>
+ <tile id="105" terrain=",2,,2"/>
+ <tile id="106" terrain="2,2,2,2"/>
+ <tile id="107" terrain="2,,2,"/>
+ <tile id="108" terrain=",3,,3"/>
+ <tile id="110" terrain="3,,3,"/>
+ <tile id="111" terrain=",4,,4"/>
+ <tile id="112" terrain="4,4,4,4"/>
+ <tile id="113" terrain="4,,4,"/>
+ <tile id="114" terrain=",5,,5"/>
+ <tile id="115" terrain="5,5,5,5"/>
+ <tile id="116" terrain="5,,5,"/>
+ <tile id="117" terrain=",6,,6"/>
+ <tile id="118" terrain="6,6,6,6"/>
+ <tile id="119" terrain="6,,6,"/>
+ <tile id="120" terrain=",7,,7"/>
+ <tile id="122" terrain="7,,7,"/>
+ <tile id="123" terrain=",8,,8"/>
+ <tile id="125" terrain="8,,8,"/>
+ <tile id="128" terrain=",11,,"/>
+ <tile id="129" terrain="11,11,,"/>
+ <tile id="130" terrain="11,,,"/>
+ <tile id="131" terrain=",0,,"/>
+ <tile id="132" terrain="0,0,,"/>
+ <tile id="133" terrain="0,,,"/>
+ <tile id="134" terrain=",1,,"/>
+ <tile id="135" terrain="1,1,,"/>
+ <tile id="136" terrain="1,,,"/>
+ <tile id="137" terrain=",2,,"/>
+ <tile id="138" terrain="2,2,,"/>
+ <tile id="139" terrain="2,,,"/>
+ <tile id="140" terrain=",3,,"/>
+ <tile id="141" terrain="3,3,,"/>
+ <tile id="142" terrain="3,,,"/>
+ <tile id="143" terrain=",4,,"/>
+ <tile id="144" terrain="4,4,,"/>
+ <tile id="145" terrain="4,,,"/>
+ <tile id="146" terrain=",5,,"/>
+ <tile id="147" terrain="5,5,,"/>
+ <tile id="148" terrain="5,,,"/>
+ <tile id="149" terrain=",6,,"/>
+ <tile id="150" terrain="6,6,,"/>
+ <tile id="151" terrain="6,,,"/>
+ <tile id="152" terrain=",7,,"/>
+ <tile id="153" terrain="7,7,,"/>
+ <tile id="154" terrain="7,,,"/>
+ <tile id="155" terrain=",8,,"/>
+ <tile id="156" terrain="8,8,,"/>
+ <tile id="157" terrain="8,,,"/>
+ <tile id="160" terrain="9,9,9,9"/>
+ <tile id="161" terrain="9,9,9,9"/>
+ <tile id="162" terrain="9,9,9,9"/>
+ <tile id="163" terrain="0,0,0,0"/>
+ <tile id="164" terrain="0,0,0,0"/>
+ <tile id="165" terrain="0,0,0,0"/>
+ <tile id="166" terrain="1,1,1,1"/>
+ <tile id="167" terrain="1,1,1,1"/>
+ <tile id="168" terrain="1,1,1,1"/>
+ <tile id="169" terrain="2,2,2,2"/>
+ <tile id="170" terrain="2,2,2,2"/>
+ <tile id="171" terrain="2,2,2,2"/>
+ <tile id="172" terrain="3,3,3,3"/>
+ <tile id="173" terrain="3,3,3,3"/>
+ <tile id="174" terrain="3,3,3,3"/>
+ <tile id="175" terrain="4,4,4,4"/>
+ <tile id="176" terrain="4,4,4,4"/>
+ <tile id="177" terrain="4,4,4,4"/>
+ <tile id="184" terrain="7,7,7,7"/>
+ <tile id="185" terrain="7,7,7,7"/>
+ <tile id="186" terrain="7,7,7,7"/>
+ <tile id="187" terrain="8,8,8,8"/>
+ <tile id="188" terrain="8,8,8,8"/>
+ <tile id="189" terrain="8,8,8,8"/>
+ <tile id="193" terrain="12,12,12,"/>
+ <tile id="194" terrain="12,12,,12"/>
+ <tile id="196" terrain="12,12,12,"/>
+ <tile id="197" terrain="12,12,,12"/>
+ <tile id="199" terrain="13,13,13,"/>
+ <tile id="200" terrain="13,13,,13"/>
+ <tile id="202" terrain="14,14,14,"/>
+ <tile id="203" terrain="14,14,,14"/>
+ <tile id="205" terrain="15,15,15,"/>
+ <tile id="206" terrain="15,15,,15"/>
+ <tile id="208" terrain="16,16,16,"/>
+ <tile id="209" terrain="16,16,,16"/>
+ <tile id="211" terrain="18,18,18,"/>
+ <tile id="212" terrain="18,18,,18"/>
+ <tile id="214" terrain="19,19,19,"/>
+ <tile id="215" terrain="19,19,,19"/>
+ <tile id="225" terrain="12,,12,12"/>
+ <tile id="226" terrain=",12,12,12"/>
+ <tile id="228" terrain="12,,12,12"/>
+ <tile id="229" terrain=",12,12,12"/>
+ <tile id="231" terrain="13,,13,13"/>
+ <tile id="232" terrain=",13,13,13"/>
+ <tile id="234" terrain="14,,14,14"/>
+ <tile id="235" terrain=",14,14,14"/>
+ <tile id="237" terrain="15,,15,15"/>
+ <tile id="238" terrain=",15,15,15"/>
+ <tile id="240" terrain="16,,16,16"/>
+ <tile id="241" terrain=",16,16,16"/>
+ <tile id="243" terrain="18,,18,18"/>
+ <tile id="244" terrain=",18,18,18"/>
+ <tile id="246" terrain="19,,19,19"/>
+ <tile id="247" terrain=",19,19,19"/>
+ <tile id="256" terrain=",,,12"/>
+ <tile id="257" terrain=",,12,12"/>
+ <tile id="258" terrain=",,12,"/>
+ <tile id="259" terrain=",,,12"/>
+ <tile id="260" terrain=",,12,12"/>
+ <tile id="261" terrain=",,12,"/>
+ <tile id="262" terrain=",,,13"/>
+ <tile id="263" terrain=",,13,13"/>
+ <tile id="264" terrain=",,13,"/>
+ <tile id="265" terrain=",,,14"/>
+ <tile id="266" terrain=",,14,14"/>
+ <tile id="267" terrain=",,14,"/>
+ <tile id="268" terrain=",,,15"/>
+ <tile id="269" terrain=",,15,15"/>
+ <tile id="270" terrain=",,15,"/>
+ <tile id="271" terrain=",,,16"/>
+ <tile id="272" terrain=",,16,16"/>
+ <tile id="273" terrain=",,16,"/>
+ <tile id="274" terrain=",,,18"/>
+ <tile id="275" terrain=",,18,18"/>
+ <tile id="276" terrain=",,18,"/>
+ <tile id="277" terrain=",,,19"/>
+ <tile id="278" terrain=",,19,19"/>
+ <tile id="279" terrain=",,19,"/>
+ <tile id="288" terrain=",12,,12"/>
+ <tile id="290" terrain="12,,12,"/>
+ <tile id="291" terrain=",12,,12"/>
+ <tile id="292" terrain="12,12,12,12"/>
+ <tile id="293" terrain="12,,12,"/>
+ <tile id="294" terrain=",13,,13"/>
+ <tile id="295" terrain="13,13,13,13"/>
+ <tile id="296" terrain="13,,13,"/>
+ <tile id="297" terrain=",14,,14"/>
+ <tile id="298" terrain="14,14,14,14"/>
+ <tile id="299" terrain="14,,14,"/>
+ <tile id="300" terrain=",15,,15"/>
+ <tile id="301" terrain="15,15,15,15"/>
+ <tile id="302" terrain="15,,15,"/>
+ <tile id="303" terrain=",16,,16"/>
+ <tile id="304" terrain="16,16,16,16"/>
+ <tile id="305" terrain="16,,16,"/>
+ <tile id="306" terrain=",18,,18"/>
+ <tile id="307" terrain="18,18,18,18"/>
+ <tile id="308" terrain="18,,18,"/>
+ <tile id="309" terrain=",19,,19"/>
+ <tile id="310" terrain="19,19,19,19"/>
+ <tile id="311" terrain="19,,19,"/>
+ <tile id="320" terrain=",12,,"/>
+ <tile id="321" terrain="12,12,,"/>
+ <tile id="322" terrain="12,,,"/>
+ <tile id="323" terrain=",12,,"/>
+ <tile id="324" terrain="12,12,,"/>
+ <tile id="325" terrain="12,,,"/>
+ <tile id="326" terrain=",13,,"/>
+ <tile id="327" terrain="13,13,,"/>
+ <tile id="328" terrain="13,,,"/>
+ <tile id="329" terrain=",14,,"/>
+ <tile id="330" terrain="14,14,,"/>
+ <tile id="331" terrain="14,,,"/>
+ <tile id="332" terrain=",15,,"/>
+ <tile id="333" terrain="15,15,,"/>
+ <tile id="334" terrain="15,,,"/>
+ <tile id="335" terrain=",16,,"/>
+ <tile id="336" terrain="16,16,,"/>
+ <tile id="337" terrain="16,,,"/>
+ <tile id="338" terrain=",18,,"/>
+ <tile id="339" terrain="18,18,,"/>
+ <tile id="340" terrain="18,,,"/>
+ <tile id="341" terrain=",19,,"/>
+ <tile id="342" terrain="19,19,,"/>
+ <tile id="343" terrain="19,,,"/>
+ <tile id="352" terrain="12,12,12,12"/>
+ <tile id="353" terrain="12,12,12,12"/>
+ <tile id="354" terrain="12,12,12,12"/>
+ <tile id="358" terrain="13,13,13,13"/>
+ <tile id="359" terrain="13,13,13,13"/>
+ <tile id="360" terrain="13,13,13,13"/>
+ <tile id="370" terrain="18,18,18,18"/>
+ <tile id="371" terrain="18,18,18,18"/>
+ <tile id="372" terrain="18,18,18,18"/>
+ <tile id="385" terrain="26,26,26,"/>
+ <tile id="386" terrain="26,26,,26"/>
+ <tile id="388" terrain="25,25,25,"/>
+ <tile id="389" terrain="25,25,,25"/>
+ <tile id="395" terrain="24,24,24,"/>
+ <tile id="396" terrain="24,24,,"/>
+ <tile id="397" terrain="24,24,,24"/>
+ <tile id="398" terrain="24,24,24,24"/>
+ <tile id="400" terrain="23,23,23,"/>
+ <tile id="401" terrain="23,23,,23"/>
+ <tile id="403" terrain="20,20,20,"/>
+ <tile id="404" terrain="20,20,,20"/>
+ <tile id="406" terrain="22,22,22,"/>
+ <tile id="407" terrain="22,22,,22"/>
+ <tile id="417" terrain="26,,26,26"/>
+ <tile id="418" terrain=",26,26,26"/>
+ <tile id="420" terrain="25,,25,25"/>
+ <tile id="421" terrain=",25,25,25"/>
+ <tile id="427" terrain="24,,24,"/>
+ <tile id="429" terrain=",24,,24"/>
+ <tile id="430" terrain="24,24,24,24"/>
+ <tile id="432" terrain="23,,23,23"/>
+ <tile id="433" terrain=",23,23,23"/>
+ <tile id="435" terrain="20,,20,20"/>
+ <tile id="436" terrain=",20,20,20"/>
+ <tile id="438" terrain="22,,22,22"/>
+ <tile id="439" terrain=",22,22,22"/>
+ <tile id="448" terrain=",,,26"/>
+ <tile id="449" terrain=",,26,26"/>
+ <tile id="450" terrain=",,26,"/>
+ <tile id="451" terrain=",,,25"/>
+ <tile id="452" terrain=",,25,25"/>
+ <tile id="453" terrain=",,25,"/>
+ <tile id="459" terrain="24,,24,24"/>
+ <tile id="460" terrain=",,24,24"/>
+ <tile id="461" terrain=",24,24,24"/>
+ <tile id="462" terrain="24,24,24,24"/>
+ <tile id="463" terrain=",,,23"/>
+ <tile id="464" terrain=",,23,23"/>
+ <tile id="465" terrain=",,23,"/>
+ <tile id="466" terrain=",,,20"/>
+ <tile id="467" terrain=",,20,20"/>
+ <tile id="468" terrain=",,20,"/>
+ <tile id="469" terrain=",,,22"/>
+ <tile id="470" terrain=",,22,22"/>
+ <tile id="471" terrain=",,22,"/>
+ <tile id="480" terrain=",26,,26"/>
+ <tile id="482" terrain="26,,26,"/>
+ <tile id="483" terrain=",25,,25"/>
+ <tile id="484" terrain="25,25,25,25"/>
+ <tile id="485" terrain="25,,25,"/>
+ <tile id="491" terrain="24,24,24,24"/>
+ <tile id="492" terrain="24,24,24,24"/>
+ <tile id="493" terrain="24,24,24,24"/>
+ <tile id="494" terrain="24,24,24,24"/>
+ <tile id="495" terrain=",23,,23"/>
+ <tile id="496" terrain="23,23,23,23"/>
+ <tile id="497" terrain="23,,23,"/>
+ <tile id="498" terrain=",20,,20"/>
+ <tile id="499" terrain="20,20,20,20"/>
+ <tile id="500" terrain="20,,20,"/>
+ <tile id="501" terrain=",22,,22"/>
+ <tile id="502" terrain="22,22,22,22"/>
+ <tile id="503" terrain="22,,22,"/>
+ <tile id="504" terrain="9,9,9,10"/>
+ <tile id="505" terrain="9,9,10,10"/>
+ <tile id="506" terrain="9,9,10,9"/>
+ <tile id="507" terrain="10,10,10,9"/>
+ <tile id="508" terrain="10,10,9,10"/>
+ <tile id="512" terrain=",26,,"/>
+ <tile id="513" terrain="26,26,,"/>
+ <tile id="514" terrain="26,,,"/>
+ <tile id="515" terrain=",25,,"/>
+ <tile id="516" terrain="25,25,,"/>
+ <tile id="517" terrain="25,,,"/>
+ <tile id="524" terrain=",,,24"/>
+ <tile id="525" terrain=",,24,"/>
+ <tile id="527" terrain=",23,,"/>
+ <tile id="528" terrain="23,23,,"/>
+ <tile id="529" terrain="23,,,"/>
+ <tile id="530" terrain=",20,,"/>
+ <tile id="531" terrain="20,20,,"/>
+ <tile id="532" terrain="20,,,"/>
+ <tile id="533" terrain=",22,,"/>
+ <tile id="534" terrain="22,22,,"/>
+ <tile id="535" terrain="22,,,"/>
+ <tile id="536" terrain="9,10,9,10"/>
+ <tile id="537" terrain="10,10,10,10"/>
+ <tile id="538" terrain="10,9,10,9"/>
+ <tile id="539" terrain="10,9,10,10"/>
+ <tile id="540" terrain="9,10,10,10"/>
+ <tile id="544" terrain="26,26,26,26"/>
+ <tile id="545" terrain="26,26,26,26"/>
+ <tile id="546" terrain="26,26,26,26"/>
+ <tile id="547" terrain="25,25,25,25"/>
+ <tile id="548" terrain="25,25,25,25"/>
+ <tile id="549" terrain="25,25,25,25"/>
+ <tile id="556" terrain=",24,,"/>
+ <tile id="557" terrain="24,,,"/>
+ <tile id="559" terrain="23,23,23,23"/>
+ <tile id="560" terrain="23,23,23,23"/>
+ <tile id="561" terrain="23,23,23,23"/>
+ <tile id="562" terrain="20,20,20,20"/>
+ <tile id="563" terrain="20,20,20,20"/>
+ <tile id="564" terrain="20,20,20,20"/>
+ <tile id="566" terrain="21,21,21,"/>
+ <tile id="567" terrain="21,21,,21"/>
+ <tile id="568" terrain="9,10,9,9"/>
+ <tile id="569" terrain="10,10,9,9"/>
+ <tile id="570" terrain="10,9,9,9"/>
+ <tile id="571" terrain="10,10,10,10"/>
+ <tile id="572" terrain="10,10,10,10"/>
+ <tile id="580" terrain="17,17,17,"/>
+ <tile id="581" terrain="17,17,,17"/>
+ <tile id="598" terrain="21,,21,21"/>
+ <tile id="599" terrain=",21,21,21"/>
+ <tile id="600" terrain="9,9,9,9"/>
+ <tile id="601" terrain="9,9,9,9"/>
+ <tile id="602" terrain="9,9,9,9"/>
+ <tile id="603" terrain="9,9,9,9"/>
+ <tile id="604" terrain="9,9,9,9"/>
+ <tile id="612" terrain="17,,17,17"/>
+ <tile id="613" terrain=",17,17,17"/>
+ <tile id="629" terrain=",,,21"/>
+ <tile id="630" terrain=",,21,21"/>
+ <tile id="631" terrain=",,21,"/>
+ <tile id="643" terrain=",,,17"/>
+ <tile id="644" terrain=",,17,17"/>
+ <tile id="645" terrain=",,17,"/>
+ <tile id="661" terrain=",21,,21"/>
+ <tile id="662" terrain="21,21,21,21"/>
+ <tile id="663" terrain="21,,21,"/>
+ <tile id="675" terrain=",17,,17"/>
+ <tile id="676" terrain="17,17,17,17"/>
+ <tile id="677" terrain="17,,17,"/>
+ <tile id="693" terrain=",21,,"/>
+ <tile id="694" terrain="21,21,,"/>
+ <tile id="695" terrain="21,,,"/>
+ <tile id="707" terrain=",17,,"/>
+ <tile id="708" terrain="17,17,,"/>
+ <tile id="709" terrain="17,,,"/>
+</tileset>
diff --git a/src/sagotmx/tmx_struct.h b/src/sagotmx/tmx_struct.h new file mode 100644 index 0000000..16c6077 --- /dev/null +++ b/src/sagotmx/tmx_struct.h
@@ -0,0 +1,481 @@
+/*
+This is a small library for reading and writing (!) Tiled map files
+It is designed especially for reading the default map format produced by Tiled 0.14.2 (http://www.mapeditor.org/)
+
+Another feature is that files can be loaded from memory. Mostly to use it with PhysFS
+This does put a bit of extra pressure on the user because if the TileSet in ints own file the user must provide it.
+
+It still has some limitations:
+* Cannot auto load the tileset (cannot access the filesystem)
+* Only one (1) TileSet
+* No functions to actually change the tilemap
+
+Compiles with g++ and requires C++11 support.
+
+Requirements:
+* zlib (http://www.zlib.net/)
+* rapidxml (http://rapidxml.sourceforge.net/)
+* b64 (http://libb64.sourceforge.net/)
+
+#License
+Provided under the MIT license. The license is as follows:
+Copyright (c) 2017 Poul Sander
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+ */
+
+#ifndef TMX_STRUCT_H
+#define TMX_STRUCT_H
+
+#include "rapidxml/rapidxml.hpp"
+
+#include <string>
+#include <vector>
+#include <zlib.h>
+#include <iostream>
+#include "b64/decode.h"
+#include "b64/encode.h"
+
+namespace sago {
+namespace tiled {
+
+class SagoTiledException : public std::exception {
+ char errMsg[256];
+public:
+ SagoTiledException() {
+ errMsg[0] = '\0';
+ }
+
+ SagoTiledException(const char* fmt, ...) __attribute__ ((format (printf, 2, 3))) {
+ va_list args;
+ va_start(args, fmt);
+ vsnprintf(errMsg, sizeof(errMsg), fmt, args);
+ va_end(args);
+ }
+
+ virtual const char* what() const noexcept override {
+ return errMsg;
+ }
+
+};
+
+inline void* z_alloc(void *opaque __attribute__((unused)), unsigned int items, unsigned int size) {
+ return realloc(NULL, items *size);
+}
+
+inline void z_free(void *opaque __attribute__((unused)), void *address) {
+ free(address);
+}
+
+inline std::string zlib_decompress(const char *source, unsigned int slength) {
+ std::string res;
+ char buffer[4096];
+ z_stream strm;
+
+ strm.zalloc = z_alloc;
+ strm.zfree = z_free;
+ strm.opaque = Z_NULL;
+ strm.next_in = (Bytef*)source;
+ strm.avail_in = slength;
+ strm.next_out = (Bytef*)buffer;
+ strm.avail_out = sizeof(buffer);
+
+ int ret=inflateInit2(&strm, 15 + 32);
+ if (ret != Z_OK) {
+ throw SagoTiledException("zlib error: inflateInit2 returned %d", ret);
+ }
+
+ while (ret == Z_OK) {
+ ret = inflate(&strm, Z_NO_FLUSH);
+ std::cout << "Read some\n";
+ if (ret == Z_OK || ret == Z_STREAM_END) {
+ res.append(buffer, sizeof(buffer));
+ strm.next_out = (Bytef*)buffer;
+ strm.avail_out = sizeof(buffer);
+ }
+ }
+
+ if ( ret != Z_STREAM_END) {
+ inflateEnd(&strm);
+ throw SagoTiledException("zlib error: inflate returned %d", ret);
+ }
+ res.resize(strm.total_out);
+
+ inflateEnd(&strm);
+
+ return res;
+}
+
+inline std::string zlib_compress(const std::string& source) {
+ std::string res;
+ char buffer[1024];
+ z_stream strm;
+
+ strm.zalloc = z_alloc;
+ strm.zfree = z_free;
+ strm.opaque = Z_NULL;
+ strm.next_in = (Bytef*)source.data();
+ strm.avail_in = source.size();
+ strm.next_out = (Bytef*)buffer;
+ strm.avail_out = sizeof(buffer);
+
+ int ret = deflateInit2(&strm, Z_BEST_SPEED,Z_DEFLATED, 15 | 16,
+ 8,
+ Z_DEFAULT_STRATEGY);
+ if (ret != Z_OK) {
+ throw SagoTiledException("zlib error: deflateInit2 returned %d", ret);
+ }
+ while (ret == Z_OK) {
+ ret = deflate(&strm, Z_FINISH);
+ if (ret == Z_OK || ret == Z_STREAM_END) {
+ res.append(buffer, sizeof(buffer));
+ strm.next_out = (Bytef*)buffer;
+ strm.avail_out = sizeof(buffer);
+ }
+ }
+ if ( ret != Z_STREAM_END) {
+ deflateEnd(&strm);
+ throw SagoTiledException("zlib error: deflate returned %d", ret);
+ }
+ res.resize(strm.total_out);
+
+ deflateEnd(&strm);
+ return res;
+}
+
+const char* const b64enc = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+/**
+ * This functions will skip whitespace until it finds a base64 encoding charecter. It will then decode it and decompress it.
+ * @param data base64 encoded data of a zlib compressed array of gids_count uint32 elements.
+ * @param gids_count Number of elements in the result.
+ * @return The raw result. will be 4*gids_count large.
+ */
+inline std::string string_decompress_decode(const std::string &data)
+{
+ std::size_t found = data.find_first_of(b64enc);
+ if (found == std::string::npos) {
+ std::cerr << "Warning: Layer without data... this is most likely a mistake.\n";
+ return "";
+ }
+ std::string compressed_str;
+ compressed_str.resize(data.length());
+ base64::decoder decoder;
+ decoder.decode(&data[found], data.length()-found, &compressed_str[0]);
+ return zlib_decompress(compressed_str.c_str(), compressed_str.length());
+}
+
+inline std::string string_encode( const std::string& data) {
+ std::stringstream ret;
+ std::stringstream input(data);
+ base64::encoder E;
+ E.encode(input, ret);
+ return ret.str();
+}
+
+struct Terrain {
+ std::string name;
+ int tile;
+};
+
+struct TerrainTypes {
+ std::vector<Terrain> terrains;
+};
+
+struct Tile {
+ int id = 0;
+ std::string terrain;
+ std::string probability;
+};
+
+struct Image {
+ std::string source;
+ int width = 0;
+ int height = 0;
+};
+
+
+struct TileSet {
+ std::string firstgid;
+ std::string source;
+ TileSet* alternativeSource = nullptr; //< Set to non-null to use an alternative TileSet. Must be set if source is set.
+ std::string name;
+ int tilewidth = 0;
+ int tileheight = 0;
+ int spacing = 0;
+ int margin = 0;
+ int tilecount = 0;
+ int columns = 0;
+ Image image;
+ std::vector<Terrain> terrainTypes;
+ std::vector<Tile> tiles;
+ std::map<int, Tile> tiles_map;
+};
+
+struct TileLayerData {
+ std::string encoding;
+ std::string compression;
+ std::string payload;
+};
+
+struct TileLayer {
+ std::string name;
+ int width=0;
+ int height=0;
+ TileLayerData data;
+};
+
+struct TileMap {
+ std::string version;
+ std::string orientation;
+ std::string renderorder;
+ int width = 0;
+ int height = 0;
+ int tilewidth=0;
+ int tileheight=0;
+ int nextobjectid = 0;
+ TileSet tileset;
+ std::vector<TileLayer> layers;
+};
+
+inline void setValueFromAttribute(rapidxml::xml_node<> * node, const char* name, std::string& result) {
+ auto val = node->first_attribute(name);
+ if (val) {
+ result = val->value();
+ }
+}
+
+inline void setValueFromAttribute(rapidxml::xml_node<> * node, const char* name, int& result) {
+ auto val = node->first_attribute(name);
+ if (val) {
+ result = std::stoi(val->value());
+ }
+}
+
+inline rapidxml::xml_node<> * getElement(rapidxml::xml_node<> * node, const char* name) {
+ auto val = node->first_node(name);
+ if (!val) {
+ throw new SagoTiledException("Failed to find mandatory valye: %s on %s", name, node->name());
+ }
+ return val;
+}
+
+inline rapidxml::xml_node<> * getElement(rapidxml::xml_node<> * node, const char* name, bool& found) {
+ auto val = node->first_node(name);
+ found = val;
+ return val;
+}
+
+inline TileSet node2tileset(rapidxml::xml_node<> * tileset_node) {
+ TileSet ts;
+ setValueFromAttribute( tileset_node, "name", ts.name);
+ setValueFromAttribute( tileset_node, "source", ts.source);
+ setValueFromAttribute( tileset_node, "tilewidth", ts.tilewidth);
+ setValueFromAttribute( tileset_node, "tileheight", ts.tileheight);
+ setValueFromAttribute( tileset_node, "tilecount", ts.tilecount);
+ setValueFromAttribute( tileset_node, "firstgid", ts.firstgid);
+ bool found;
+ rapidxml::xml_node<> * image_node = getElement(tileset_node, "image", found);
+ if (found) {
+ setValueFromAttribute(image_node, "source", ts.image.source);
+ setValueFromAttribute(image_node, "width", ts.image.width);
+ setValueFromAttribute(image_node, "height", ts.image.height);
+ }
+ rapidxml::xml_node<> * terraintypes_node = tileset_node->first_node("terraintypes");
+ if (terraintypes_node) {
+ for (rapidxml::xml_node<> * terrain_node = terraintypes_node->first_node("terrain"); terrain_node; terrain_node = terrain_node->next_sibling()) {
+ Terrain t;
+ setValueFromAttribute(terrain_node, "name", t.name);
+ setValueFromAttribute(terrain_node, "tile", t.tile);
+ ts.terrainTypes.push_back(t);
+ }
+ }
+ for (rapidxml::xml_node<> * tile_node = tileset_node->first_node("tile"); tile_node; tile_node = tile_node->next_sibling()) {
+ Tile t;
+ setValueFromAttribute(tile_node, "id", t.id);
+ setValueFromAttribute(tile_node, "terrain", t.terrain);
+ setValueFromAttribute(tile_node, "probability", t.probability);
+ ts.tiles_map[t.id] = t;
+ ts.tiles.push_back(t);
+ }
+ return ts;
+}
+
+inline TileSet string2tileset(const std::string& tsx_content) {
+ std::string tsx_parseable_content = tsx_content;
+ rapidxml::xml_document<> doc; // character type defaults to char
+ char* parsable_pointer = &tsx_parseable_content[0]; //Legal from C++11 and forward
+ doc.parse<0>(parsable_pointer);
+ rapidxml::xml_node<> * root_node = doc.first_node("tileset");
+ return node2tileset(root_node);
+}
+
+inline TileMap string2tilemap(const std::string& tmx_content) {
+ TileMap m;
+ std::string tmx_parseable_content = tmx_content;
+ rapidxml::xml_document<> doc; // character type defaults to char
+ char* parsable_pointer = &tmx_parseable_content[0]; //Legal from C++11 and forward
+ doc.parse<0>(parsable_pointer);
+ rapidxml::xml_node<> * root_node = doc.first_node("map");
+ setValueFromAttribute( root_node, "verion", m.version);
+ setValueFromAttribute( root_node, "orientation", m.orientation);
+ setValueFromAttribute( root_node, "renderorder", m.renderorder);
+ setValueFromAttribute( root_node, "width", m.width);
+ setValueFromAttribute( root_node, "height", m.height);
+ setValueFromAttribute( root_node, "tilewidth", m.tilewidth);
+ setValueFromAttribute( root_node, "tileheight", m.tileheight);
+ setValueFromAttribute( root_node, "nextobjectid", m.nextobjectid);
+ auto tileset_node = getElement(root_node, "tileset");
+ m.tileset = node2tileset(tileset_node);
+ for (rapidxml::xml_node<> * layer_node = root_node->first_node("layer"); layer_node; layer_node = layer_node->next_sibling()) {
+ TileLayer tl;
+ setValueFromAttribute(layer_node, "name", tl.name);
+ setValueFromAttribute(layer_node, "height", tl.height);
+ setValueFromAttribute(layer_node, "width", tl.width);
+ auto data_node = getElement(layer_node, "data");
+ setValueFromAttribute(data_node, "encoding", tl.data.encoding);
+ setValueFromAttribute(data_node, "compression", tl.data.compression);
+ std::string compressed_payload = data_node->value();
+ tl.data.payload = sago::tiled::string_decompress_decode(compressed_payload);
+ m.layers.push_back(tl);
+ }
+ return m;
+}
+
+inline void xml_add_attribute(std::iostream& io, const std::string& name, const std::string& value) {
+ if (value.length()) {
+ io << " " << name << "=\"" << value << "\"";
+ }
+}
+
+inline void xml_add_attribute(std::iostream& io, const char* name, int value) {
+ if (value) {
+ io << " " << name << "=\"" << value << "\"";
+ }
+}
+
+inline void xml_add_tileset(std::iostream& io, const TileMap& m) {
+ const auto& ts = m.tileset;
+ io << "<tileset";
+ xml_add_attribute(io, "firstgid", ts.firstgid);
+ xml_add_attribute(io, "source", ts.source);
+ io << "/>\n";
+}
+
+inline void xml_add_layer(std::iostream& io, const TileMap& m, size_t layer_number) {
+ const TileLayer& l = m.layers.at(layer_number);
+ io << "<layer";
+ xml_add_attribute(io, "name", l.name);
+ xml_add_attribute(io, "height", l.height);
+ xml_add_attribute(io, "width", l.width);
+ io << ">\n";
+ io << "<data encoding=\"base64\" compression=\"zlib\">\n";
+ io << string_encode(zlib_compress(l.data.payload));
+ io << "</data>\n";
+ io << "</layer>\n";
+}
+
+inline std::string tilemap2string(const TileMap& m) {
+ //Assuming UTF-8 because rapidxml ignores it.
+ std::stringstream ret;
+ ret << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
+ ret << "<map version=\"1.0\"";
+ xml_add_attribute(ret, "orientation", m.orientation);
+ xml_add_attribute(ret, "renderorder", m.renderorder);
+ xml_add_attribute(ret, "width", m.width);
+ xml_add_attribute(ret, "height", m.height);
+ xml_add_attribute(ret, "tilewidth", m.tilewidth);
+ xml_add_attribute(ret, "tileheight", m.tileheight);
+ xml_add_attribute(ret, "nextobjectid", m.nextobjectid);
+ ret << ">\n";
+ xml_add_tileset(ret, m);
+ for (size_t i = 0; i < m.layers.size(); ++i) {
+ xml_add_layer(ret, m, i);
+ }
+ ret << "</map>\n";
+ return ret.str();
+}
+
+/**
+ * This function returns the coordinates from a texture to find the gid.
+ * Note that this might not work correctly at the moment and will fail in case of more than one tileset
+ * @param tm The map to take the tileset from,
+ * @param gid The gid to use. Note that this must be 1 or larger. An invalid gid yilds undefined behaivior.
+ * @param[out] imageFile The image filename will be written to this pointer if not NULL. May be null.
+ * @param[out] x The X coordinate will be written to this pointer if not NULL. May be null.
+ * @param[out] y The y coordinate will be written to this pointer if not NULL. May be null.
+ * @param[out] w The tile width will be written to this pointer if not NULL. May be null.
+ * @param[out] h The tile height will be written to this pointer if not NULL. May be null.
+ */
+inline void getTextureLocationFromGid(const TileMap& tm, int gid, std::string* imageFile, int* x, int* y, int* w, int* h ) {
+ //Currently hardcoded to one tileset
+ const TileSet *ts = &(tm.tileset);
+ //TODO: Check this. Is "firstgid" from the tiledset related?
+ gid--; //Gids starts at 1 by default
+ while (ts->alternativeSource) {
+ //Follow source links
+ ts = ts->alternativeSource;
+ }
+ if (imageFile) {
+ *imageFile = ts->image.source;
+ }
+ if (x) {
+ *x = ( gid *ts->tilewidth)%ts->image.width;
+ }
+ if (y) {
+ *y = ( gid *ts->tilewidth)/ts->image.width* ts->tilewidth;
+ }
+ if (w) {
+ *w = ts->tilewidth;
+ }
+ if (h) {
+ *h = ts->tileheight;
+ }
+}
+
+/**
+ * This function tells the gid of the tile in a given location on a given map, on a given layer
+ *
+ * If the layer is corrupt or the coordinates out of bound then the behavior is unspecified.
+ * It may return the wrong gid or throw a SagoTiledException
+ *
+ * @param m The TileMap to look at. Required because the total size are located here
+ * @param l The layer to look at
+ * @param x The X coordinate
+ * @param y The Y coordiante
+ * @return The gid number of the given tile. Provided that X and Y are within the map limits
+ */
+inline uint32_t getTileFromLayer(const TileMap& m, const TileLayer& l, int x, int y) {
+ size_t tile_index = (m.height*y+x)*sizeof(uint32_t);
+ if (tile_index > l.data.payload.size()-sizeof(uint32_t) ) {
+ throw SagoTiledException("ERROR: getTileFromLayer called with coordiantes out-of-bound. Called with (%d, %d). Limit (%d, %d). Or the layer is corrupt. "
+ "Reported number of tiles in layer: %ld", x, y, m.width-1, m.height-1, l.data.payload.size()/sizeof(uint32_t));
+ }
+ const unsigned char *data = reinterpret_cast<const unsigned char*>(l.data.payload.data());
+ uint32_t global_tile_id = data[tile_index] |
+ data[tile_index + 1] << 8 |
+ data[tile_index + 2] << 16 |
+ data[tile_index + 3] << 24;
+ return global_tile_id;
+}
+
+} //tiled
+} //sago
+
+#endif /* TMX_STRUCT_H */
+