mirror of
https://git.do.srb2.org/STJr/UltimateZoneBuilder.git
synced 2024-12-02 08:32:55 +00:00
157 lines
5.1 KiB
C#
157 lines
5.1 KiB
C#
|
#region ================== Copyright (c) 2020 Boris Iwanski
|
|||
|
|
|||
|
/*
|
|||
|
* This program is free software: you can redistribute it and/or modify
|
|||
|
*
|
|||
|
* it under the terms of the GNU General Public License as published by
|
|||
|
*
|
|||
|
* the Free Software Foundation, either version 3 of the License, or
|
|||
|
* (at your option) any later version.
|
|||
|
*
|
|||
|
* This program is distributed in the hope that it will be useful,
|
|||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|||
|
*
|
|||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
|
|||
|
*
|
|||
|
* GNU General Public License for more details.
|
|||
|
*
|
|||
|
* You should have received a copy of the GNU General Public License
|
|||
|
* along with this program.If not, see<http://www.gnu.org/licenses/>.
|
|||
|
*/
|
|||
|
|
|||
|
#endregion
|
|||
|
|
|||
|
using System;
|
|||
|
using System.Collections.Generic;
|
|||
|
using System.Drawing;
|
|||
|
using System.Drawing.Imaging;
|
|||
|
using System.Drawing.Drawing2D;
|
|||
|
using System.IO;
|
|||
|
using System.Linq;
|
|||
|
using System.Text;
|
|||
|
using System.Threading.Tasks;
|
|||
|
using CodeImp.DoomBuilder.Geometry;
|
|||
|
using CodeImp.DoomBuilder.Map;
|
|||
|
using System.Diagnostics;
|
|||
|
|
|||
|
namespace CodeImp.DoomBuilder.BuilderModes.IO
|
|||
|
{
|
|||
|
internal struct ImageExportSettings
|
|||
|
{
|
|||
|
public string Name;
|
|||
|
public string Path;
|
|||
|
public bool Floor;
|
|||
|
public PixelFormat PixelFormat;
|
|||
|
public ImageFormat ImageFormat;
|
|||
|
|
|||
|
public ImageExportSettings(string name, string path, bool floor, PixelFormat pformat, ImageFormat iformat)
|
|||
|
{
|
|||
|
Name = name;
|
|||
|
Path = path;
|
|||
|
Floor = floor;
|
|||
|
PixelFormat = pformat;
|
|||
|
ImageFormat = iformat;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
internal class ImageExporter
|
|||
|
{
|
|||
|
public void Export(ICollection<Sector> sectors, ImageExportSettings settings)
|
|||
|
{
|
|||
|
Bitmap bitmap;
|
|||
|
Vector2D offset = new Vector2D(double.MaxValue, double.MinValue);
|
|||
|
Vector2D size = new Vector2D(double.MinValue, double.MaxValue);
|
|||
|
|
|||
|
HashSet<Vertex> vertices = new HashSet<Vertex>();
|
|||
|
|
|||
|
// Find the top left and bottom right corners of the selection
|
|||
|
foreach(Sector s in sectors)
|
|||
|
{
|
|||
|
foreach (Sidedef sd in s.Sidedefs)
|
|||
|
{
|
|||
|
foreach (Vertex v in new Vertex[] { sd.Line.Start, sd.Line.End })
|
|||
|
{
|
|||
|
if (v.Position.x < offset.x)
|
|||
|
offset.x = v.Position.x;
|
|||
|
|
|||
|
if (v.Position.x > size.x)
|
|||
|
size.x = v.Position.x;
|
|||
|
|
|||
|
if (v.Position.y > offset.y)
|
|||
|
offset.y = v.Position.y;
|
|||
|
|
|||
|
if (v.Position.y < size.y)
|
|||
|
size.y = v.Position.y;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Right now "size" is the bottom right corener of the selection, so subtract the offset
|
|||
|
// (top left corner of the selection). y will always be negative, so make it positive
|
|||
|
size -= offset;
|
|||
|
size.y *= -1.0;
|
|||
|
|
|||
|
bitmap = new Bitmap((int)size.x, (int)size.y, settings.PixelFormat);
|
|||
|
|
|||
|
Graphics g = Graphics.FromImage(bitmap);
|
|||
|
g.Clear(Color.Black); // If we don't clear to black we'll see seams where the sectors touch, due to the AA
|
|||
|
g.InterpolationMode = InterpolationMode.HighQualityBilinear;
|
|||
|
g.CompositingQuality = CompositingQuality.HighQuality;
|
|||
|
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
|
|||
|
g.SmoothingMode = SmoothingMode.AntiAlias; // Without AA the sector edges will be quite rough
|
|||
|
|
|||
|
foreach (Sector s in sectors)
|
|||
|
{
|
|||
|
GraphicsPath p = new GraphicsPath();
|
|||
|
float rotation = (float)s.Fields.GetValue("rotationfloor", 0.0);
|
|||
|
|
|||
|
// If a sector is rotated any offset is on the rotated axes. But we need to offset by
|
|||
|
// map coordinates. We'll use this vector to compute that offset
|
|||
|
Vector2D rotationvector = Vector2D.FromAngle(Angle2D.DegToRad(rotation) + Angle2D.PIHALF);
|
|||
|
|
|||
|
// Sectors are triangulated, so draw every triangle
|
|||
|
for (int i = 0; i < s.Triangles.Vertices.Count / 3; i++)
|
|||
|
{
|
|||
|
// The GDI image has the 0/0 coordinate in the top left, so invert the y component
|
|||
|
Vector2D v1 = s.Triangles.Vertices[i * 3] - offset; v1.y *= -1.0;
|
|||
|
Vector2D v2 = s.Triangles.Vertices[i * 3 + 1] - offset; v2.y *= -1.0;
|
|||
|
Vector2D v3 = s.Triangles.Vertices[i * 3 + 2] - offset; v3.y *= -1.0;
|
|||
|
|
|||
|
p.AddLine((float)v1.x, (float)v1.y, (float)v2.x, (float)v2.y);
|
|||
|
p.AddLine((float)v2.x, (float)v2.y, (float)v3.x, (float)v3.y);
|
|||
|
p.CloseFigure();
|
|||
|
}
|
|||
|
|
|||
|
Bitmap texture;
|
|||
|
|
|||
|
if(settings.Floor)
|
|||
|
texture = General.Map.Data.GetFlatImage(s.FloorTexture).ExportBitmap();
|
|||
|
else
|
|||
|
texture = General.Map.Data.GetFlatImage(s.CeilTexture).ExportBitmap();
|
|||
|
|
|||
|
Vector2D textureoffset = new Vector2D();
|
|||
|
textureoffset.x = s.Fields.GetValue("xpanningfloor", 0.0);
|
|||
|
textureoffset.y = s.Fields.GetValue("ypanningfloor", 0.0);
|
|||
|
|
|||
|
// Create the transformation matrix
|
|||
|
Matrix matrix = new Matrix();
|
|||
|
matrix.Rotate(rotation);
|
|||
|
matrix.Translate((float)(-offset.x * rotationvector.x), (float)(offset.x * rotationvector.y)); // Left/right offset from the map origin
|
|||
|
matrix.Translate((float)(offset.y * rotationvector.y), (float)(offset.y * rotationvector.x)); // Up/down offset from the map origin
|
|||
|
matrix.Translate(-(float)textureoffset.x, -(float)textureoffset.y); // Texture offset
|
|||
|
|
|||
|
// Create the texture brush and apply the matrix
|
|||
|
TextureBrush t = new TextureBrush(texture);
|
|||
|
t.Transform = matrix;
|
|||
|
|
|||
|
// Draw the islands of the sector
|
|||
|
g.FillPath(t, p);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
// Finally save the image
|
|||
|
bitmap.Save(Path.Combine(settings.Path, settings.Name), settings.ImageFormat);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|