Example #1
0
    /// <summary>
    /// Checks if the given sprite is valid for the given mask of positions.
    /// </summary>
    /// <param name="spriteNeighbourMask">The sprite to check against the mask of positions.</param>
    /// <param name="mask">The mask of tile positions to compare against.</param>
    /// <returns></returns>
    protected bool MatchesMask(SpriteNeighbourMask spriteNeighbourMask, SpriteNeighbour mask)
    {
        // Convert optional positions to 1 in both masks so they don't effect the comparison
        SpriteNeighbour tempMask = mask | spriteNeighbourMask.optionalNeighboursMask;
        SpriteNeighbour tempReq  = spriteNeighbourMask.requiredNeighboursMask | spriteNeighbourMask.optionalNeighboursMask;

        return(tempMask == tempReq && spriteNeighbourMask.sprite);
    }
Example #2
0
 protected override Sprite GetSprite(SpriteNeighbour mask)
 {
     foreach (SpriteNeighbourMask sm in m_Sprites)
     {
         if (MatchesMask(sm, mask))
         {
             return(sm.sprite);
         }
     }
     return(m_Error);
 }
Example #3
0
 protected override Sprite GetSprite(SpriteNeighbour mask)
 {
     foreach (AnimatedSpriteNeighbourMask sm in m_Sprites)
     {
         if (MatchesMask(sm, mask))
         {
             m_CurrentSprite = sm;
             return(sm.sprite);
         }
     }
     return(m_Error);
 }
Example #4
0
    public override void GetTileData(Vector3Int position, ITilemap tilemap, ref TileData tileData)
    {
        base.GetTileData(position, tilemap, ref tileData);
        SpriteNeighbour mask = 0;

        for (int i = 0; i < m_PositionsToCheck.Length; i++)
        {
            mask += (byte)(HasTile(tilemap, position + m_PositionsToCheck[i]) ? Mathf.Pow(2, i) : 0);
        }

        tileData.sprite = GetSprite(mask);
    }
    /// <summary>
    /// Generates a toggle grid for a sprite neighbour mask.
    /// </summary>
    /// <param name="offset">The position of the top-left corner of the grid</param>
    /// <param name="mask">The mask to generate a grid for</param>
    /// <returns>The mask value after being modified by user input</returns>
    protected SpriteNeighbour ToggleGrid(Rect rect, SpriteNeighbour mask, string label = "")
    {
        if (label != "")
        {
            Rect labelRect = new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight);
            EditorGUI.LabelField(labelRect, label);

            // Shrink rect by area taken up by label so toggles are evenly distributed
            rect.y      += EditorGUIUtility.singleLineHeight;
            rect.height -= EditorGUIUtility.singleLineHeight;
        }
        //EditorGUI.DrawRect(rect, new Color(1f, 0f, 0f));
        // Subtract space taken by final row/col of toggles so they can be placed at xMax/yMax
        rect.width  -= EditorGUIUtility.singleLineHeight;
        rect.height -= EditorGUIUtility.singleLineHeight;

        for (int r = 0; r < 3; r++)
        {
            for (int c = 0; c < 3; c++)
            {
                if (r != 1 || c != 1)
                {
                    // Conditional reduces the array index once it skips the middle square, because there are only 8 enums but the loop counts 0 to 8 (9 positions)
                    SpriteNeighbour positionMask = m_EnumValues[r * 3 + c - (r * 3 + c > 4 ? 1 : 0)];
                    bool            value        = (mask & positionMask) == positionMask;

                    Rect checkboxRect = new Rect(
                        Mathf.Lerp(rect.xMin, rect.xMax, c / 2f),
                        Mathf.Lerp(rect.yMin, rect.yMax, r / 2f),
                        EditorGUIUtility.singleLineHeight, // For some reason the checkbox is unclickable unless the width is doubled
                        EditorGUIUtility.singleLineHeight
                        );
                    value = EditorGUI.Toggle(checkboxRect, value);

                    if (EditorGUI.Toggle(checkboxRect, value))
                    {
                        // Toggle set to true, so set this bit to 1 with an OR mask
                        mask = mask | positionMask;
                    }
                    else
                    {
                        // Toggle set to false, so set this bit to 0 with an inverted AND mask
                        mask = mask & ~positionMask;
                    }
                }
            }
        }

        return(mask);
    }
    /// <summary>
    /// Render the control to the inspector.
    /// </summary>
    /// <param name="position">The rect containing the control.</param>
    /// <param name="property">The serialized property to render the control for.</param>
    /// <param name="label">The label for this property.</param>
    protected virtual void Render(Rect position, SerializedProperty property, GUIContent label)
    {
        SerializedProperty spriteProp       = property.FindPropertyRelative("sprite");
        SerializedProperty requiredMaskProp = property.FindPropertyRelative("requiredNeighboursMask");
        SerializedProperty optionalMaskProp = property.FindPropertyRelative("optionalNeighboursMask");

        // Place sprite field along the top above sprite preview and to the right of mask grids
        Rect spriteFieldRect = new Rect(
            position.x,
            position.y,
            position.width - maskGridSize * 2 - EditorGUIUtility.singleLineHeight * 2,
            EditorGUIUtility.singleLineHeight
            );
        // Place sprite preview along left edge
        Rect spritePreviewRect = new Rect(
            position.x,
            position.y + EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing,
            maskGridSize,
            maskGridSize
            );
        // Place required mask grid second from the right (singleLineHeight away from optional mask grid)
        Rect requiredMaskFieldRect = new Rect(
            position.xMax - maskGridSize * 2 - EditorGUIUtility.singleLineHeight,
            position.y,
            maskGridSize,
            maskGridSize + EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing
            );
        // Place optional mask grid along right edge
        Rect optionalMaskFieldRect = new Rect(
            position.xMax - maskGridSize,
            position.y,
            maskGridSize,
            maskGridSize + EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing
            );

        SpriteNeighbour requiredMaskVal = (SpriteNeighbour)requiredMaskProp.intValue;
        SpriteNeighbour optionalMaskVal = (SpriteNeighbour)optionalMaskProp.intValue;

        bool val = EditorGUI.PropertyField(spriteFieldRect, spriteProp, GUIContent.none);

        // Render preview sprite
        Sprite sprite = spriteProp.objectReferenceValue as Sprite;

        if (sprite != null)
        {
            Rect spritesheetRect = new Rect(
                sprite.textureRect.x / sprite.texture.width,
                sprite.textureRect.y / sprite.texture.height,
                sprite.textureRect.width / sprite.texture.width,
                sprite.textureRect.height / sprite.texture.height
                );
            GUI.DrawTextureWithTexCoords(spritePreviewRect, sprite.texture, spritesheetRect);
        }
        else
        {
            EditorGUI.DrawRect(spritePreviewRect, Color.grey);
        }

        requiredMaskVal = ToggleGrid(requiredMaskFieldRect, requiredMaskVal, "Required");
        optionalMaskVal = ToggleGrid(optionalMaskFieldRect, optionalMaskVal, "Optional");

        requiredMaskProp.intValue = (int)requiredMaskVal;
        optionalMaskProp.intValue = (int)optionalMaskVal;
    }
Example #7
0
 /// <summary>
 /// Gets the sprite matching the given mask of tile positions.
 /// </summary>
 /// <param name="mask">A mask of neighbouring tile positions.</param>
 /// <returns></returns>
 protected abstract Sprite GetSprite(SpriteNeighbour mask);