<?xml version="1.0" encoding="utf-8"?>

<!--
  format 1.0.0 by
    Tiled Developers (mapeditor.org)
  documented in schema form originally by
    Olivier.Beaton@quadir.net
    Creative Commons Attribution 3.0
    http://creativecommons.org/licenses/by/3.0/
  amended by
    Asser Fahrenholz
  last updated on
    31-10-2016
-->

<xs:schema version="0.7.0" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://mapeditor.org" xmlns="http://mapeditor.org" elementFormDefault="qualified">

  <!--
  types
-->

  <xs:simpleType name="pixelT">
    <xs:restriction base="xs:nonNegativeInteger"></xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="encodingT">
    <xs:restriction base="xs:NMTOKEN">
      <xs:enumeration value="base64" />
      <xs:enumeration value="csv" />
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="compressionT">
    <xs:restriction base="xs:NMTOKEN">
      <xs:enumeration value="gzip" />
      <xs:enumeration value="zlib" />
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="nameT">
    <xs:restriction base="xs:string">
      <xs:minLength value="1"/>
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="draworderT">
    <xs:restriction base="xs:NMTOKEN">
      <xs:enumeration value="index" />
      <xs:enumeration value="topdown" />
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="staggeraxisT">
    <xs:restriction base="xs:NMTOKEN">
      <xs:enumeration value="x" />
      <xs:enumeration value="y" />
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="imageformatT">
    <xs:restriction base="xs:NMTOKEN">
      <xs:enumeration value="png" />
      <xs:enumeration value="gif" />
      <xs:enumeration value="jpg" />
      <xs:enumeration value="bmp" />
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="degreesT">
    <xs:restriction base="xs:double">
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="opacityT">
    <xs:restriction base="xs:float">
      <xs:maxInclusive value="1"/>
      <xs:minInclusive value="0"/>
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="tileId">
    <xs:restriction base="xs:nonNegativeInteger"/>
  </xs:simpleType>

  <xs:simpleType name="staggerindexT">
    <xs:restriction base="xs:NMTOKEN">
      <xs:enumeration value="even" />
      <xs:enumeration value="odd" />
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="propertytypeT">
    <xs:restriction base="xs:NMTOKEN">
      <xs:enumeration value="string" />
      <xs:enumeration value="int" />
      <xs:enumeration value="float" />
      <xs:enumeration value="bool" />
      <xs:enumeration value="color" />
      <xs:enumeration value="file" />
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="orientationT">
    <xs:restriction base="xs:NMTOKEN">
      <xs:enumeration value="orthogonal" />
      <xs:enumeration value="isometric" />
      <xs:enumeration value="hexagonal" />
      <xs:enumeration value="shifted" />
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="renderorderT">
    <xs:restriction base="xs:NMTOKEN">
      <xs:enumeration value="right-down" />
      <xs:enumeration value="right-up" />
      <xs:enumeration value="left-down" />
      <xs:enumeration value="left-up" />
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="formatT">
    <xs:restriction base="xs:NMTOKEN">
      <xs:enumeration value="png" />
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="cornerterrainT">
    <xs:restriction base="xs:string">
      <xs:pattern value="[0-9]{1,3},[0-9]{1,3},[0-9]{1,3},[0-9]{1,3}"/>
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="hexColorT">
    <xs:restriction base="xs:string">
      <xs:pattern value="#?([a-fA-F0-9][a-fA-F0-9]){3}"/>
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="pointsT">
    <xs:restriction base="xs:string"/>
  </xs:simpleType>

  <xs:simpleType name="hexColorAlphaT">
    <xs:restriction base="xs:string">
      <xs:pattern value="#?([a-fA-F0-9][a-fA-F0-9]){3,4}"/>
    </xs:restriction>
  </xs:simpleType>

  <xs:complexType name="simpleDataT">
    <xs:simpleContent>
      <xs:extension base="xs:base64Binary">
        <xs:attributeGroup ref="simpleDataT"/>
      </xs:extension>
    </xs:simpleContent>
  </xs:complexType>

  <xs:complexType name="simpleImageT">
    <xs:sequence>
      <!-- data -->
      <xs:element name="data" minOccurs="0" type="simpleDataT"/>
    </xs:sequence>
    <xs:attributeGroup ref="simpleImageT"/>
  </xs:complexType>

  <!--
  elements
-->

  <xs:element name="properties">
    <xs:complexType>
      <xs:sequence maxOccurs="unbounded" minOccurs="1">
        <xs:element name="property">
          <xs:complexType>
            <xs:attributeGroup ref="property"/>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

  <xs:element name="image">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="data" minOccurs="0"/>
      </xs:sequence>
      <xs:attributeGroup ref="image"/>
    </xs:complexType>
  </xs:element>


  <xs:element name="imagelayer">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="properties" minOccurs="0"/>
        <xs:element ref="image" minOccurs="0"/>
      </xs:sequence>
      <xs:attributeGroup ref="imagelayer"/>
    </xs:complexType>
  </xs:element>

  <xs:element name="map">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="properties" minOccurs="0"/>
        <xs:element ref="tileset" maxOccurs="unbounded"/>
        <xs:choice maxOccurs="unbounded">
          <xs:element ref="layer"/>
          <xs:element ref="objectgroup"/>
        </xs:choice>
        <xs:element ref="imagelayer" minOccurs="0"/>
      </xs:sequence>
      <xs:attributeGroup ref="map"/>
    </xs:complexType>
  </xs:element>

  <xs:element name="tileset">
    <xs:complexType>
      <xs:sequence>

        <!-- image.tileset -->
        <xs:element name="image" minOccurs="0" maxOccurs="unbounded">
          <xs:complexType>
            <xs:complexContent>
              <xs:extension base="simpleImageT">
                <xs:attributeGroup ref="image.tileset"/>
              </xs:extension>
            </xs:complexContent>
          </xs:complexType>
        </xs:element>

        <!-- tile.tileset -->
        <xs:element name="tile" minOccurs="0" maxOccurs="unbounded">
          <xs:complexType>
            <xs:sequence>
              <xs:element ref="properties" minOccurs="0"/>

              <!-- image.tile.tileset -->
              <xs:element name="image" minOccurs="0" type="simpleImageT"/>
              <xs:element ref="objectgroup" minOccurs="0"/>
              <xs:element name="animation" maxOccurs="1">
                <xs:complexType>
                  <xs:sequence>
                    <xs:element name="frame" minOccurs="1" maxOccurs="unbounded">
                      <xs:complexType>
                        <xs:attributeGroup ref="frame"/>
                      </xs:complexType>
                    </xs:element>
                  </xs:sequence>
                </xs:complexType>
              </xs:element>
            </xs:sequence>
            <xs:attributeGroup ref="tile.tileset"/>
          </xs:complexType>
        </xs:element>
        <xs:element name="tileoffset">
          <xs:complexType>
            <xs:attributeGroup ref="tileoffset"/>
          </xs:complexType>
        </xs:element>
        <xs:element ref="properties" minOccurs="0" maxOccurs="1"/>
        <xs:element name="terraintypes">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="terrain">
                <xs:complexType>
                  <xs:sequence>
                    <xs:element ref="properties" minOccurs="0" maxOccurs="1"/>
                  </xs:sequence>
                  <xs:attributeGroup ref="terrain"/>
                </xs:complexType>
              </xs:element>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
      <xs:attributeGroup ref="tileset"/>
    </xs:complexType>
  </xs:element>

  <!-- Can be used in both image and layer -->
  <xs:element name="data">
    <xs:complexType mixed="true">
      <xs:choice>
        <!-- tile.data -->
        <xs:element name="tile" minOccurs="0" maxOccurs="unbounded">
          <xs:complexType>
            <xs:attributeGroup ref="tile.data.layer"/>
          </xs:complexType>
        </xs:element>
      </xs:choice>
      <xs:attributeGroup ref="data.layer"/>
    </xs:complexType>
  </xs:element>

  <xs:element name="layer">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="properties" minOccurs="0"/>
        <!-- data.layer -->
        <xs:element ref="data"/>
      </xs:sequence>
      <xs:attributeGroup ref="layer"/>
    </xs:complexType>
  </xs:element>

  <xs:element name="objectgroup">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="object" maxOccurs="unbounded">
          <xs:complexType>
            <xs:sequence>
              <xs:element ref="properties" minOccurs="0"/>
              <xs:choice>
                <xs:element name="point" minOccurs="0" maxOccurs="1">
                </xs:element>
                <xs:element name="ellipse" minOccurs="0" maxOccurs="1">
                </xs:element>
                <xs:element name="polygon" minOccurs="0" maxOccurs="1">
                  <xs:complexType>
                    <xs:attribute name="points" type="pointsT"/>
                  </xs:complexType>
                </xs:element>
                <xs:element name="polyline" minOccurs="0" maxOccurs="1">
                  <xs:complexType>
                    <xs:attribute name="points" type="pointsT"/>
                  </xs:complexType>
                </xs:element>
              </xs:choice>
            </xs:sequence>
            <xs:attributeGroup ref="object"/>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
      <xs:attributeGroup ref="objectgroup"/>
    </xs:complexType>
  </xs:element>

  <!--
  attributes
-->

  <xs:attributeGroup name="simpleDataT">
    <xs:attribute name="encoding" type="encodingT" use="required"></xs:attribute>
  </xs:attributeGroup>

  <xs:attributeGroup name="simpleImageT">
    <xs:attribute name="id" type="xs:nonNegativeInteger"/>
    <xs:attribute name="format" type="formatT"/>
  </xs:attributeGroup>

  <xs:attributeGroup name="property">
    <xs:attribute name="name" type="nameT" use="required"/>
    <xs:attribute name="value" type="xs:string" use="required"/>
    <xs:attribute name="type" type="propertytypeT" use="optional" default="string"/>
  </xs:attributeGroup>

  <xs:attributeGroup name="map">
    <xs:attribute name="version" type="xs:string" use="required"/>
    <xs:attribute name="orientation" type="orientationT" use="required"/>
    <xs:attribute name="renderorder" type="renderorderT" default="right-down"/>
    <xs:attribute name="width" type="xs:nonNegativeInteger" use="required"/>
    <xs:attribute name="height" type="xs:nonNegativeInteger" use="required"/>
    <xs:attribute name="tilewidth" type="pixelT" use="required"/>
    <xs:attribute name="tileheight" type="pixelT" use="required"/>
    <xs:attribute name="hexsidelength" type="xs:integer" use="optional"/>
    <xs:attribute name="staggeraxis" type="staggeraxisT" use="optional"/>
    <xs:attribute name="staggerindex" type="staggerindexT" use="optional"/>
    <xs:attribute name="backgroundcolor" type="hexColorAlphaT" use="optional"/>
    <xs:attribute name="nextlayerid" type="xs:nonNegativeInteger" use="optional"/>
    <xs:attribute name="nextobjectid" type="xs:nonNegativeInteger" use="optional"/>
  </xs:attributeGroup>

  <xs:attributeGroup name="tileset">
    <xs:attribute name="name" type="nameT"/>
    <xs:attribute name="firstgid" type="xs:positiveInteger" use="required"/>
    <xs:attribute name="source" type="xs:anyURI"/>
    <xs:attribute name="tilewidth" type="pixelT"/>
    <xs:attribute name="tileheight" type="pixelT"/>
    <xs:attribute name="spacing" type="pixelT"/>
    <xs:attribute name="margin" type="pixelT"/>
    <xs:attribute name="tilecount" type="xs:nonNegativeInteger"/>
    <xs:attribute name="columns" type="xs:nonNegativeInteger"/>
  </xs:attributeGroup>

  <xs:attributeGroup name="imagelayer">
    <xs:attribute name="name" type="nameT"/>
    <xs:attribute name="offsetx" type="xs:double" default="0" use="optional"/>
    <xs:attribute name="offsety" type="xs:double" default="0" use="optional"/>
    <xs:attribute name="opacity" type="opacityT" default="1" use="optional"/>
    <xs:attribute name="visible" type="xs:boolean" default="1" use="optional"/>
  </xs:attributeGroup>

  <xs:attributeGroup name="terrain">
    <xs:attribute name="name" type="nameT"/>
    <xs:attribute name="tile" type="tileId"/>
  </xs:attributeGroup>

  <xs:attributeGroup name="tileoffset">
    <xs:attribute name="x" type="xs:integer" use="required"/>
    <xs:attribute name="y" type="xs:integer" use="required"/>
  </xs:attributeGroup>

  <xs:attributeGroup name="data">
    <xs:attribute name="encoding" type="encodingT" use="required"/>
    <xs:attribute name="compression" type="compressionT" use="optional"/>
  </xs:attributeGroup>

  <xs:attributeGroup name="frame">
    <xs:attribute name="tileid" type="tileId" use="required"/>
    <xs:attribute name="duration" type="xs:nonNegativeInteger" use="required"/>
  </xs:attributeGroup>

  <xs:attributeGroup name="image">
    <xs:attribute name="format" type="imageformatT" use="optional"/>
    <xs:attribute name="source" type="xs:anyURI" use="optional"/>
    <xs:attribute name="trans" type="hexColorT" use="optional"/>
    <xs:attribute name="width" type="pixelT" use="optional"/>
    <xs:attribute name="height" type="pixelT" use="optional"/>
  </xs:attributeGroup>

  <xs:attributeGroup name="image.tileset">
    <xs:attribute name="source" type="xs:anyURI"/>
    <xs:attribute name="trans" type="hexColorT"/>
  </xs:attributeGroup>

  <xs:attributeGroup name="tile.tileset">
    <xs:attribute name="id" type="tileId" use="required"/>
    <xs:attribute name="terrain" type="cornerterrainT" use="optional"/>
    <xs:attribute name="probability" type="xs:float" use="optional"/>
  </xs:attributeGroup>

  <xs:attributeGroup name="layer">
    <xs:attribute name="name" type="nameT" use="required"/>
    <xs:attribute name="width" type="xs:nonNegativeInteger" use="required"/>
    <xs:attribute name="height" type="xs:nonNegativeInteger" use="required"/>
    <xs:attribute name="opacity" type="opacityT" default="1"/>
    <xs:attribute name="visible" type="xs:boolean" default="1"/>
    <xs:attribute name="offsetx" type="xs:double" default="0"/>
    <xs:attribute name="offsety" type="xs:double" default="0"/>
  </xs:attributeGroup>

  <xs:attributeGroup name="data.layer">
    <xs:attribute name="encoding" type="encodingT"/>
    <xs:attribute name="compression" type="compressionT"/>
  </xs:attributeGroup>

  <xs:attributeGroup name="tile.data.layer">
    <xs:attribute name="gid" type="tileId" use="required"/>
  </xs:attributeGroup>

  <xs:attributeGroup name="objectgroup">
    <xs:attribute name="name" type="nameT" use="required"/>
    <xs:attribute name="color" type="hexColorT" use ="required"/>
    <xs:attribute name="opacity" type="opacityT" use="optional" default="1"/>
    <xs:attribute name="visible" type="xs:boolean" use="optional" default="1"/>
    <xs:attribute name="offsetx" type="xs:double" use="optional" default="0"/>
    <xs:attribute name="offsety" type="xs:double" use="optional" default="0"/>
    <xs:attribute name="draworder" type="draworderT" use="optional" default="topdown"/>
  </xs:attributeGroup>

  <xs:attributeGroup name="object">
    <xs:attribute name="id" type="xs:nonNegativeInteger" use="optional"/>
    <xs:attribute name="name" type="nameT" use="required"/>
    <xs:attribute name="type" type="xs:string" use="required"/>
    <xs:attribute name="x" type="xs:double" use="required"/>
    <xs:attribute name="y" type="xs:double" use="required"/>
    <xs:attribute name="width" type="xs:double" use="optional" default="0"/>
    <xs:attribute name="height" type="xs:double" use="optional" default="0"/>
    <xs:attribute name="rotation" type="degreesT" use="optional" default="0"/>
    <xs:attribute name="gid" type="tileId" use="optional" default="0"/>
    <xs:attribute name="visible" type="xs:boolean" use="optional" default="1"/>
  </xs:attributeGroup>

</xs:schema>
