Пример #1
0
 /// <summary>
 /// Constructs a changeset for overwriting an integer field.
 /// </summary>
 /// <param name="targetCell">The cell of the target to perform the changeset.</param>
 /// <param name="modifier">Reference to the modifier.</param>
 /// <param name="tileset">The tileset of this changeset.</param>
 public CellChangeSet(RCIntVector targetCell, ICellDataModifier modifier, TileSet tileset)
     : base(modifier, tileset)
 {
     this.CheckAndAssignCtorParams(targetCell);
 }
Пример #2
0
 /// <summary>
 /// Constructs a changeset for overwriting an integer field.
 /// </summary>
 /// <param name="targetRow">The row of the target to perform the changeset.</param>
 /// <param name="modifier">Reference to the modifier.</param>
 /// <param name="tileset">The tileset of this changeset.</param>
 public RowChangeSet(int targetRow, ICellDataModifier modifier, TileSet tileset)
     : base(modifier, tileset)
 {
     this.CheckAndAssignCtorParams(targetRow);
 }
Пример #3
0
        /// <summary>
        /// Constructs a NeighbourCondition instance.
        /// </summary>
        /// <param name="combination">The terrain combination of the neighbour to check.</param>
        /// <param name="direction">The direction of the neighbour to check.</param>
        /// <param name="tileset">The tileset of this condition.</param>
        public NeighbourCondition(TerrainCombination combination, MapDirection direction, TileSet tileset)
        {
            if (tileset == null)
            {
                throw new ArgumentNullException("tileset");
            }

            this.combination = combination;
            this.direction   = direction;
            this.tileset     = tileset;
        }
Пример #4
0
        /// <summary>
        /// Constructs a TerrainObjectType instance.
        /// </summary>
        /// <param name="name">The name of the TerrainObjectType.</param>
        /// <param name="imageData">The byte sequence that contains the image data of the TerrainObjectType.</param>
        /// <param name="quadraticSize">The size of the TerrainObjectType in quadratic tiles.</param>
        /// <param name="transparentColor">The transparent color of this TerrainObjectType.</param>
        /// <param name="tileset">Reference to the tileset that this TerrainObjectType belongs to.</param>
        public TerrainObjectType(string name, byte[] imageData, RCIntVector quadraticSize, RCColor transparentColor, TileSet tileset)
        {
            if (name == null)
            {
                throw new ArgumentNullException("name");
            }
            if (imageData == null || imageData.Length == 0)
            {
                throw new ArgumentNullException("imageData");
            }
            if (quadraticSize == RCIntVector.Undefined)
            {
                throw new ArgumentNullException("quadraticSize");
            }
            if (transparentColor == RCColor.Undefined)
            {
                throw new ArgumentNullException("transparentColor");
            }
            if (tileset == null)
            {
                throw new ArgumentNullException("tileset");
            }
            if (quadraticSize.X <= 0 || quadraticSize.Y <= 0)
            {
                throw new ArgumentOutOfRangeException("quadraticSize", "Quadratic size cannot be 0 in any direction!");
            }

            this.name               = name;
            this.imageData          = imageData;
            this.quadraticSize      = quadraticSize;
            this.transparentColor   = transparentColor;
            this.tileset            = tileset;
            this.areaCanBeExcluded  = true;
            this.constraints        = new List <ITerrainObjectConstraint>();
            this.cellDataChangesets = new List <ICellDataChangeSet>();

            this.includedQuadCoords = new RCSet <RCIntVector>();
            for (int x = 0; x < quadraticSize.X; x++)
            {
                for (int y = 0; y < quadraticSize.Y; y++)
                {
                    this.includedQuadCoords.Add(new RCIntVector(x, y));
                }
            }
        }
Пример #5
0
        /// <summary>
        /// Constructs a mixed tile type for the given terrain types and combination.
        /// </summary>
        /// <param name="terrainTypeA">The name of the first terrain type.</param>
        /// <param name="terrainTypeB">The name of the second terrain type.</param>
        /// <param name="tileset">The tileset of the tile type.</param>
        /// <remarks>Terrain type A must be the parent of terrain type B.</remarks>
        public IsoTileType(string terrainTypeA, string terrainTypeB, TerrainCombination combination, TileSet tileset)
        {
            if (terrainTypeA == null)
            {
                throw new ArgumentNullException("terrainTypeA");
            }
            if (terrainTypeB == null)
            {
                throw new ArgumentNullException("terrainTypeB");
            }
            if (tileset == null)
            {
                throw new ArgumentNullException("tileset");
            }
            if (combination == TerrainCombination.Simple)
            {
                throw new ArgumentException("combination", "Invalid combination for a mixed tile type!");
            }

            this.tileset = tileset;
            TerrainType tA = this.tileset.GetTerrainTypeImpl(terrainTypeA);
            TerrainType tB = this.tileset.GetTerrainTypeImpl(terrainTypeB);

            if (tB.Parent != tA)
            {
                throw new ArgumentException(string.Format("TerrainType '{0}' must be the parent of TerrainType '{1}'!", terrainTypeA, terrainTypeB));
            }

            this.terrainA         = tA;
            this.terrainB         = tB;
            this.combination      = combination;
            this.tmpCurrentBranch = null;
            this.defaultBranch    = null;
            this.variants         = new List <Tuple <List <IsoTileVariant>, IIsoTileCondition> >();
        }
Пример #6
0
 /// <summary>
 /// Constructs a changeset for overwriting an integer field.
 /// </summary>
 /// <param name="targetCol">The column of the target to perform the changeset.</param>
 /// <param name="modifier">Reference to the modifier.</param>
 /// <param name="tileset">The tileset of this changeset.</param>
 public ColumnChangeSet(int targetCol, ICellDataModifier modifier, TileSet tileset)
     : base(modifier, tileset)
 {
     this.CheckAndAssignCtorParams(targetCol);
 }
Пример #7
0
        /// <summary>
        /// Loads the variants of a tile type from the XML element into the given tileset.
        /// </summary>
        /// <param name="fromElem">The XML element to load from.</param>
        /// <param name="tile">The tile type to load to.</param>
        /// <param name="tileset">The tileset of the tile type.</param>
        private static void LoadVariants(XElement fromElem, IsoTileType tile, TileSet tileset)
        {
            TileReadStatus status = TileReadStatus.None;

            foreach (XElement childElem in fromElem.Elements())
            {
                if (status == TileReadStatus.None)
                {
                    /// We are in the initial read status.
                    if (childElem.Name == XmlTileSetConstants.VARIANT_ELEM)
                    {
                        /// No conditional expression at the current tile type.
                        status = TileReadStatus.NoCondition;
                        LoadVariant(childElem, tile, tileset);
                    }
                    else if (childElem.Name == XmlTileSetConstants.IF_ELEM)
                    {
                        /// Beginning of the conditional branch.
                        status = TileReadStatus.ConditionalBranch;
                        LoadBranch(childElem, tile, tileset);
                    }
                    else
                    {
                        /// Other XML elements not allowed at this read status.
                        throw new TileSetException(string.Format("Unexpected node '{0}'!", childElem.Name));
                    }
                }
                else if (status == TileReadStatus.NoCondition)
                {
                    /// We are in the read status where only variant elements are allowed.
                    if (childElem.Name == XmlTileSetConstants.VARIANT_ELEM)
                    {
                        LoadVariant(childElem, tile, tileset);
                    }
                    else
                    {
                        /// Other XML elements not allowed at this read status.
                        throw new TileSetException(string.Format("Unexpected node '{0}'!", childElem.Name));
                    }
                }
                else if (status == TileReadStatus.ConditionalBranch)
                {
                    /// We are in the read status where only conditional branch and default branch elements are allowed.
                    if (childElem.Name == XmlTileSetConstants.ELSEIF_ELEM)
                    {
                        /// Load the conditional branch.
                        LoadBranch(childElem, tile, tileset);
                    }
                    else if (childElem.Name == XmlTileSetConstants.ELSE_ELEM)
                    {
                        /// Load the default branch.
                        status = TileReadStatus.DefaultBranch;
                        foreach (XElement varElem in childElem.Elements(XmlTileSetConstants.VARIANT_ELEM))
                        {
                            LoadVariant(varElem, tile, tileset);
                        }
                    }
                    else
                    {
                        /// Other XML elements not allowed at this read status.
                        throw new TileSetException(string.Format("Unexpected node '{0}'!", childElem.Name));
                    }
                }
                else
                {
                    /// Other XML elements not allowed.
                    throw new TileSetException(string.Format("Unexpected node '{0}' after default branch!", childElem.Name));
                }
            }
        }
Пример #8
0
        /// <summary>
        /// Load a cell data changeset from the given XML element.
        /// </summary>
        /// <param name="fromElem">The XML element to load from.</param>
        /// <param name="tileset">The tileset being loaded.</param>
        /// <returns>The loaded cell data changeset.</returns>
        private static ICellDataChangeSet LoadCellDataChangeSet(XElement fromElem, TileSet tileset)
        {
            ICellDataChangeSet retObj   = null;
            ICellDataModifier  modifier = null;

            /// Load the name of the target field.
            XAttribute fieldAttr = fromElem.Attribute(XmlTileSetConstants.CELLDATACHANGESET_FIELD_ATTR);

            if (fieldAttr == null)
            {
                throw new TileSetException("Field name not defined for a data changeset element!");
            }

            if (fieldAttr.Value == XmlTileSetConstants.CELLDATA_ISWALKABLE_NAME)
            {
                modifier = new WalkabilityFlagModifier(XmlHelper.LoadBool(fromElem.Value));
            }
            else if (fieldAttr.Value == XmlTileSetConstants.CELLDATA_ISBUILDABLE_NAME)
            {
                modifier = new BuildabilityFlagModifier(XmlHelper.LoadBool(fromElem.Value));
            }
            else if (fieldAttr.Value == XmlTileSetConstants.CELLDATA_GROUNDLEVEL_NAME)
            {
                modifier = new GroundLevelModifier(XmlHelper.LoadInt(fromElem.Value));
            }
            if (modifier == null)
            {
                throw new TileSetException("Unexpected field name defined for a data changeset element!");
            }

            switch (fromElem.Name.LocalName)
            {
            case XmlTileSetConstants.CELLDATACHANGESET_ALL_ELEM:
                retObj = new CellDataChangeSetBase(modifier, tileset);
                break;

            case XmlTileSetConstants.CELLDATACHANGESET_CELL_ELEM:
                XAttribute cellAttr = fromElem.Attribute(XmlTileSetConstants.CELLDATACHANGESET_CELL_CELL_ATTR);
                if (cellAttr == null)
                {
                    throw new TileSetException("Cell not defined for a cell data changeset element!");
                }
                retObj = new CellChangeSet(XmlHelper.LoadIntVector(cellAttr.Value), modifier, tileset);
                break;

            case XmlTileSetConstants.CELLDATACHANGESET_COL_ELEM:
                XAttribute colIndexAttr = fromElem.Attribute(XmlTileSetConstants.CELLDATACHANGESET_COL_INDEX_ATTR);
                if (colIndexAttr == null)
                {
                    throw new TileSetException("Column not defined for a column data changeset element!");
                }
                retObj = new ColumnChangeSet(XmlHelper.LoadInt(colIndexAttr.Value), modifier, tileset);
                break;

            case XmlTileSetConstants.CELLDATACHANGESET_QUARTER_ELEM:
                XAttribute quarterAttr = fromElem.Attribute(XmlTileSetConstants.CELLDATACHANGESET_QUARTER_WHICH_ATTR);
                if (quarterAttr == null)
                {
                    throw new TileSetException("Quarter not defined for a quarter data changeset element!");
                }
                MapDirection quarter;
                if (!EnumMap <MapDirection, string> .TryDemap(quarterAttr.Value, out quarter))
                {
                    throw new TileSetException(string.Format("Unexpected quarter '{0}' defined for quarter data changeset!", quarterAttr.Value));
                }
                retObj = new IsoQuarterChangeSet(quarter, modifier, tileset);
                break;

            case XmlTileSetConstants.CELLDATACHANGESET_RECT_ELEM:
                XAttribute rectAttr = fromElem.Attribute(XmlTileSetConstants.CELLDATACHANGESET_RECT_RECT_ATTR);
                if (rectAttr == null)
                {
                    throw new TileSetException("Rectangle not defined for a rectangle data changeset element!");
                }
                retObj = new RectangleChangeSet(XmlHelper.LoadIntRectangle(rectAttr.Value), modifier, tileset);
                break;

            case XmlTileSetConstants.CELLDATACHANGESET_ROW_ELEM:
                XAttribute rowIndexAttr = fromElem.Attribute(XmlTileSetConstants.CELLDATACHANGESET_ROW_INDEX_ATTR);
                if (rowIndexAttr == null)
                {
                    throw new TileSetException("Row not defined for a row data changeset element!");
                }
                retObj = new RowChangeSet(XmlHelper.LoadInt(rowIndexAttr.Value), modifier, tileset);
                break;

            default:
                throw new TileSetException(string.Format("Unexpected data changeset element '{0}'!", fromElem.Name));
            }

            if (retObj == null)
            {
                throw new TileSetException("Unable to load cell data changeset!");
            }
            return(retObj);
        }
Пример #9
0
        /// <summary>
        /// Load a tile-constraint for a terrain object from the given XML element.
        /// </summary>
        /// <param name="fromElem">The XML element to load from.</param>
        /// <param name="terrainObj">The terrain object.</param>
        /// <param name="tileset">The tileset being loaded.</param>
        /// <returns>The loaded tile-constraint.</returns>
        private static ITerrainObjectConstraint LoadTileConstraint(XElement fromElem, TerrainObjectType terrainObj, TileSet tileset)
        {
            /// Load the attributes of the constraint.
            XAttribute quadCoordsAttr   = fromElem.Attribute(XmlTileSetConstants.TERRAINOBJ_TILECONSTRAINT_QUADCOORDS_ATTR);
            XAttribute terrainAttr      = fromElem.Attribute(XmlTileSetConstants.TERRAINOBJ_TILECONSTRAINT_TERRAIN_ATTR);
            XAttribute terrainAAttr     = fromElem.Attribute(XmlTileSetConstants.TERRAINOBJ_TILECONSTRAINT_TERRAINA_ATTR);
            XAttribute terrainBAttr     = fromElem.Attribute(XmlTileSetConstants.TERRAINOBJ_TILECONSTRAINT_TERRAINB_ATTR);
            XAttribute combinationsAttr = fromElem.Attribute(XmlTileSetConstants.TERRAINOBJ_TILECONSTRAINT_COMBINATIONS_ATTR);

            if (quadCoordsAttr == null)
            {
                throw new TileSetException("Quadratic coordinates not defined for tile constraint element!");
            }
            if (terrainAttr != null && (terrainAAttr != null || terrainBAttr != null || combinationsAttr != null))
            {
                throw new TileSetException("Invalid attributes defined for tile constraint on a simple tile!");
            }
            if (terrainAttr == null && (terrainAAttr == null || terrainBAttr == null || combinationsAttr == null))
            {
                throw new TileSetException("Invalid attributes defined for tile constraint on a mixed tile!");
            }

            RCIntVector quadCoords = XmlHelper.LoadIntVector(quadCoordsAttr.Value);

            if (terrainObj.IsExcluded(quadCoords))
            {
                throw new TileSetException(string.Format("TileConstraint at excluded coordinates {0} cannot be defined!", quadCoords));
            }
            if (terrainAttr != null)
            {
                TerrainType terrain = tileset.GetTerrainTypeImpl(terrainAttr.Value);
                return(new IsoTileConstraint(quadCoords, terrain, tileset));
            }
            else
            {
                TerrainType terrainA = tileset.GetTerrainTypeImpl(terrainAAttr.Value);
                TerrainType terrainB = tileset.GetTerrainTypeImpl(terrainBAttr.Value);
                List <TerrainCombination> combinations = new List <TerrainCombination>();
                string[] combinationStrings            = combinationsAttr.Value.Split(';');
                if (combinationStrings.Length == 0)
                {
                    throw new TileSetException("Terrain combination not defined for tile constraint on a mixed tile!");
                }
                foreach (string combStr in combinationStrings)
                {
                    TerrainCombination combination;
                    if (!EnumMap <TerrainCombination, string> .TryDemap(combStr, out combination) || combination == TerrainCombination.Simple)
                    {
                        throw new TileSetException(string.Format("Unexpected terrain combination '{0}' defined for tile constraint!", combStr));
                    }
                    combinations.Add(combination);
                }

                return(new IsoTileConstraint(quadCoords, terrainA, terrainB, combinations, tileset));
            }
        }
Пример #10
0
        /// <summary>
        /// Reads the given XML document, and constructs a TileSet object from it.
        /// </summary>
        /// <param name="xmlStr">The string that contains the XML document to read.</param>
        /// <param name="imageDir">The directory where the referenced images can be found. (TODO: this is a hack!)</param>
        /// <returns>The constructed TileSet object.</returns>
        public static TileSet Read(string xmlStr, string imageDir)
        {
            if (xmlStr == null)
            {
                throw new ArgumentNullException("xmlStr");
            }
            if (imageDir == null)
            {
                throw new ArgumentNullException("imageDir");
            }

            tmpImageDir = imageDir;

            /// Load the XML document.
            XDocument  xmlDoc                    = XDocument.Parse(xmlStr);
            XAttribute tilesetNameAttr           = xmlDoc.Root.Attribute(XmlTileSetConstants.TILESET_NAME_ATTR);
            XElement   terrainTreeElem           = xmlDoc.Root.Element(XmlTileSetConstants.TERRAINTYPE_ELEM);
            XElement   declareTilesElem          = xmlDoc.Root.Element(XmlTileSetConstants.DECLARETILES_ELEM);
            XElement   declareTerrainObjectsElem = xmlDoc.Root.Element(XmlTileSetConstants.DECLARETERRAINOBJECTS_ELEM);

            if (tilesetNameAttr == null)
            {
                throw new TileSetException("Tileset name not defined!");
            }
            if (terrainTreeElem == null)
            {
                throw new TileSetException("Terrain-tree not defined!");
            }
            if (declareTilesElem == null)
            {
                throw new TileSetException("Tile declarations not found");
            }

            /// Create the TileSet object.
            TileSet tileset = new TileSet(tilesetNameAttr.Value);

            /// Load the terrain tree.
            LoadTerrainTree(terrainTreeElem, null, tileset);

            /// Load the simple tiles.
            foreach (XElement simpleTileElem in declareTilesElem.Elements(XmlTileSetConstants.SIMPLETILE_ELEM))
            {
                LoadSimpleTile(simpleTileElem, tileset);
            }

            /// Load the mixed tiles.
            foreach (XElement mixedTileElem in declareTilesElem.Elements(XmlTileSetConstants.MIXEDTILE_ELEM))
            {
                LoadMixedTile(mixedTileElem, tileset);
            }

            /// Load the terrain objects.
            if (declareTerrainObjectsElem != null)
            {
                foreach (XElement terrainObjElem in declareTerrainObjectsElem.Elements(XmlTileSetConstants.TERRAINOBJECT_ELEM))
                {
                    LoadTerrainObject(terrainObjElem, tileset);
                }
            }

            tileset.CheckAndFinalize();
            return(tileset);
        }
Пример #11
0
        /// <summary>
        /// Loads a terrain object definition from the XML element into the given tileset.
        /// </summary>
        /// <param name="fromElem">The XML element to load from.</param>
        /// <param name="tileset">The TileSet to load to.</param>
        private static void LoadTerrainObject(XElement fromElem, TileSet tileset)
        {
            XAttribute nameAttr        = fromElem.Attribute(XmlTileSetConstants.TERRAINOBJ_NAME_ATTR);
            XAttribute imageAttr       = fromElem.Attribute(XmlTileSetConstants.TERRAINOBJ_IMAGE_ATTR);
            XAttribute quadSizeAttr    = fromElem.Attribute(XmlTileSetConstants.TERRAINOBJ_QUADSIZE_ATTR);
            XAttribute transpColorAttr = fromElem.Attribute(XmlTileSetConstants.TERRAINOBJ_TRANSPCOLOR_ATTR);

            if (nameAttr == null)
            {
                throw new TileSetException("Name not defined for terrain object!");
            }
            if (imageAttr == null)
            {
                throw new TileSetException("Image not defined for terrain object!");
            }
            if (quadSizeAttr == null)
            {
                throw new TileSetException("Quadratic size not defined for terrain object!");
            }
            if (transpColorAttr == null)
            {
                throw new TileSetException("Transparent color not defined for terrain object!");
            }

            /// Read the image data.
            string imagePath = Path.Combine(tmpImageDir, imageAttr.Value);

            byte[] imageData = File.ReadAllBytes(imagePath);

            tileset.CreateTerrainObjectType(nameAttr.Value,
                                            imageData,
                                            XmlHelper.LoadIntVector(quadSizeAttr.Value),
                                            XmlHelper.LoadColor(transpColorAttr.Value));
            TerrainObjectType terrainObj = tileset.GetTerrainObjectTypeImpl(nameAttr.Value);

            /// Apply the defined area exclusions.
            foreach (XElement excludeAreaElem in fromElem.Elements(XmlTileSetConstants.TERRAINOBJ_EXCLUDEAREA_ELEM))
            {
                XAttribute rectAttr = excludeAreaElem.Attribute(XmlTileSetConstants.TERRAINOBJ_EXCLUDEAREA_RECT_ATTR);
                if (rectAttr == null)
                {
                    throw new TileSetException("The rectangle of the excluded area not defined!");
                }
                terrainObj.ExcludeArea(XmlHelper.LoadIntRectangle(rectAttr.Value));
            }

            /// Load the constraints and the cell data changesets.
            foreach (XElement childElem in fromElem.Elements())
            {
                if (childElem.Name.LocalName == XmlTileSetConstants.TERRAINOBJ_TILECONSTRAINT_ELEM)
                {
                    ITerrainObjectConstraint constraint = LoadTileConstraint(childElem, terrainObj, tileset);
                    terrainObj.AddConstraint(constraint);
                }
                else if (childElem.Name.LocalName != XmlTileSetConstants.TERRAINOBJ_EXCLUDEAREA_ELEM)
                {
                    ICellDataChangeSet changeset = LoadCellDataChangeSet(childElem, tileset);
                    terrainObj.AddCellDataChangeset(changeset);
                }
                /// TODO: loading other constraint types can take place here!
            }
        }
Пример #12
0
        /// <summary>
        /// Constructs a ComplexCondition instance.
        /// </summary>
        /// <param name="subconditions">The subconditions connected by a logical operator.</param>
        /// <param name="logicalOp">The operator.</param>
        /// <param name="tileset">The tileset of this condition.</param>
        public ComplexCondition(List <IIsoTileCondition> subconditions, LogicalOp logicalOp, TileSet tileset)
        {
            if (subconditions == null)
            {
                throw new ArgumentNullException("subconditions");
            }
            if (tileset == null)
            {
                throw new ArgumentNullException("tileset");
            }

            if (logicalOp == LogicalOp.AND || logicalOp == LogicalOp.OR)
            {
                if (subconditions.Count < 2)
                {
                    throw new TileSetException("At least 2 subconditions must be defined in case of LogicalOp.AND or LogicalOp.OR operators!");
                }
            }
            else
            {
                if (subconditions.Count != 1)
                {
                    throw new TileSetException("Only one subcondition must be defined in case of LogicalOp.NOT operator!");
                }
            }

            this.subconditions = new List <IIsoTileCondition>(subconditions);
            this.logicalOp     = logicalOp;
            this.tileset       = tileset;
        }
Пример #13
0
 /// <summary>
 /// Constructs a changeset for overwriting an integer field.
 /// </summary>
 /// <param name="targetRect">The rectangle of the target to perform the changeset.</param>
 /// <param name="modifier">Reference to the modifier.</param>
 /// <param name="tileset">The tileset of this changeset.</param>
 public RectangleChangeSet(RCIntRectangle targetRect, ICellDataModifier modifier, TileSet tileset)
     : base(modifier, tileset)
 {
     this.CheckAndAssignCtorParams(targetRect);
 }