Exemple #1
0
        private void AddAttachments(IBrushContext context, TileData tile, GameObject tileGO, bool addCollider)
        {
            // Add collider to tile game object?
            if (addCollider)
            {
                switch (this.colliderType)
                {
                case Tile.ColliderType.BoxCollider2D:
                    tileGO.AddComponent <BoxCollider2D>();
                    break;

                case Tile.ColliderType.BoxCollider3D:
                    tileGO.AddComponent <BoxCollider>();
                    break;
                }
            }

            // Attach prefab to tile?
            if (this.attachPrefab != null)
            {
                GameObject attachment = InstantiatePrefabForTile(this.attachPrefab, tile, context.TileSystem);
                if (attachment != null)
                {
                    attachment.transform.SetParent(tileGO.transform);
                }
            }
        }
Exemple #2
0
        /// <inheritdoc/>
        protected internal override void ApplyTransforms(IBrushContext context, TileData tile, Brush transformer)
        {
            var tileSystem    = context.TileSystem;
            var tileTransform = tile.gameObject.transform;

            // Place tile into its respective chunk.
            // NOTE: Chunk will definately exist at this stage.
            Transform newParent = tileSystem.GetChunkFromTileIndex(context.Row, context.Column).transform;

            tileTransform.SetParent(newParent, false);

            // Calculate position of tile within system.
            tileTransform.localPosition = tileSystem.LocalPositionFromTileIndex(context.Row, context.Column, true);
            // Turn tile to face away from system and rotate tile to align with system.
            tileTransform.localRotation = tileSystem.CalculateSimpleRotation(TileFacing.Sideways, tile.Rotation) * MathUtility.AngleAxis_180_Up;
            // Adjust scale of tile container.
            tileTransform.localScale = tileSystem.CalculateCellSizeScale(tile.Rotation);

            // Transform attachment?
            if (tileTransform.childCount == 1)
            {
                var attachmentTransform = tileTransform.GetChild(0);

                Matrix4x4 convertSystemToAttachmentSpaceMatrix = tileTransform.worldToLocalMatrix * tileSystem.transform.localToWorldMatrix;
                int       rotation = this.applySimpleRotationToAttachment ? tile.Rotation : 0;

                Matrix4x4 attachmentMatrix = convertSystemToAttachmentSpaceMatrix * transformer.GetTransformMatrix(tileSystem, context.Row, context.Column, rotation, this.attachPrefab.transform);
                MathUtility.SetTransformFromMatrix(attachmentTransform, ref attachmentMatrix);
            }
        }
        /// <inheritdoc/>
        protected internal override void ApplyTransforms(IBrushContext context, TileData tile, Brush transformer)
        {
            // If transforming brush has not already been overridden...
            if (transformer == this)
            {
                // Find nested brush reference?
                var orientation = this.FindOrientation(tile.orientationMask);
                if (orientation != null && orientation.VariationCount > 0)
                {
                    // Note: Do not update variation index in tile data because this may be unintended!
                    int variationIndex = (int)tile.variationIndex;
                    if (variationIndex >= orientation.VariationCount)
                    {
                        variationIndex = 0;
                    }

                    var nestedBrush = orientation.GetVariation(variationIndex) as Brush;

                    // Apply transforms using the nested brush (as would be expected!).
                    if (nestedBrush != null)
                    {
                        nestedBrush.ApplyTransforms(context, tile, this.overrideTransforms ? this : nestedBrush);
                        return;
                    }
                }

                base.ApplyTransforms(context, tile, this);
            }
            else
            {
                base.ApplyTransforms(context, tile, transformer);
            }
        }
        /// <inheritdoc/>
        protected internal override void CreateTile(IBrushContext context, TileData tile)
        {
            bool addCollider = ((tile.orientationMask & 0x5A) == 0x5A)
                ? this.addInnerCollider
                : this.addCollider;

            // Tile is procedural for autotile brushes regardless.
            this.CreateProceduralTile(context, tile, addCollider);
        }
Exemple #5
0
 /// <inheritdoc/>
 protected internal override bool CalculateManualOffset(IBrushContext context, TileData tile, Transform transform, out Vector3 offsetPosition, out Quaternion offsetRotation, out Vector3 offsetScale, Brush transformer)
 {
     // If transforming brush has not already been overridden...
     if (transformer == this && !this.overrideTransforms)
     {
         transformer = this.target;
     }
     return(this.target.CalculateManualOffset(context, tile, transform, out offsetPosition, out offsetRotation, out offsetScale, transformer));
 }
Exemple #6
0
 /// <inheritdoc/>
 protected internal override void ApplyTransforms(IBrushContext context, TileData tile, Brush transformer)
 {
     // If transforming brush has not already been overridden...
     if (transformer == this && !this.overrideTransforms)
     {
         transformer = this.target;
     }
     this.target.ApplyTransforms(context, tile, transformer);
 }
        /// <inheritdoc/>
        /// <seealso cref="CustomImmediatePreview"/>
        public override void OnDrawImmediatePreview(IBrushContext context, TileData previewTile, Material previewMaterial, Brush transformer)
        {
            var orientation = this.FindClosestOrientation(previewTile.orientationMask);

            if (orientation == null || orientation.VariationCount == 0)
            {
                return;
            }

            // Wrap variation index if necessary.
            int variationIndex = previewTile.variationIndex;

            if (variationIndex >= orientation.VariationCount)
            {
                variationIndex = 0;
            }
            // Randomization is not supported here!
            if (variationIndex == RANDOM_VARIATION)
            {
                variationIndex = 0;
            }

            var variationGO = orientation.GetVariation(variationIndex) as GameObject;

            if (variationGO != null)
            {
                var       variationTransform = variationGO.transform;
                Matrix4x4 matrix             = ImmediatePreviewUtility.Matrix * transformer.GetTransformMatrix(context.TileSystem, context.Row, context.Column, previewTile.Rotation, variationTransform);

                // Allow variation to provide a custom immediate preview.
                var customImmediatePreview = variationGO.GetComponent <CustomImmediatePreview>();
                if (customImmediatePreview != null)
                {
                    // Bail if custom immediate preview was drawn.
                    if (customImmediatePreview.DrawImmediatePreview(context, previewTile, previewMaterial, matrix))
                    {
                        return;
                    }
                }

                ImmediatePreviewUtility.DrawNow(previewMaterial, variationTransform, matrix, context.Brush as IMaterialMappings);
                return;
            }

            var variationBrush = orientation.GetVariation(variationIndex) as Brush;

            if (variationBrush != null)
            {
                // If transforming brush has not already been overridden then...
                if (transformer == this && !this.overrideTransforms)
                {
                    transformer = variationBrush;
                }
                variationBrush.OnDrawImmediatePreview(context, previewTile, previewMaterial, transformer);
                return;
            }
        }
        /// <inheritdoc/>
        protected internal override void CreateTile(IBrushContext context, TileData tile)
        {
            var orientation = this.FindOrientation(tile.orientationMask);

            if (orientation == null)
            {
                Debug.LogWarning(string.Format("Brush '{0}' orientation '{1}' not defined", this.name, OrientationUtility.NameFromMask(tile.orientationMask)));
                return;
            }

            if (orientation.VariationCount == 0)
            {
                Debug.LogWarning(string.Format("Brush '{0}' orientation '{1}' has no variations", this.name, OrientationUtility.NameFromMask(tile.orientationMask)));
                return;
            }

            // Note: Do not update variation index in tile data because this may be unintended!
            int variationIndex = (int)tile.variationIndex;

            if (variationIndex >= orientation.VariationCount)
            {
                variationIndex = 0;
            }

            var orientedVariation = orientation.GetVariation(variationIndex);

            // Orchestrate a "nested" brush?
            var nestedBrush = orientedVariation as Brush;

            if (nestedBrush != null)
            {
                // Force override flags with that of nested brush?
                //
                // Note: Naming a little backwards in this scenario, we want to preserve
                //       flags from nested brush!
                //
                if (!this.forceOverrideFlags)
                {
                    // Remove all user flags, solid flag and replace with flags from nested brush.
                    tile.flags = (tile.flags & ~0x8FFFF) | nestedBrush.TileFlags;
                }

                nestedBrush.CreateTile(context, tile);
                nestedBrush.PostProcessTile(context, tile);
                return;
            }

            var variationPrefab = orientedVariation as GameObject;

            if (variationPrefab == null)
            {
                return;
            }

            // Actually create tile!
            tile.gameObject = InstantiatePrefabForTile(variationPrefab, tile, context.TileSystem);
        }
Exemple #9
0
 /// <summary>
 /// Get data for immediate tile preview.
 /// </summary>
 /// <param name="context">Context in which brush is being used.</param>
 /// <param name="brush">The brush.</param>
 /// <param name="rotation">Zero-based index of simple rotation (0 = 0°, 1 = 90°, 2 = 180°, 3 = 270°).</param>
 /// <returns>
 /// Data for preview tile.
 /// </returns>
 public static TileData GetPreviewTileData(IBrushContext context, Brush brush, int rotation)
 {
     s_PreviewTileData.Clear();
     s_PreviewTileData.brush           = brush;
     s_PreviewTileData.flags           = brush.TileFlags;
     s_PreviewTileData.PaintedRotation = rotation;
     s_PreviewTileData.Rotation        = rotation;
     brush.PrepareTileData(context, s_PreviewTileData, 0);
     return(s_PreviewTileData);
 }
Exemple #10
0
 /// <inheritdoc/>
 protected internal override void CreateTile(IBrushContext context, TileData tile)
 {
     // Tile is procedural regardless of which brush defined it.
     if (tile.Procedural)
     {
         this.CreateProceduralTile(context, tile, this.addCollider);
     }
     else
     {
         this.CreateNonProceduralTile(context, tile, this.addCollider);
     }
 }
Exemple #11
0
 /// <inheritdoc/>
 public override void OnDrawImmediatePreview(IBrushContext context, TileData previewTile, Material previewMaterial, Brush transformer)
 {
     if (this.target != null)
     {
         // If transforming brush has not already been overridden then...
         if (transformer == this && !this.overrideTransforms)
         {
             transformer = this.target;
         }
         this.target.OnDrawImmediatePreview(context, previewTile, previewMaterial, transformer);
     }
 }
Exemple #12
0
 /// <summary>
 /// Create procedural tile.
 /// </summary>
 /// <remarks>
 /// <para>Creates container game object for tile when collider and/or attachment
 /// is to be added. Collider and/or attachment is also added when specified.</para>
 /// </remarks>
 /// <param name="context">Describes context of tile that is being painted.</param>
 /// <param name="tile">The tile.</param>
 /// <param name="addCollider">Indicates if collider should be added.</param>
 protected void CreateProceduralTile(IBrushContext context, TileData tile, bool addCollider)
 {
     // Attach object to tile?
     if (addCollider || this.attachPrefab != null)
     {
         tile.gameObject = new GameObject("tile");
         this.AddAttachments(context, tile, tile.gameObject, addCollider);
     }
     else if (this.alwaysAddContainer)
     {
         tile.gameObject = new GameObject("tile");
     }
 }
        /// <inheritdoc/>
        protected internal override bool CalculateManualOffset(IBrushContext context, TileData tile, Transform transform, out Vector3 offsetPosition, out Quaternion offsetRotation, out Vector3 offsetScale, Brush transformer)
        {
            var orientation = this.FindOrientation(tile.orientationMask);

            if (orientation != null && orientation.VariationCount != 0)
            {
                // Note: Do not update variation index in tile data because this may be unintended!
                int variationIndex = (int)tile.variationIndex;
                if (variationIndex >= orientation.VariationCount)
                {
                    variationIndex = 0;
                }

                var nestedBrush = orientation.GetVariation(variationIndex) as Brush;
                if (nestedBrush != null)
                {
                    // If transforming brush has not already been overridden then...
                    if (transformer == this && !this.overrideTransforms)
                    {
                        transformer = nestedBrush;
                    }
                    return(nestedBrush.CalculateManualOffset(context, tile, transform, out offsetPosition, out offsetRotation, out offsetScale, transformer));
                }

                var prefab = orientation.GetVariation(variationIndex) as GameObject;
                if (prefab != null)
                {
                    Matrix4x4 normalPlacement = transformer.GetTransformMatrix(context.TileSystem, context.Row, context.Column, tile.Rotation, prefab.transform);
                    MathUtility.DecomposeMatrix(ref normalPlacement, out offsetPosition, out offsetRotation, out offsetScale);

                    Vector3 localScale = transform.localScale;

                    offsetPosition = transform.localPosition - offsetPosition;
                    offsetRotation = Quaternion.Inverse(offsetRotation) * transform.localRotation;
                    offsetScale    = new Vector3(
                        localScale.x / offsetScale.x,
                        localScale.y / offsetScale.y,
                        localScale.z / offsetScale.z
                        );

                    return(true);
                }
            }

            return(IdentityManualOffset(out offsetPosition, out offsetRotation, out offsetScale));
        }
Exemple #14
0
        /// <inheritdoc/>
        protected internal override void PostProcessTile(IBrushContext context, TileData tile)
        {
            if (tile == null)
            {
                return;
            }

            var go = tile.gameObject;

            if (go != null)
            {
                // Assign tag and layer to tile.
                go.tag   = this.tag;
                go.layer = this.layer;

                InternalUtility.HideEditorWireframe(go);
            }
        }
        /// <inheritdoc/>
        protected internal override void PrepareTileData(IBrushContext context, TileData tile, int variationIndex)
        {
            // Find actual orientation of target tile.
            int actualOrientation = OrientationUtility.DetermineTileOrientation(context.TileSystem, context.Row, context.Column, context.Brush, tile.PaintedRotation);

            // Find nearest match, assume default scenario.
            tile.orientationMask = (byte)this.Tileset.FindClosestOrientation(actualOrientation);

            tile.Procedural   = true;
            tile.tileset      = this.Tileset;
            tile.tilesetIndex = this.Tileset.IndexFromOrientation(tile.orientationMask);

            // Is this an inner tile?
            if ((tile.orientationMask & 0x5A) == 0x5A)
            {
                tile.SolidFlag = this.InnerSolidFlag;
            }
        }
        /// <inheritdoc/>
        protected internal override void CreateTile(IBrushContext context, TileData tile)
        {
            // Attach object to tile?
            if (this.addCollider || this.alwaysAddContainer)
            {
                tile.gameObject = new GameObject("tile");

                if (this.addCollider)
                {
                    switch (this.colliderType)
                    {
                    case Tile.ColliderType.BoxCollider2D:
                        tile.gameObject.AddComponent <BoxCollider2D>();
                        break;

                    case Tile.ColliderType.BoxCollider3D:
                        tile.gameObject.AddComponent <BoxCollider>();
                        break;
                    }
                }
            }
        }
Exemple #17
0
        /// <summary>
        /// Helper method to draw immediate preview of tileset tile.
        /// </summary>
        /// <remarks>
        /// <para>Attached prefab will also be included in preview when applicable.</para>
        /// </remarks>
        /// <param name="context">Describes context of tile that is being previewed.</param>
        /// <param name="previewMaterial">Material to use for preview.</param>
        /// <param name="previewTile">Data for preview tile.</param>
        /// <param name="transformer">Brush used to transform painted tile.
        /// The <see cref="Brush.scaleMode"/> and <see cref="Brush.applyPrefabTransform"/>
        /// fields of transform brush should be used. <c>transformer</c> may refer to this
        /// brush, or it may refer to another (like alias or oriented for example).</param>
        protected void DrawImmediateTilePreview(IBrushContext context, Material previewMaterial, TileData previewTile, Brush transformer)
        {
            var atlasTexture = Tileset.AtlasTexture;

            if (atlasTexture == null)
            {
                return;
            }

            // Prepare mesh for tile background.
            Rect texCoords = Tileset.CalculateTexCoords(previewTile.tilesetIndex);
            var  mesh      = ImmediatePreviewUtility.UpdateQuadPreviewMesh(texCoords);

            // Compute matrix for tile background.
            var tileSystem = context.TileSystem;

            Matrix4x4 matrix;

            tileSystem.CalculateTileMatrix(out matrix, context.Row, context.Column, TileFacing.Sideways, previewTile.Rotation);
            MathUtility.MultiplyMatrixByScale(ref matrix, tileSystem.CalculateCellSizeScale(previewTile.Rotation));

            matrix = ImmediatePreviewUtility.Matrix * matrix;

            // Draw tile background.
            previewMaterial.mainTexture = atlasTexture;
            ImmediatePreviewUtility.DrawNow(previewMaterial, mesh, matrix);

            // Draw preview of tile attachment?
            if (this.attachPrefab != null)
            {
                int rotation = this.applySimpleRotationToAttachment ? previewTile.PaintedRotation : 0;

                var attachmentTransform = this.attachPrefab.transform;
                matrix = tileSystem.transform.localToWorldMatrix * transformer.GetTransformMatrix(tileSystem, context.Row, context.Column, rotation, attachmentTransform);

                ImmediatePreviewUtility.DrawNow(previewMaterial, attachmentTransform, matrix, context.Brush as IMaterialMappings);
            }
        }
Exemple #18
0
        /// <inheritdoc/>
        protected internal override bool CalculateManualOffset(IBrushContext context, TileData tile, Transform transform, out Vector3 offsetPosition, out Quaternion offsetRotation, out Vector3 offsetScale, Brush transformer)
        {
            var tileSystem = context.TileSystem;

            // Calculate normal position of tile within system.
            offsetPosition = tileSystem.LocalPositionFromTileIndex(context.Row, context.Column, true);
            // Turn tile to face away from system and rotate tile to align with system.
            offsetRotation = tileSystem.CalculateSimpleRotation(TileFacing.Sideways, tile.Rotation) * MathUtility.AngleAxis_180_Up;
            // Adjust scale of tile container.
            offsetScale = tileSystem.CalculateCellSizeScale(tile.Rotation);

            Vector3 localScale = transform.localScale;

            offsetPosition = transform.localPosition - offsetPosition;
            offsetRotation = Quaternion.Inverse(offsetRotation) * transform.localRotation;
            offsetScale    = new Vector3(
                localScale.x / offsetScale.x,
                localScale.y / offsetScale.y,
                localScale.z / offsetScale.z
                );

            return(true);
        }
Exemple #19
0
        /// <summary>
        /// Create non-procedural tile.
        /// </summary>
        /// <remarks>
        /// <para>Creates container game object for tile and adds the mesh filter and
        /// renderer components for tile mesh. Collider and/or attachment is also added
        /// when specified.</para>
        /// </remarks>
        /// <param name="context">Describes context of tile that is being painted.</param>
        /// <param name="tile">The tile.</param>
        /// <param name="addCollider">Indicates if collider should be added.</param>
        protected void CreateNonProceduralTile(IBrushContext context, TileData tile, bool addCollider)
        {
            // Create container object for tile and attach to chunk.
            var tileGO = new GameObject("tile");

            tile.gameObject = tileGO;

            if (addCollider || this.attachPrefab != null)
            {
                this.AddAttachments(context, tile, tileGO, addCollider);
            }

            var tileset      = tile.tileset;
            int tilesetIndex = tile.tilesetIndex;

            if (tileset.tileMeshes != null && tilesetIndex >= 0 && tilesetIndex < tileset.tileMeshes.Length)
            {
                var filter = tileGO.AddComponent <MeshFilter>();
                filter.sharedMesh = tileset.tileMeshes[tilesetIndex];

                var renderer = tileGO.AddComponent <MeshRenderer>();
                renderer.sharedMaterial = tileset.AtlasMaterial;
            }
        }
        /// <inheritdoc/>
        protected internal override void PrepareTileData(IBrushContext context, TileData tile, int variationIndex)
        {
            var tileSystem = context.TileSystem;

            // Find actual orientation of target tile.
            int actualOrientation = OrientationUtility.DetermineTileOrientation(tileSystem, context.Row, context.Column, context.Brush, tile.PaintedRotation);
            // Try to find nearest match, assume default scenario.
            int bestOrientation = this.FindClosestOrientationMask(actualOrientation);

            // Select tile for painting using tile brush.
            var orientation = this.FindOrientation(bestOrientation);

            if (orientation == null)
            {
                Debug.LogWarning(string.Format("Brush '{0}' orientation '{1}' not defined", this.name, OrientationUtility.NameFromMask(bestOrientation)));
                return;
            }

            int orientationVariationCount = orientation.VariationCount;

            // Randomize variation?
            if (variationIndex == RANDOM_VARIATION)
            {
                if (!tileSystem.BulkEditMode || tileSystem.IsEndingBulkEditMode)
                {
                    variationIndex = orientation.PickRandomVariationIndex();
                }
            }
            // Negative offset from variations of orientation.
            else if (variationIndex < 0)
            {
                variationIndex = Mathf.Max(0, orientationVariationCount + variationIndex);
            }

            // Ensure variation index is within bounds of orientation!
            int wrappedVariationIndex = variationIndex;

            if (wrappedVariationIndex >= orientationVariationCount)
            {
                wrappedVariationIndex = 0;
            }

            if (orientationVariationCount > 0)
            {
                //
                // Could re-insert following to 'fix' state of randomly selected tiles.
                // Note: Randomization is lost when erasing tiles from mass filled areas.
                //
                //// Persist wrapped variation when painting tile?
                //if (!system.BulkEditMode || system.IsEndingBulkEditMode) {
                //    variationIndex = wrappedVariationIndex;
                //}

                // Fetch nested brush reference (if there is one).
                var nestedBrush = orientation.GetVariation(wrappedVariationIndex) as Brush;
                if (nestedBrush != null)
                {
                    // Prepare tile data using nested brush.
                    nestedBrush.PrepareTileData(context, tile, wrappedVariationIndex);
                }
            }

            tile.orientationMask = (byte)bestOrientation;
            tile.variationIndex  = (byte)variationIndex;

            // Do not attempt automatic rotation where rotation has been manually specified.
            int rotation = tile.PaintedRotation + orientation.Rotation;

            if (rotation > 3)
            {
                rotation -= 4;
            }
            tile.Rotation = rotation;
        }
Exemple #21
0
 /// <inheritdoc/>
 protected internal override void PostProcessTile(IBrushContext context, TileData tile)
 {
     this.target.PostProcessTile(context, tile);
     base.PostProcessTile(context, tile);
 }
 /// <inheritdoc/>
 protected internal override bool CalculateManualOffset(IBrushContext context, TileData tile, Transform transform, out Vector3 offsetPosition, out Quaternion offsetRotation, out Vector3 offsetScale, Brush transformer)
 {
     return(IdentityManualOffset(out offsetPosition, out offsetRotation, out offsetScale));
 }
Exemple #23
0
 /// <inheritdoc/>
 protected internal override void CreateTile(IBrushContext context, TileData tile)
 {
     this.target.CreateTile(context, tile);
 }
Exemple #24
0
 /// <inheritdoc/>
 protected internal override void PrepareTileData(IBrushContext context, TileData tile, int variationIndex)
 {
     this.target.PrepareTileData(context, tile, variationIndex);
 }
Exemple #25
0
 /// <inheritdoc/>
 public override void OnDrawImmediatePreview(IBrushContext context, TileData previewTile, Material previewMaterial, Brush transformer)
 {
     this.DrawImmediateTilePreview(context, previewMaterial, previewTile, transformer);
 }
 /// <summary>
 /// Method is invoked to draw immediate preview.
 /// </summary>
 /// <remarks>
 /// <para>Immediate preview should be drawn using the <a href="http://docs.unity3d.com/ScriptReference/Graphics.html"><c>Graphics</c></a>
 /// class from the <c>UnityEngine</c> API.</para>
 /// </remarks>
 /// <param name="context">Describes context of tile that is being previewed.</param>
 /// <param name="previewTile">Data for preview tile.</param>
 /// <param name="previewMaterial">Material to use for preview.</param>
 /// <param name="matrix">Matrix which describes transformation of tile.</param>
 /// <returns>
 /// A value of <c>true</c> if custom immediate preview was drawn; otherwise a value
 /// of <c>false</c> indicating that default implementation should be assumed.
 /// </returns>
 public abstract bool DrawImmediatePreview(IBrushContext context, TileData previewTile, Material previewMaterial, Matrix4x4 matrix);
Exemple #27
0
 /// <inheritdoc/>
 protected internal override void PrepareTileData(IBrushContext context, TileData tile, int variationIndex)
 {
     tile.Procedural   = this.IsProcedural;
     tile.tileset      = this.tileset;
     tile.tilesetIndex = this.tileIndex;
 }