JD2022-TU1/main/tools/legacy/UA_AtlasEditor/Tools/TextureArea.cs

390 lines
14 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;
using System.Runtime.InteropServices;
public class TextureArea : IDisposable
{
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
private static extern short GetKeyState(int keyCode);
//-----------------------------------------------------------------------------------------
// members
//
Image _texture = null;
Color _backColor = Color.Black;
bool _bilinearFilter = true;
Rectangle _winRect = new Rectangle(); // window rect to display atlas
Rectangle _winTextureRect = new Rectangle(); // window rect to display texture (keeping texture ratio)
RectangleF _textureRect = new RectangleF(); // rect of texture to be displayed
RectangleF _capturedTextureRect;
Point _captureStart;
RectangleF _allTextureRectRatio = new RectangleF();
Rectangle _allTextureRect = new Rectangle();
Rectangle _capturedAllTextureRect;
//-----------------------------------------------------------------------------------------
Bitmap _TextureCache = null;
Rectangle _TextureCacheTextureRect = Rectangle.FromLTRB(0, 0, 0, 0);
Rectangle _TextureCacheWindowRect = Rectangle.FromLTRB(0, 0, 0, 0);
Rectangle _TextureCacheRect = Rectangle.FromLTRB(0, 0, 0, 0);
//-----------------------------------------------------------------------------------------
// init
//
public void init()
{
_textureRect = new RectangleF(0, 0, 1.0f, 1.0f);
_allTextureRectRatio = new RectangleF(0, 0, 1.0f, 1.0f);
}
//-----------------------------------------------------------------------------------------
// accessors
//
public void setTexture(Image texture) { _texture = texture; }
public void setBackColor( Color backColor ) { _backColor = backColor; }
public void setBilinearFilter(bool bilinearFilter) { _bilinearFilter = bilinearFilter; }
public void setWinRect(Rectangle rectangle)
{
_winRect = rectangle;
_winTextureRect = rectangle;
if (_texture == null) return;
int y = (_winTextureRect.Width * _texture.Height) / _texture.Width;
if (y < _winTextureRect.Height)
{
_winTextureRect.Y = _winTextureRect.Y + (_winTextureRect.Height - y) / 2;
_winTextureRect.Height = y;
}
else
{
int x = (_winTextureRect.Height * _texture.Width) / _texture.Height;
_winTextureRect.X = _winTextureRect.X + (_winTextureRect.Width - x) / 2;
_winTextureRect.Width = x;
}
_allTextureRectRatio.X = (float)(_winTextureRect.Left - _winRect.Left) / (float) _winRect.Width;
_allTextureRectRatio.Width = (float)_winTextureRect.Width / (float)_winRect.Width;
_allTextureRectRatio.Y = (float)(_winTextureRect.Top - _winRect.Top) / (float)_winRect.Height;
_allTextureRectRatio.Height = (float)_winTextureRect.Height / (float)_winRect.Height;
}
public Rectangle getWinRect() { return _winRect; }
public Rectangle getWinTextureRect() { return _winTextureRect; }
public void setSubRect(RectangleF rectangleF) { _textureRect = rectangleF; }
public RectangleF getSubRect() { return _textureRect; }
public int getTextureWidth() { return _texture != null ? _texture.Width : 0; }
public int getTextureHeight() { return _texture != null ? _texture.Height: 0; }
readonly bool _methodOld = false;
//-----------------------------------------------------------------------------------------
// clip painting region
//
public void clip(ref Graphics graphics)
{
if (_methodOld)
graphics.Clip = new Region(getWinTextureRect());
else
graphics.Clip = new Region(getWinRect());
}
//-----------------------------------------------------------------------------------------
// paint
//
public void paintOld(Graphics graphics)
{
// display background
Region region = new Region(getWinRect());
region.Exclude(getWinTextureRect());
graphics.Clip = region;
graphics.FillRectangle(new SolidBrush(Color.Black), getWinRect());
graphics.Clip = new Region(getWinTextureRect());
// display image
if (_texture != null)
{
Rectangle displayRectangle = new Rectangle();
displayRectangle.X = (int)(getSubRect().X * (_texture.Width));
displayRectangle.Y = (int)(getSubRect().Y * (_texture.Height));
displayRectangle.Width = (int)(getSubRect().Width * (_texture.Width));
displayRectangle.Height = (int)(getSubRect().Height * (_texture.Height));
Rectangle windowRect = getWinTextureRect();
if (_TextureCache == null || _TextureCacheTextureRect != displayRectangle || _TextureCacheWindowRect != windowRect || _TextureCache != _texture)
{
if (_TextureCacheWindowRect != windowRect || _TextureCache == null)
{
if (_TextureCache != null) _TextureCache.Dispose();
_TextureCache = new Bitmap(_texture, windowRect.Width, windowRect.Height);
_TextureCacheWindowRect = windowRect;
}
Graphics g = Graphics.FromImage(_TextureCache);
g.Clear(_backColor);
if (_bilinearFilter)
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Bilinear;
else
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Half;
_TextureCacheRect.Width = windowRect.Width;
_TextureCacheRect.Height = windowRect.Height;
g.DrawImage(_texture, _TextureCacheRect, displayRectangle, GraphicsUnit.Pixel);
g.Dispose();
_TextureCacheTextureRect = displayRectangle;
}
graphics.DrawImage(_TextureCache, windowRect.Left, windowRect.Top);
}
}
//-----------------------------------------------------------------------------------------
public void computeDisplayRect()
{
_allTextureRect.X = (int)(_allTextureRectRatio.X * _winRect.Width + _winRect.Left);
_allTextureRect.Width = (int)(_allTextureRectRatio.Width * _winRect.Width);
_allTextureRect.Y = (int)(_allTextureRectRatio.Y * _winRect.Height + _winRect.Top);
_allTextureRect.Height = (int)(_allTextureRectRatio.Height * _winRect.Height);
_winTextureRect = _allTextureRect;
_winTextureRect.Intersect(_winRect);
_textureRect.X = (float)(_winTextureRect.X - _allTextureRect.X) / (float)_allTextureRect.Width;
_textureRect.Width = (float)_winTextureRect.Width / (float)_allTextureRect.Width;
_textureRect.Y = (float)(_winTextureRect.Y - _allTextureRect.Y) / (float)_allTextureRect.Height;
_textureRect.Height = (float)_winTextureRect.Height / (float)_allTextureRect.Height;
}
//-----------------------------------------------------------------------------------------
public void computeAllTextureRect()
{
_allTextureRect.Width = (int) (_winTextureRect.Width / _textureRect.Width);
_allTextureRect.Height = (int) (_winTextureRect.Height / _textureRect.Height);
_allTextureRect.X = (int) (_winTextureRect.X - _textureRect.X * _allTextureRect.Width);
_allTextureRect.Y = (int) (_winTextureRect.Y - _textureRect.Y * _allTextureRect.Height);
computeAllTextureRectRatio();
}
//-----------------------------------------------------------------------------------------
public void computeAllTextureRectRatio()
{
_allTextureRectRatio.X = (float)(_allTextureRect.Left - _winRect.Left) / (float)_winRect.Width;
_allTextureRectRatio.Width = (float)_allTextureRect.Width / (float)_winRect.Width;
_allTextureRectRatio.Y = (float)(_allTextureRect.Top - _winRect.Top) / (float)_winRect.Height;
_allTextureRectRatio.Height = (float)_allTextureRect.Height / (float)_winRect.Height;
}
//-----------------------------------------------------------------------------------------
// paint
//
public void paintNew(Graphics graphics)
{
// display image
if (_texture == null)
{
graphics.FillRectangle(new SolidBrush(Color.Black), getWinRect());
return;
}
computeDisplayRect();
if (_winTextureRect.IsEmpty)
{
graphics.FillRectangle(new SolidBrush(Color.Black), getWinRect());
return;
}
paintOld( graphics );
}
//-----------------------------------------------------------------------------------------
// paint
//
public void paint(Graphics graphics)
{
if (_methodOld)
paintOld(graphics);
else
paintNew(graphics);
}
//-----------------------------------------------------------------------------------------
// picking
//
public bool isWinPointInside(Point point) { return _winTextureRect.Contains(point); }
//-----------------------------------------------------------------------------------------
// edit sub rect
//
public void subRectZoom(Point pos, bool inOrOut)
{
float xwinratio = (float)(pos.X - _winTextureRect.Left) / (float)_winTextureRect.Width;
float ywinratio = (float)(pos.Y - _winTextureRect.Top) / (float)_winTextureRect.Height;
float xtextureratioBefore = _textureRect.Left + xwinratio * (_textureRect.Width);
float ytextureratioBefore = _textureRect.Top + ywinratio * (_textureRect.Height);
float w = (_textureRect.Width * 0.05f) * (inOrOut ? 1 : -1);
float h = (_textureRect.Height * 0.05f) * (inOrOut ? 1 : -1);
_textureRect.Inflate(w, h);
float xtextureratioAfter = _textureRect.Left + xwinratio * (_textureRect.Width);
float ytextureratioAfter = _textureRect.Top + ywinratio * (_textureRect.Height);
_textureRect.X += xtextureratioBefore - xtextureratioAfter;
_textureRect.Y += ytextureratioBefore - ytextureratioAfter;
computeAllTextureRect();
}
public void subRectStartPan(Point pos)
{
_captureStart = pos;
_capturedTextureRect = getSubRect();
_capturedAllTextureRect = _allTextureRect;
}
public void subRectPan(Point pos)
{
if (_methodOld)
{
float ratiox = _capturedTextureRect.Width / (float)_winTextureRect.Width;
_textureRect.X = _capturedTextureRect.X + (_captureStart.X - pos.X) * ratiox;
float ratioy = _capturedTextureRect.Height / (float)_winTextureRect.Height;
_textureRect.Y = _capturedTextureRect.Y + (_captureStart.Y - pos.Y) * ratioy;
computeAllTextureRect();
}
else
{
_allTextureRect.X = _capturedAllTextureRect.X - (_captureStart.X - pos.X);
_allTextureRect.Y = _capturedAllTextureRect.Y - (_captureStart.Y - pos.Y);
computeAllTextureRectRatio();
}
}
//-----------------------------------------------------------------------------------------
// mouse function
//
bool _capturePan = false;
public bool mouseDown(Point pos)
{
if (!isWinPointInside(pos)) return false;
if (GetKeyState(32 /*VK_SPACE*/ ) >= 0) return false;
_capturePan = true;
subRectStartPan(pos);
return true;
}
public void mouseMove( Point pos )
{
if (!_capturePan) return;
subRectPan(pos);
}
public void mouseUp( Point pos )
{
_capturePan = false;
}
public bool mouseWheel(Point pos, bool inOrOut)
{
if (!isWinPointInside(pos)) return false;
if (GetKeyState(32 /*VK_SPACE*/ ) >= 0) return false;
subRectZoom(pos, inOrOut);
return true;
}
public bool mouseSetCursor(Point pos, ref Cursor cursor )
{
if (!isWinPointInside(pos)) return false;
if (GetKeyState(32 /*VK_SPACE*/ ) >= 0) return false;
cursor = Cursors.Hand;
return true;
}
//-----------------------------------------------------------------------------------------
// transformation function
//
public int x_atlas2win(float xAtlas)
{
int xTexture = (int)(xAtlas * _texture.Width + 0.5);
float xTextureDisplayed = ((float)xTexture - _TextureCacheTextureRect.Left) / (float)_TextureCacheTextureRect.Width;
int xTextureWindow = (int)_TextureCacheWindowRect.Left + (int)(_TextureCacheWindowRect.Width * xTextureDisplayed);
return xTextureWindow;
}
public int y_atlas2win(float yAtlas)
{
int yTexture = (int)(yAtlas * _texture.Height + 0.5);
float yTextureDisplayed = ((float) yTexture - _TextureCacheTextureRect.Top) / (float)_TextureCacheTextureRect.Height;
int yTextureWindow = (int)_TextureCacheWindowRect.Top + (int)(_TextureCacheWindowRect.Height * yTextureDisplayed);
return yTextureWindow;
}
public Point point_atlas2win(PointF pos)
{
return new Point(x_atlas2win(pos.X), y_atlas2win(pos.Y));
}
public Rectangle rect_atlas2win(RectangleF rect)
{
int x0 = x_atlas2win(rect.X);
int y0 = y_atlas2win(rect.Y);
int x1 = x_atlas2win(rect.Right);
int y1 = y_atlas2win(rect.Bottom);
return Rectangle.FromLTRB(x0, y0, x1, y1);
}
public float x_win2atlas(int xWin)
{
float x = xWin - _winTextureRect.Left;
x /= (float)_winTextureRect.Width;
return x * _textureRect.Width + _textureRect.Left;
}
public float y_win2atlas(int yWin)
{
float y = yWin - _winTextureRect.Top;
y /= (float)_winTextureRect.Height;
return y * _textureRect.Height + _textureRect.Top;
}
public PointF point_win2atlas(Point pos)
{
return new PointF(x_win2atlas(pos.X), y_win2atlas(pos.Y));
}
public RectangleF rect_win2atlas(Rectangle rect)
{
float x0 = x_win2atlas(rect.X);
float y0 = y_win2atlas(rect.Y);
float x1 = x_win2atlas(rect.Right);
float y1 = y_win2atlas(rect.Bottom);
return RectangleF.FromLTRB(x0, y0, x1, y1);
}
public void Dispose()
{
_texture?.Dispose();
_TextureCache?.Dispose();
}
}