public void HandleKeyboard()
    {
        if (Event.current.keyCode == KeyCode.Alpha1)
        {
            brushType = BrushType.Brush1;
        }
        if (Event.current.keyCode == KeyCode.Alpha2)
        {
            brushType = BrushType.Brush3;
        }
        if (Event.current.keyCode == KeyCode.Alpha3)
        {
            brushType = BrushType.Brush5;
        }
        if (Event.current.keyCode == KeyCode.RightBracket)
        {
            brushType = (BrushType)((int)brushType < 2 ? (int)brushType + 1 : 0);
        }
        if (Event.current.keyCode == KeyCode.LeftBracket)
        {
            brushType = (BrushType)((int)brushType > 0 ? (int)brushType - 1 : 2);
        }
        if (Event.current.keyCode == KeyCode.RightArrow && (Event.current.control || Event.current.command) && Event.current.type == EventType.keyDown)
        {
            selection = null;
            selectionActive = false;
            ragePixelSprite.shiftCell(1, true);
            ragePixelSprite.refreshMesh();
            animStripGUI.isDirty = true;
            Event.current.Use();
        }
        if (Event.current.keyCode == KeyCode.LeftArrow && (Event.current.control || Event.current.command) && Event.current.type == EventType.keyDown)
        {
            selection = null;
            selectionActive = false;
            ragePixelSprite.shiftCell(-1, true);
            ragePixelSprite.refreshMesh();
            animStripGUI.isDirty = true;
            Event.current.Use();
        }
        if (Event.current.keyCode == KeyCode.Z && (Event.current.control || Event.current.command) && Event.current.alt && Event.current.type == EventType.keyDown)
        {
            DoPaintUndo();
            animStripGUI.isDirty = true;
            spriteSheetGUI.isDirty = true;
            atlasTextureIsDirty = true;
            Event.current.Use();
        }
        if (Event.current.keyCode == KeyCode.D && (Event.current.control || Event.current.command) && Event.current.alt && Event.current.type == EventType.keyDown && mode == Mode.Select)
        {
            backBuffer.PasteBitmap(selection.X, selection.Y, frontBuffer);
            animStripGUI.isDirty = true;
            spriteSheetGUI.isDirty = true;
            atlasTextureIsDirty = true;
            Event.current.Use();
        }
        if (Event.current.keyCode == KeyCode.X && (Event.current.control || Event.current.command) && Event.current.alt && Event.current.type == EventType.keyDown && mode == Mode.Select)
        {
            SavePaintUndo();
            RagePixelUtil.Settings.clipboard = new RagePixelBitmap(frontBuffer.pixels, frontBuffer.Width(), frontBuffer.Height());
            selectionActive = false;
            Rect currentUV = ragePixelSprite.GetCurrentCell().uv;
            Rect selectionUV = new Rect(
                currentUV.xMin + (float)selection.X / (float)spritesheetTexture.width,
                currentUV.yMin + (float)selection.Y / (float)spritesheetTexture.height,
                (float)(selection.X2 - selection.X + 1) / (float)spritesheetTexture.width,
                (float)(selection.Y2 - selection.Y + 1) / (float)spritesheetTexture.height
                );
            RagePixelUtil.clearPixels(spritesheetTexture, selectionUV);
            spritesheetTexture.Apply();
            atlasTextureIsDirty = true;

            selection = null;
            Event.current.Use();
        }
        if (Event.current.keyCode == KeyCode.C && (Event.current.control || Event.current.command) && Event.current.alt && Event.current.type == EventType.keyDown && mode == Mode.Select)
        {
            RagePixelUtil.Settings.clipboard = new RagePixelBitmap(frontBuffer.pixels, frontBuffer.Width(), frontBuffer.Height());
            selection = null;
            selectionActive = false;
            Event.current.Use();
        }
        if (Event.current.keyCode == KeyCode.V && (Event.current.control || Event.current.command) && Event.current.alt && Event.current.type == EventType.keyDown)
        {
            if (RagePixelUtil.Settings.clipboard != null)
            {
                mode = Mode.Select;

                SavePaintUndo();

                Rect spriteUV = ragePixelSprite.GetCurrentCell().uv;

                selection = new RagePixelTexelRect(
                    0,
                    0,
                    Mathf.Min(RagePixelUtil.Settings.clipboard.Width(), ragePixelSprite.GetCurrentRow().pixelSizeX),
                    Mathf.Min(RagePixelUtil.Settings.clipboard.Height(), ragePixelSprite.GetCurrentRow().pixelSizeY)
                    );

                backBuffer = GrabSprite(spriteUV);
                frontBuffer = RagePixelUtil.Settings.clipboard;

                frontBufferPosition = new RagePixelTexel(0, 0);
                frontBufferDragStartPosition = new RagePixelTexel(0, 0);

                PasteBitmapToSpritesheetAlpha(frontBufferPosition, spriteUV, frontBuffer);

                selectionActive = true;
                spritesheetTexture.Apply();

                Event.current.Use();
            }
        }
    }
    public RagePixelTexel WorldToTexelCoords(Texture2D tex, Transform t, Vector3 worldPos)
    {
        RagePixelTexel coords = new RagePixelTexel();
        Vector3 localPos = t.InverseTransformPoint(worldPos) - GetPivotOffset();

        switch (ragePixelSprite.mode)
        {
            case (RagePixelSprite.Mode.Default):
                coords.X = Mathf.FloorToInt(localPos.x);
                coords.Y = Mathf.FloorToInt(localPos.y);

                if (coords.X >= 0 && coords.Y >= 0 && coords.X < ragePixelSprite.pixelSizeX && coords.Y < ragePixelSprite.pixelSizeY)
                {
                    coords.X = coords.X % ragePixelSprite.GetCurrentRow().pixelSizeX;
                    coords.Y = coords.Y % ragePixelSprite.GetCurrentRow().pixelSizeY;
                }
                break;
            case (RagePixelSprite.Mode.Grid9):

                coords.X = Mathf.FloorToInt(localPos.x);
                coords.Y = Mathf.FloorToInt(localPos.y);

                if (coords.X >= 0 && coords.Y >= 0 && coords.X < ragePixelSprite.pixelSizeX && coords.Y < ragePixelSprite.pixelSizeY)
                {
                    if (coords.X < ragePixelSprite.grid9Left)
                    {
                        //noop
                    }
                    else if (coords.X >= ragePixelSprite.pixelSizeX - ragePixelSprite.grid9Right)
                    {
                        coords.X = ragePixelSprite.GetCurrentRow().pixelSizeX - (ragePixelSprite.pixelSizeX - coords.X);
                    }
                    else
                    {
                        coords.X = ragePixelSprite.grid9Left + (coords.X - ragePixelSprite.grid9Left) % (ragePixelSprite.GetCurrentRow().pixelSizeX - ragePixelSprite.grid9Left - ragePixelSprite.grid9Right);
                    }

                    if (coords.Y < ragePixelSprite.grid9Bottom)
                    {
                        //noop
                    }
                    else if (coords.Y >= ragePixelSprite.pixelSizeY - ragePixelSprite.grid9Top)
                    {
                        coords.Y = ragePixelSprite.GetCurrentRow().pixelSizeY - (ragePixelSprite.pixelSizeY - coords.Y);
                    }
                    else
                    {
                        coords.Y = ragePixelSprite.grid9Bottom + (coords.Y - ragePixelSprite.grid9Bottom) % (ragePixelSprite.GetCurrentRow().pixelSizeY - ragePixelSprite.grid9Top - ragePixelSprite.grid9Bottom);
                    }
                }
                break;
        }

        return coords;
    }
 public Vector3 TexelCoordsToWorld(Texture2D tex, Transform t, RagePixelTexel texel)
 {
     Vector3 v = new Vector3(texel.X, texel.Y, 0f);
     //v.Scale(new Vector3(1f/t.localScale.x,1f/t.localScale.y,1f));
     return t.TransformPoint(v + GetPivotOffset());
 }
    public void PasteBitmapToSpritesheetAlpha(RagePixelTexel position, Rect spriteUV, RagePixelBitmap bitmap)
    {
        for (int y = Mathf.Max(position.Y, 0); y < position.Y + bitmap.Height() && y < (int)(spriteUV.height * spritesheetTexture.height); y++)
        {
            for (int x = Mathf.Max(position.X, 0); x < position.X + bitmap.Width() && x < (int)(spriteUV.width * spritesheetTexture.width); x++)
            {
                Color src = bitmap.GetPixel(x - position.X, y - position.Y);
                Color trg = spritesheetTexture.GetPixel((int)(spriteUV.x * spritesheetTexture.width) + x, (int)(spriteUV.y * spritesheetTexture.height) + y);

                spritesheetTexture.SetPixel(
                    (int)(spriteUV.x * spritesheetTexture.width) + x,
                    (int)(spriteUV.y * spritesheetTexture.height) + y,
                    src + (1f-src.a) * trg
                    );
            }
        }
    }
 public void PasteBitmapToSpritesheet(RagePixelTexel position, Rect spriteUV, RagePixelBitmap bitmap)
 {
     for (int y = Mathf.Max(position.Y, 0); y < position.Y + bitmap.Height() && y < (int)(spriteUV.height * spritesheetTexture.height); y++)
     {
         for (int x = Mathf.Max(position.X, 0); x < position.X + bitmap.Width() && x < (int)(spriteUV.width * spritesheetTexture.width); x++)
         {
             spritesheetTexture.SetPixel(
                 (int)(spriteUV.x * spritesheetTexture.width) + x,
                 (int)(spriteUV.y * spritesheetTexture.height) + y,
                 bitmap.GetPixel(x - position.X, y - position.Y)
                 );
         }
     }
 }
    public void HandleModeSelect()
    {
        if (Event.current.type == EventType.mouseDown || Event.current.type == EventType.mouseDrag || Event.current.type == EventType.mouseUp)
        {
            Vector3 mouseWorldPosition = sceneScreenToWorldPoint(Event.current.mousePosition);

            RagePixelTexel texel = WorldToTexelCoords(spritesheetTexture, ragePixelSprite.transform, mouseWorldPosition);
            int spriteWidth = ragePixelSprite.GetCurrentRow().pixelSizeX;
            int spriteHeight = ragePixelSprite.GetCurrentRow().pixelSizeY;

            if (texel.X >= 0 && texel.X < spriteWidth &&
                texel.Y >= 0 && texel.Y < spriteHeight)
            {
                if (Event.current.type == EventType.mouseDown)
                {
                    if (Event.current.button == 0)
                    {
                        if (selection == null)
                        {
                            selectionActive = false;
                            selectionStart = texel;
                            selection = new RagePixelTexelRect(texel.X, texel.Y, texel.X, texel.Y);
                        }
                        else
                        {
                            if (texel.X < frontBufferPosition.X || texel.Y < frontBufferPosition.Y || texel.X > frontBufferPosition.X + selection.Width() || texel.Y > frontBufferPosition.Y + selection.Height())
                            {
                                selectionActive = false;
                                selectionStart = texel;
                                selection = new RagePixelTexelRect(texel.X, texel.Y, texel.X, texel.Y);
                            }
                            else
                            {
                                frontBufferDragStartMousePosition = texel;
                                frontBufferDragStartPosition = frontBufferPosition;
                            }
                        }
                    }
                }
                if (Event.current.type == EventType.mouseDrag)
                {
                    if (selectionActive)
                    {
                        RagePixelTexel movement = new RagePixelTexel(texel.X - frontBufferDragStartMousePosition.X, texel.Y - frontBufferDragStartMousePosition.Y);
                        frontBufferPosition = new RagePixelTexel(frontBufferDragStartPosition.X + movement.X, frontBufferDragStartPosition.Y + movement.Y);

                        Rect spriteUV = ragePixelSprite.GetCurrentCell().uv;

                        PasteBitmapToSpritesheet(new RagePixelTexel(0, 0), spriteUV, backBuffer);
                        PasteBitmapToSpritesheetAlpha(frontBufferPosition, spriteUV, frontBuffer);

                        spritesheetTexture.Apply();
                    }
                    else
                    {
                        selection = new RagePixelTexelRect(selectionStart.X, selectionStart.Y, texel.X, texel.Y);
                    }
                }
                if (Event.current.type == EventType.mouseUp && !selectionActive)
                {
                    if (selection.Width() > 1 || selection.Height() > 1)
                    {
                        SavePaintUndo();

                        Rect spriteUV = ragePixelSprite.GetCurrentCell().uv;

                        frontBuffer = GrabRectFromSpritesheet(selection);
                        CutRectInSpritesheet(selection, spriteUV);
                        backBuffer = GrabSprite(spriteUV);

                        frontBufferPosition = new RagePixelTexel(selection.X, selection.Y);
                        frontBufferDragStartPosition = new RagePixelTexel(selection.X, selection.Y);

                        PasteBitmapToSpritesheetAlpha(frontBufferPosition, spriteUV, frontBuffer);

                        selectionActive = true;
                        spritesheetTexture.Apply();
                    }
                    else
                    {
                        selection = null;
                        selectionActive = false;
                    }
                }
                if (selectionActive && Event.current.type == EventType.mouseUp)
                {
                    spritesheetTexture.Apply();
                    atlasTextureIsDirty = true;
                }
            }
            else
            {
                if (Event.current.type != EventType.mouseDrag)
                {
                    mode = Mode.Default;
                }

            }
            if (Event.current.type != EventType.mouseUp)
            {
                Event.current.Use();
            }
        }
    }