ZoneBuilder/Source/Plugins/BuilderModes/Interface/FitTexturesForm.cs

291 lines
7 KiB
C#

#region ================== Namespaces
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;
using CodeImp.DoomBuilder.Windows;
#endregion
namespace CodeImp.DoomBuilder.BuilderModes
{
internal struct FitTextureOptions
{
public int HorizontalRepeat;
public int VerticalRepeat;
public bool FitWidth;
public bool FitHeight;
public bool FitAcrossSurfaces;
public Rectangle GlobalBounds;
public Rectangle Bounds;
//Initial texture coordinats
public float InitialOffsetX;
public float InitialOffsetY;
public float ControlSideOffsetX;
public float ControlSideOffsetY;
public float InitialScaleX;
public float InitialScaleY;
}
internal partial class FitTexturesForm : DelayedForm
{
#region ================== Event handlers
#endregion
#region ================== Variables
private static Point location = Point.Empty;
private bool blockupdate;
private int prevhorizrepeat;
private int prevvertrepeat;
// Settings
private static int horizontalrepeat = 1;
private static int verticalrepeat = 1;
private static bool fitacrosssurfaces = true;
private static bool fitwidth = true;
private static bool fitheight = true;
//Surface stuff
private List<SortedVisualSide> strips;
#endregion
#region ================== Constructor
public FitTexturesForm()
{
InitializeComponent();
if(!location.IsEmpty)
{
this.StartPosition = FormStartPosition.Manual;
this.Location = location;
}
}
#endregion
#region ================== Methods
public bool Setup(IEnumerable<BaseVisualGeometrySidedef> sides)
{
// Get shapes
strips = BuilderModesTools.SortVisualSides(sides);
// No dice...
if(strips.Count == 0)
{
General.Interface.DisplayStatus(StatusType.Warning, "Failed to setup sidedef chains...");
this.DialogResult = DialogResult.Cancel;
this.Close();
return false;
}
#if DEBUG
//debug
DrawDebugUV();
#endif
// Restore settings
blockupdate = true;
horizrepeat.Value = horizontalrepeat;
vertrepeat.Value = verticalrepeat;
prevhorizrepeat = horizontalrepeat;
prevvertrepeat = verticalrepeat;
cbfitconnected.Checked = fitacrosssurfaces;
cbfitconnected.Enabled = (strips.Count > 1);
cbfitwidth.Checked = fitwidth;
cbfitheight.Checked = fitheight;
UpdateRepeatGroup();
blockupdate = false;
//trigger update
UpdateChanges();
return true;
}
private void UpdateChanges()
{
// Apply changes
FitTextureOptions options = new FitTextureOptions
{
FitAcrossSurfaces = (cbfitconnected.Enabled && cbfitconnected.Checked),
FitWidth = cbfitwidth.Checked,
FitHeight = cbfitheight.Checked,
HorizontalRepeat = (int)horizrepeat.Value,
VerticalRepeat = (int)vertrepeat.Value
};
foreach(SortedVisualSide side in strips) side.OnTextureFit(options);
}
private void UpdateRepeatGroup()
{
// Disable whole group?
repeatgroup.Enabled = cbfitwidth.Checked || cbfitheight.Checked;
if(!repeatgroup.Enabled) return;
// Update control status
labelhorizrepeat.Enabled = cbfitwidth.Checked;
horizrepeat.Enabled = cbfitwidth.Checked;
resethoriz.Enabled = cbfitwidth.Checked;
labelvertrepeat.Enabled = cbfitheight.Checked;
vertrepeat.Enabled = cbfitheight.Checked;
resetvert.Enabled = cbfitheight.Checked;
}
#endregion
#region ================== Events
private void FitTexturesForm_FormClosing(object sender, FormClosingEventArgs e)
{
location = this.Location;
// Store settings
if(this.DialogResult == DialogResult.OK)
{
horizontalrepeat = (int)horizrepeat.Value;
verticalrepeat = (int)vertrepeat.Value;
fitacrosssurfaces = cbfitwidth.Checked;
fitwidth = cbfitwidth.Checked;
fitheight = cbfitheight.Checked;
}
}
private void resethoriz_Click(object sender, EventArgs e)
{
prevhorizrepeat = 1;
horizrepeat.Value = 1;
}
private void resetvert_Click(object sender, EventArgs e)
{
prevvertrepeat = 1;
vertrepeat.Value = 1;
}
private void horizrepeat_ValueChanged(object sender, EventArgs e)
{
if(blockupdate) return;
if(horizrepeat.Value == 0)
{
horizrepeat.Value = prevhorizrepeat > 0 ? -1 : 1;
return;
}
prevhorizrepeat = (int)horizrepeat.Value;
UpdateChanges();
}
private void vertrepeat_ValueChanged(object sender, EventArgs e)
{
if(blockupdate) return;
if(vertrepeat.Value == 0)
{
vertrepeat.Value = prevvertrepeat > 0 ? -1 : 1;
return;
}
prevvertrepeat = (int)vertrepeat.Value;
UpdateChanges();
}
private void accept_Click(object sender, EventArgs e)
{
this.DialogResult = DialogResult.OK;
this.Close();
}
private void cancel_Click(object sender, EventArgs e)
{
this.DialogResult = DialogResult.Cancel;
this.Close();
}
private void cb_CheckedChanged(object sender, EventArgs e)
{
if(blockupdate) return;
UpdateRepeatGroup();
UpdateChanges();
}
#endregion
#region ================== Debug
#if DEBUG
private void DrawDebugUV()
{
const int margin = 20;
//sort by texture...
Dictionary<long, List<SortedVisualSide>> sortedstrips = new Dictionary<long, List<SortedVisualSide>>();
foreach(SortedVisualSide side in strips)
{
if(!sortedstrips.ContainsKey(side.Side.Texture.LongName))
sortedstrips.Add(side.Side.Texture.LongName, new List<SortedVisualSide>());
sortedstrips[side.Side.Texture.LongName].Add(side);
}
foreach(KeyValuePair<long, List<SortedVisualSide>> pair in sortedstrips)
{
//find bounds
int minx = int.MaxValue;
int maxx = int.MinValue;
int miny = int.MaxValue;
int maxy = int.MinValue;
foreach(SortedVisualSide side in pair.Value)
{
if(side.Bounds.X < minx) minx = side.Bounds.X;
if(side.Bounds.X + side.Bounds.Width > maxx) maxx = side.Bounds.X + side.Bounds.Width;
if(side.Bounds.Y < miny) miny = side.Bounds.Y;
if(side.Bounds.Y + side.Bounds.Height > maxy) maxy = side.Bounds.Y + side.Bounds.Height;
}
Bitmap bmp = new Bitmap(maxx - minx + margin * 2, maxy - miny + margin * 2);
using(Graphics g = Graphics.FromImage(bmp))
{
int i = 0;
foreach(SortedVisualSide side in pair.Value)
{
Color c = General.Colors.BrightColors[General.Random(0, General.Colors.BrightColors.Length - 1)].ToColor();
int x = side.Bounds.X - minx + margin;
int y = side.Bounds.Y - miny + margin;
using (Pen p = new Pen(c))
{
g.DrawRectangle(p, x, y, side.Bounds.Width, side.Bounds.Height);
}
using (Brush b = new SolidBrush(c))
{
g.DrawString(i++ + ": line " + side.Side.Sidedef.Line.Index + "; x:" + side.Bounds.X + " y:" + side.Bounds.Y, this.Font, b, x + 2, y + 2);
}
}
}
bmp.Save("testuv_" + pair.Value[0].Side.Texture.ShortName + ".png", ImageFormat.Png);
}
General.Interface.DisplayStatus(StatusType.Info, "Saved test image!");
}
#endif
#endregion
}
}