mirror of
https://git.do.srb2.org/STJr/UltimateZoneBuilder.git
synced 2024-11-26 22:01:45 +00:00
- change a lot in the resources system
- fixed memory leak in PixelColorBlock - several small changes and bugfixes
This commit is contained in:
parent
2784090aca
commit
1dad4b68c6
51 changed files with 712 additions and 407 deletions
BIN
Resources/Failed.png
Normal file
BIN
Resources/Failed.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.5 KiB |
BIN
Resources/Hourglass3D.png
Normal file
BIN
Resources/Hourglass3D.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 406 B |
|
@ -70,7 +70,7 @@ namespace CodeImp.DoomBuilder.Actions
|
||||||
// Set cooperative level
|
// Set cooperative level
|
||||||
mouse.SetCooperativeLevel(source,
|
mouse.SetCooperativeLevel(source,
|
||||||
CooperativeLevel.Nonexclusive | CooperativeLevel.Foreground);
|
CooperativeLevel.Nonexclusive | CooperativeLevel.Foreground);
|
||||||
|
|
||||||
// Aquire device
|
// Aquire device
|
||||||
try { mouse.Acquire(); }
|
try { mouse.Acquire(); }
|
||||||
catch(Exception) { }
|
catch(Exception) { }
|
||||||
|
@ -113,20 +113,30 @@ namespace CodeImp.DoomBuilder.Actions
|
||||||
float changex, changey;
|
float changex, changey;
|
||||||
|
|
||||||
// Poll the device
|
// Poll the device
|
||||||
Result result = mouse.Poll();
|
try
|
||||||
if(result.IsSuccess)
|
|
||||||
{
|
{
|
||||||
// Get the changes since previous poll
|
Result result = mouse.Poll();
|
||||||
ms = mouse.GetCurrentState();
|
if(result.IsSuccess)
|
||||||
|
{
|
||||||
// Calculate changes depending on sensitivity
|
// Get the changes since previous poll
|
||||||
changex = (float)ms.X * General.Settings.VisualMouseSensX;
|
ms = mouse.GetCurrentState();
|
||||||
changey = (float)ms.Y * General.Settings.VisualMouseSensY;
|
|
||||||
|
// Calculate changes depending on sensitivity
|
||||||
// Return changes
|
changex = (float)ms.X * General.Settings.VisualMouseSensX;
|
||||||
return new Vector2D(changex, changey);
|
changey = (float)ms.Y * General.Settings.VisualMouseSensY;
|
||||||
|
|
||||||
|
// Return changes
|
||||||
|
return new Vector2D(changex, changey);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Reaquire device
|
||||||
|
try { mouse.Acquire(); }
|
||||||
|
catch(Exception) { }
|
||||||
|
return new Vector2D();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
catch(DirectInputException)
|
||||||
{
|
{
|
||||||
// Reaquire device
|
// Reaquire device
|
||||||
try { mouse.Acquire(); }
|
try { mouse.Acquire(); }
|
||||||
|
|
|
@ -600,6 +600,8 @@
|
||||||
<None Include="Resources\Copy.png" />
|
<None Include="Resources\Copy.png" />
|
||||||
<None Include="Resources\Cut.png" />
|
<None Include="Resources\Cut.png" />
|
||||||
<Content Include="Resources\DB2.ico" />
|
<Content Include="Resources\DB2.ico" />
|
||||||
|
<EmbeddedResource Include="Resources\Hourglass3D.png" />
|
||||||
|
<None Include="Resources\Failed.png" />
|
||||||
<None Include="Resources\Monster2.png" />
|
<None Include="Resources\Monster2.png" />
|
||||||
<None Include="Resources\Grid2_arrowup.png" />
|
<None Include="Resources\Grid2_arrowup.png" />
|
||||||
<None Include="Resources\Zoom_arrowup.png" />
|
<None Include="Resources\Zoom_arrowup.png" />
|
||||||
|
|
|
@ -30,6 +30,7 @@ using CodeImp.DoomBuilder.Map;
|
||||||
using CodeImp.DoomBuilder.Rendering;
|
using CodeImp.DoomBuilder.Rendering;
|
||||||
using CodeImp.DoomBuilder.Geometry;
|
using CodeImp.DoomBuilder.Geometry;
|
||||||
using CodeImp.DoomBuilder.Editing;
|
using CodeImp.DoomBuilder.Editing;
|
||||||
|
using CodeImp.DoomBuilder.Actions;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
@ -215,6 +216,23 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
|
||||||
|
|
||||||
#region ================== Methods
|
#region ================== Methods
|
||||||
|
|
||||||
|
[EndAction("reloadresources", BaseAction = true)]
|
||||||
|
public void ReloadResources()
|
||||||
|
{
|
||||||
|
foreach(KeyValuePair<Sector, BaseVisualSector> s in allsectors) s.Value.Dispose();
|
||||||
|
allsectors.Clear();
|
||||||
|
visiblesectors.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mode engages
|
||||||
|
public override void OnEngage()
|
||||||
|
{
|
||||||
|
// Update the used textures
|
||||||
|
General.Map.Data.UpdateUsedTextures();
|
||||||
|
|
||||||
|
base.OnEngage();
|
||||||
|
}
|
||||||
|
|
||||||
// This draws a frame
|
// This draws a frame
|
||||||
public override void OnRedrawDisplay()
|
public override void OnRedrawDisplay()
|
||||||
{
|
{
|
||||||
|
|
|
@ -62,7 +62,6 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
|
||||||
|
|
||||||
// Load floor texture
|
// Load floor texture
|
||||||
base.Texture = General.Map.Data.GetFlatImage(s.LongCeilTexture);
|
base.Texture = General.Map.Data.GetFlatImage(s.LongCeilTexture);
|
||||||
base.Texture.LoadImage();
|
|
||||||
|
|
||||||
// Make vertices
|
// Make vertices
|
||||||
verts = new WorldVertex[s.Vertices.Length];
|
verts = new WorldVertex[s.Vertices.Length];
|
||||||
|
@ -74,9 +73,17 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
|
||||||
verts[i].c = -1;
|
verts[i].c = -1;
|
||||||
|
|
||||||
// Grid aligned texture coordinates
|
// Grid aligned texture coordinates
|
||||||
verts[i].u = s.Vertices[i].x / base.Texture.ScaledWidth;
|
if(base.Texture.IsImageLoaded)
|
||||||
verts[i].v = s.Vertices[i].y / base.Texture.ScaledHeight;
|
{
|
||||||
|
verts[i].u = s.Vertices[i].x / base.Texture.ScaledWidth;
|
||||||
|
verts[i].v = s.Vertices[i].y / base.Texture.ScaledHeight;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
verts[i].u = s.Vertices[i].x / 64;
|
||||||
|
verts[i].v = s.Vertices[i].y / 64;
|
||||||
|
}
|
||||||
|
|
||||||
// Vertex coordinates
|
// Vertex coordinates
|
||||||
verts[i].x = s.Vertices[i].x;
|
verts[i].x = s.Vertices[i].x;
|
||||||
verts[i].y = s.Vertices[i].y;
|
verts[i].y = s.Vertices[i].y;
|
||||||
|
|
|
@ -61,7 +61,6 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
|
||||||
|
|
||||||
// Load floor texture
|
// Load floor texture
|
||||||
base.Texture = General.Map.Data.GetFlatImage(s.LongFloorTexture);
|
base.Texture = General.Map.Data.GetFlatImage(s.LongFloorTexture);
|
||||||
base.Texture.LoadImage();
|
|
||||||
|
|
||||||
// Make vertices
|
// Make vertices
|
||||||
verts = new WorldVertex[s.Vertices.Length];
|
verts = new WorldVertex[s.Vertices.Length];
|
||||||
|
@ -73,8 +72,16 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
|
||||||
verts[i].c = -1;
|
verts[i].c = -1;
|
||||||
|
|
||||||
// Grid aligned texture coordinates
|
// Grid aligned texture coordinates
|
||||||
verts[i].u = s.Vertices[i].x / base.Texture.ScaledWidth;
|
if(base.Texture.IsImageLoaded)
|
||||||
verts[i].v = s.Vertices[i].y / base.Texture.ScaledHeight;
|
{
|
||||||
|
verts[i].u = s.Vertices[i].x / base.Texture.ScaledWidth;
|
||||||
|
verts[i].v = s.Vertices[i].y / base.Texture.ScaledHeight;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
verts[i].u = s.Vertices[i].x / 64;
|
||||||
|
verts[i].v = s.Vertices[i].y / 64;
|
||||||
|
}
|
||||||
|
|
||||||
// Vertex coordinates
|
// Vertex coordinates
|
||||||
verts[i].x = s.Vertices[i].x;
|
verts[i].x = s.Vertices[i].x;
|
||||||
|
|
|
@ -74,7 +74,6 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
|
||||||
{
|
{
|
||||||
// Load texture
|
// Load texture
|
||||||
base.Texture = General.Map.Data.GetTextureImage(s.LongLowTexture);
|
base.Texture = General.Map.Data.GetTextureImage(s.LongLowTexture);
|
||||||
base.Texture.LoadImage();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -83,7 +83,6 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
|
||||||
{
|
{
|
||||||
// Load texture
|
// Load texture
|
||||||
base.Texture = General.Map.Data.GetTextureImage(s.LongMiddleTexture);
|
base.Texture = General.Map.Data.GetTextureImage(s.LongMiddleTexture);
|
||||||
base.Texture.LoadImage();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -74,7 +74,6 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
|
||||||
{
|
{
|
||||||
// Load texture
|
// Load texture
|
||||||
base.Texture = General.Map.Data.GetTextureImage(s.LongHighTexture);
|
base.Texture = General.Map.Data.GetTextureImage(s.LongHighTexture);
|
||||||
base.Texture.LoadImage();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -59,7 +59,7 @@ namespace CodeImp.DoomBuilder.Controls
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Set the image
|
// Set the image
|
||||||
return General.Map.Data.GetFlatBitmap(imagename);
|
return General.Map.Data.GetFlatImage(imagename).GetPreview();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
1
Source/Controls/ImageBrowserControl.Designer.cs
generated
1
Source/Controls/ImageBrowserControl.Designer.cs
generated
|
@ -15,6 +15,7 @@ namespace CodeImp.DoomBuilder.Controls
|
||||||
{
|
{
|
||||||
if(disposing && (components != null))
|
if(disposing && (components != null))
|
||||||
{
|
{
|
||||||
|
CleanUp();
|
||||||
components.Dispose();
|
components.Dispose();
|
||||||
}
|
}
|
||||||
base.Dispose(disposing);
|
base.Dispose(disposing);
|
||||||
|
|
|
@ -40,9 +40,6 @@ namespace CodeImp.DoomBuilder.Controls
|
||||||
{
|
{
|
||||||
#region ================== Constants
|
#region ================== Constants
|
||||||
|
|
||||||
// Maximum loaded items
|
|
||||||
private const int MAX_LOADED_ITEMS = 200;
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region ================== Delegates / Events
|
#region ================== Delegates / Events
|
||||||
|
@ -61,9 +58,6 @@ namespace CodeImp.DoomBuilder.Controls
|
||||||
// All items
|
// All items
|
||||||
private List<ImageBrowserItem> items;
|
private List<ImageBrowserItem> items;
|
||||||
|
|
||||||
// Loaded items
|
|
||||||
private LinkedList<ImageBrowserItem> loadeditems;
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region ================== Properties
|
#region ================== Properties
|
||||||
|
@ -81,7 +75,6 @@ namespace CodeImp.DoomBuilder.Controls
|
||||||
// Initialize
|
// Initialize
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
items = new List<ImageBrowserItem>();
|
items = new List<ImageBrowserItem>();
|
||||||
loadeditems = new LinkedList<ImageBrowserItem>();
|
|
||||||
|
|
||||||
// Move textbox with label
|
// Move textbox with label
|
||||||
objectname.Left = label.Right + label.Margin.Right + objectname.Margin.Left;
|
objectname.Left = label.Right + label.Margin.Right + objectname.Margin.Left;
|
||||||
|
@ -98,7 +91,7 @@ namespace CodeImp.DoomBuilder.Controls
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This cleans everything up (we can't override Dispose?)
|
// This cleans everything up
|
||||||
public virtual void CleanUp()
|
public virtual void CleanUp()
|
||||||
{
|
{
|
||||||
// Stop refresh timer
|
// Stop refresh timer
|
||||||
|
@ -109,24 +102,16 @@ namespace CodeImp.DoomBuilder.Controls
|
||||||
list.SuspendLayout();
|
list.SuspendLayout();
|
||||||
list.BeginUpdate();
|
list.BeginUpdate();
|
||||||
|
|
||||||
// Go for all items
|
// Dispose items
|
||||||
foreach(ImageBrowserItem i in list.Items)
|
foreach(ImageBrowserItem i in list.Items) i.Dispose();
|
||||||
{
|
|
||||||
// Queue image for unloading if only temporary
|
|
||||||
if(i.icon.IsLoaded && i.icon.Temporary) General.Map.Data.BackgroundLoadImage(i.icon, false);
|
|
||||||
|
|
||||||
// Dispose item
|
|
||||||
i.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Trash list items
|
// Trash list items
|
||||||
list.Clear();
|
list.Clear();
|
||||||
loadeditems.Clear();
|
|
||||||
|
|
||||||
// Done updating list
|
// Done updating list
|
||||||
updating = false;
|
|
||||||
list.EndUpdate();
|
list.EndUpdate();
|
||||||
list.ResumeLayout();
|
list.ResumeLayout();
|
||||||
|
updating = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -136,67 +121,34 @@ namespace CodeImp.DoomBuilder.Controls
|
||||||
// Draw item
|
// Draw item
|
||||||
private void list_DrawItem(object sender, DrawListViewItemEventArgs e)
|
private void list_DrawItem(object sender, DrawListViewItemEventArgs e)
|
||||||
{
|
{
|
||||||
if(!updating) e.Graphics.DrawImageUnscaled((e.Item as ImageBrowserItem).GetImage(e.Bounds), e.Bounds);
|
if(!updating) (e.Item as ImageBrowserItem).Draw(e.Graphics, e.Bounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Refresher
|
// Refresher
|
||||||
private void refreshtimer_Tick(object sender, EventArgs e)
|
private void refreshtimer_Tick(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
|
bool allpreviewsloaded = true;
|
||||||
|
|
||||||
// Go for all items
|
// Go for all items
|
||||||
foreach(ImageBrowserItem i in list.Items)
|
foreach(ImageBrowserItem i in list.Items)
|
||||||
{
|
{
|
||||||
// Bounds within view?
|
// Check if there are still previews that are not loaded
|
||||||
if(i.Bounds.IntersectsWith(list.ClientRectangle))
|
allpreviewsloaded &= i.IsPreviewLoaded;
|
||||||
|
|
||||||
|
// Items needs to be redrawn?
|
||||||
|
if(i.CheckRedrawNeeded())
|
||||||
{
|
{
|
||||||
// Remove from loaded list if in there
|
// Bounds within view?
|
||||||
if(i.LoadedTicket != null) loadeditems.Remove(i.LoadedTicket);
|
if(i.Bounds.IntersectsWith(list.ClientRectangle))
|
||||||
|
|
||||||
// Image not loaded?
|
|
||||||
if(!i.icon.IsLoaded && !i.IsImageLoaded)
|
|
||||||
{
|
{
|
||||||
// Queue for background loading
|
|
||||||
General.Map.Data.BackgroundLoadImage(i.icon, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Items needs to be redrawn?
|
|
||||||
if(i.CheckRedrawNeeded(i.Bounds))
|
|
||||||
{
|
|
||||||
// Redraw item
|
|
||||||
i.GetImage(i.Bounds);
|
|
||||||
|
|
||||||
// Refresh item in list
|
// Refresh item in list
|
||||||
list.RedrawItems(i.Index, i.Index, false);
|
list.RedrawItems(i.Index, i.Index, false);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
// Queue for unloading if only temporary
|
|
||||||
if(i.icon.IsLoaded && i.icon.Temporary) General.Map.Data.BackgroundLoadImage(i.icon, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add to loaded list
|
|
||||||
i.LoadedTicket = loadeditems.AddLast(i);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Queue for unloading if only temporary
|
|
||||||
if(i.icon.IsLoaded && i.icon.Temporary)
|
|
||||||
General.Map.Data.BackgroundLoadImage(i.icon, false);
|
|
||||||
else
|
|
||||||
General.Map.Data.BackgroundCancelImage(i.icon);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// More items laoded than allowed?
|
// If all previews were loaded, stop this timer
|
||||||
if(loadeditems.Count > MAX_LOADED_ITEMS)
|
if(allpreviewsloaded) refreshtimer.Stop();
|
||||||
{
|
|
||||||
// Unload items
|
|
||||||
for(int i = 0; i < (loadeditems.Count - MAX_LOADED_ITEMS); i++)
|
|
||||||
{
|
|
||||||
loadeditems.First.Value.ReleaseImage();
|
|
||||||
loadeditems.First.Value.LoadedTicket = null;
|
|
||||||
loadeditems.RemoveFirst();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
|
@ -46,11 +46,8 @@ namespace CodeImp.DoomBuilder.Controls
|
||||||
|
|
||||||
// Group
|
// Group
|
||||||
private ListViewGroup listgroup;
|
private ListViewGroup listgroup;
|
||||||
private LinkedListNode<ImageBrowserItem> loadedticked;
|
|
||||||
|
|
||||||
// Image cache
|
// Image cache
|
||||||
private Image normalimage;
|
|
||||||
private Image selectedimage;
|
|
||||||
private bool imageloaded;
|
private bool imageloaded;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -58,9 +55,7 @@ namespace CodeImp.DoomBuilder.Controls
|
||||||
#region ================== Properties
|
#region ================== Properties
|
||||||
|
|
||||||
public ListViewGroup ListGroup { get { return listgroup; } set { listgroup = value; } }
|
public ListViewGroup ListGroup { get { return listgroup; } set { listgroup = value; } }
|
||||||
public LinkedListNode<ImageBrowserItem> LoadedTicket { get { return loadedticked; } set { loadedticked = value; } }
|
public bool IsPreviewLoaded { get { return imageloaded; } }
|
||||||
public bool IsImageLoaded { get { return imageloaded; } }
|
|
||||||
public bool HasImage { get { return (normalimage != null); } }
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
@ -78,8 +73,6 @@ namespace CodeImp.DoomBuilder.Controls
|
||||||
// Disposer
|
// Disposer
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
ReleaseImage();
|
|
||||||
loadedticked = null;
|
|
||||||
icon = null;
|
icon = null;
|
||||||
listgroup = null;
|
listgroup = null;
|
||||||
}
|
}
|
||||||
|
@ -89,36 +82,37 @@ namespace CodeImp.DoomBuilder.Controls
|
||||||
#region ================== Methods
|
#region ================== Methods
|
||||||
|
|
||||||
// This checks if a redraw is needed
|
// This checks if a redraw is needed
|
||||||
public bool CheckRedrawNeeded(Rectangle bounds)
|
public bool CheckRedrawNeeded()
|
||||||
{
|
{
|
||||||
return (normalimage == null) || (selectedimage == null) || (icon.IsLoaded && !imageloaded);
|
return (icon.IsPreviewLoaded != imageloaded);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This draws the images
|
// This draws the images
|
||||||
private Image DrawImage(Rectangle bounds, bool selected)
|
public void Draw(Graphics g, Rectangle bounds)
|
||||||
{
|
{
|
||||||
Brush forecolor;
|
Brush forecolor;
|
||||||
Brush backcolor;
|
Brush backcolor;
|
||||||
|
|
||||||
|
// Remember if the preview is loaded
|
||||||
|
imageloaded = icon.IsPreviewLoaded;
|
||||||
|
|
||||||
// Make a new image and graphics to draw with
|
// Drawing settings
|
||||||
Image image = new Bitmap(bounds.Width, bounds.Height, PixelFormat.Format32bppArgb);
|
|
||||||
Graphics g = Graphics.FromImage(image);
|
|
||||||
g.CompositingQuality = CompositingQuality.HighSpeed;
|
g.CompositingQuality = CompositingQuality.HighSpeed;
|
||||||
g.InterpolationMode = InterpolationMode.Bilinear;
|
g.InterpolationMode = InterpolationMode.NearestNeighbor;
|
||||||
g.SmoothingMode = SmoothingMode.HighQuality;
|
g.SmoothingMode = SmoothingMode.HighSpeed;
|
||||||
g.PixelOffsetMode = PixelOffsetMode.None;
|
g.PixelOffsetMode = PixelOffsetMode.None;
|
||||||
|
|
||||||
// Determine coordinates
|
// Determine coordinates
|
||||||
SizeF textsize = g.MeasureString(this.Text, this.ListView.Font, bounds.Width);
|
SizeF textsize = g.MeasureString(this.Text, this.ListView.Font, bounds.Width);
|
||||||
Size bordersize = new Size((bounds.Width - 64) >> 1, (bounds.Height - 64 - (int)textsize.Height) >> 1);
|
Rectangle imagerect = new Rectangle(bounds.Left + ((bounds.Width - 64) >> 1),
|
||||||
Rectangle imagerect = new Rectangle(bordersize.Width, bordersize.Height, 64, 64);
|
bounds.Top + ((bounds.Height - 64 - (int)textsize.Height) >> 1), 64, 64);
|
||||||
PointF textpos = new PointF(((float)bounds.Width - textsize.Width) * 0.5f, bounds.Height - textsize.Height - 2);
|
PointF textpos = new PointF(bounds.Left + ((float)bounds.Width - textsize.Width) * 0.5f, bounds.Bottom - textsize.Height - 2);
|
||||||
|
|
||||||
// Determine colors
|
// Determine colors
|
||||||
if(selected)
|
if(this.Selected)
|
||||||
{
|
{
|
||||||
// Highlighted
|
// Highlighted
|
||||||
backcolor = new LinearGradientBrush(new Point(0, 0), new Point(0, bounds.Height),
|
backcolor = new LinearGradientBrush(new Point(0, bounds.Top - 1), new Point(0, bounds.Bottom + 1),
|
||||||
AdjustedColor(SystemColors.Highlight, 0.2f),
|
AdjustedColor(SystemColors.Highlight, 0.2f),
|
||||||
AdjustedColor(SystemColors.Highlight, -0.1f));
|
AdjustedColor(SystemColors.Highlight, -0.1f));
|
||||||
forecolor = SystemBrushes.HighlightText;
|
forecolor = SystemBrushes.HighlightText;
|
||||||
|
@ -131,43 +125,9 @@ namespace CodeImp.DoomBuilder.Controls
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw!
|
// Draw!
|
||||||
g.FillRectangle(backcolor, 0, 0, bounds.Width, bounds.Height);
|
g.FillRectangle(backcolor, bounds);
|
||||||
g.DrawImage(icon.Bitmap, General.MakeZoomedRect(icon.Bitmap.Size, imagerect));
|
icon.DrawPreview(g, imagerect.Location);
|
||||||
g.DrawString(this.Text, this.ListView.Font, forecolor, textpos);
|
g.DrawString(this.Text, this.ListView.Font, forecolor, textpos);
|
||||||
|
|
||||||
// Done
|
|
||||||
g.Dispose();
|
|
||||||
return image;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This requests the cached image and redraws it if needed
|
|
||||||
public Image GetImage(Rectangle bounds)
|
|
||||||
{
|
|
||||||
// Do we need to redraw?
|
|
||||||
if(CheckRedrawNeeded(bounds))
|
|
||||||
{
|
|
||||||
// Keep image loaded state
|
|
||||||
imageloaded = icon.IsLoaded;
|
|
||||||
|
|
||||||
// Redraw both images
|
|
||||||
if(normalimage != null) normalimage.Dispose();
|
|
||||||
if(selectedimage != null) selectedimage.Dispose();
|
|
||||||
normalimage = DrawImage(bounds, false);
|
|
||||||
selectedimage = DrawImage(bounds, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return image
|
|
||||||
if(this.Selected) return selectedimage; else return normalimage;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This releases image resources
|
|
||||||
public void ReleaseImage()
|
|
||||||
{
|
|
||||||
if(normalimage != null) normalimage.Dispose();
|
|
||||||
if(selectedimage != null) selectedimage.Dispose();
|
|
||||||
normalimage = null;
|
|
||||||
selectedimage = null;
|
|
||||||
imageloaded = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This brightens or darkens a color
|
// This brightens or darkens a color
|
||||||
|
|
1
Source/Controls/ImageSelectorControl.Designer.cs
generated
1
Source/Controls/ImageSelectorControl.Designer.cs
generated
|
@ -15,6 +15,7 @@ namespace CodeImp.DoomBuilder.Controls
|
||||||
{
|
{
|
||||||
if(disposing && (components != null))
|
if(disposing && (components != null))
|
||||||
{
|
{
|
||||||
|
bmp.Dispose();
|
||||||
components.Dispose();
|
components.Dispose();
|
||||||
}
|
}
|
||||||
base.Dispose(disposing);
|
base.Dispose(disposing);
|
||||||
|
|
|
@ -38,16 +38,32 @@ namespace CodeImp.DoomBuilder.Controls
|
||||||
{
|
{
|
||||||
public abstract partial class ImageSelectorControl : UserControl
|
public abstract partial class ImageSelectorControl : UserControl
|
||||||
{
|
{
|
||||||
// Properties
|
#region ================== Variables
|
||||||
public string TextureName { get { return name.Text; } set { name.Text = value; } }
|
|
||||||
|
private Bitmap bmp;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region ================== Properties
|
||||||
|
|
||||||
|
public string TextureName { get { return name.Text; } set { name.Text = value; } }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region ================== Constructor / Destructor
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
public ImageSelectorControl()
|
public ImageSelectorControl()
|
||||||
{
|
{
|
||||||
// Initialize
|
// Initialize
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
bmp = new Bitmap(PreviewManager.IMAGE_WIDTH, PreviewManager.IMAGE_HEIGHT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region ================== Events
|
||||||
|
|
||||||
// When resized
|
// When resized
|
||||||
private void ImageSelectorControl_Resize(object sender, EventArgs e)
|
private void ImageSelectorControl_Resize(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
|
@ -74,9 +90,27 @@ namespace CodeImp.DoomBuilder.Controls
|
||||||
// Name text changed
|
// Name text changed
|
||||||
private void name_TextChanged(object sender, EventArgs e)
|
private void name_TextChanged(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
|
// Show it centered
|
||||||
General.DisplayZoomedImage(preview, FindImage(name.Text));
|
General.DisplayZoomedImage(preview, FindImage(name.Text));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region ================== Methods
|
||||||
|
|
||||||
|
// This redraws the image preview
|
||||||
|
private void ShowPreview(ImageData image)
|
||||||
|
{
|
||||||
|
// Draw preview image
|
||||||
|
Graphics g = Graphics.FromImage(bmp);
|
||||||
|
g.Clear(Color.Transparent);
|
||||||
|
image.DrawPreview(g, new Point(0, 0));
|
||||||
|
g.Dispose();
|
||||||
|
|
||||||
|
// Show it centered
|
||||||
|
General.DisplayZoomedImage(preview, bmp);
|
||||||
|
}
|
||||||
|
|
||||||
// This must determine and return the image to show
|
// This must determine and return the image to show
|
||||||
protected abstract Image FindImage(string imagename);
|
protected abstract Image FindImage(string imagename);
|
||||||
|
|
||||||
|
@ -98,5 +132,7 @@ namespace CodeImp.DoomBuilder.Controls
|
||||||
return original;
|
return original;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -259,7 +259,7 @@ namespace CodeImp.DoomBuilder.Controls
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Set the image
|
// Set the image
|
||||||
panel.BackgroundImage = General.Map.Data.GetTextureBitmap(name);
|
panel.BackgroundImage = General.Map.Data.GetTextureImage(name).GetPreview();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Image not null?
|
// Image not null?
|
||||||
|
|
|
@ -65,8 +65,8 @@ namespace CodeImp.DoomBuilder.Controls
|
||||||
brightness.Text = s.Brightness.ToString();
|
brightness.Text = s.Brightness.ToString();
|
||||||
floorname.Text = s.FloorTexture;
|
floorname.Text = s.FloorTexture;
|
||||||
ceilingname.Text = s.CeilTexture;
|
ceilingname.Text = s.CeilTexture;
|
||||||
General.DisplayZoomedImage(floortex, General.Map.Data.GetFlatBitmap(s.FloorTexture));
|
General.DisplayZoomedImage(floortex, General.Map.Data.GetFlatImage(s.FloorTexture).GetPreview());
|
||||||
General.DisplayZoomedImage(ceilingtex, General.Map.Data.GetFlatBitmap(s.CeilTexture));
|
General.DisplayZoomedImage(ceilingtex, General.Map.Data.GetFlatImage(s.CeilTexture).GetPreview());
|
||||||
|
|
||||||
// Show the whole thing
|
// Show the whole thing
|
||||||
this.Show();
|
this.Show();
|
||||||
|
|
|
@ -68,7 +68,7 @@ namespace CodeImp.DoomBuilder.Controls
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Set the image
|
// Set the image
|
||||||
return General.Map.Data.GetTextureBitmap(imagename);
|
return General.Map.Data.GetTextureImage(imagename).GetPreview();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -136,7 +136,7 @@ namespace CodeImp.DoomBuilder.Controls
|
||||||
tag.Text = t.Tag.ToString();
|
tag.Text = t.Tag.ToString();
|
||||||
angle.Text = t.AngleDeg.ToString() + "\u00B0";
|
angle.Text = t.AngleDeg.ToString() + "\u00B0";
|
||||||
spritename.Text = ti.Sprite;
|
spritename.Text = ti.Sprite;
|
||||||
General.DisplayZoomedImage(spritetex, General.Map.Data.GetSpriteBitmap(ti.Sprite));
|
General.DisplayZoomedImage(spritetex, General.Map.Data.GetSpriteImage(ti.Sprite).GetPreview());
|
||||||
|
|
||||||
// Arguments
|
// Arguments
|
||||||
if(act != null)
|
if(act != null)
|
||||||
|
|
|
@ -29,6 +29,7 @@ using System.Windows.Forms;
|
||||||
using SlimDX.Direct3D9;
|
using SlimDX.Direct3D9;
|
||||||
using CodeImp.DoomBuilder.Config;
|
using CodeImp.DoomBuilder.Config;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using CodeImp.DoomBuilder.Map;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
@ -62,12 +63,14 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
// Background loading
|
// Background loading
|
||||||
private Queue<ImageData> imageque;
|
private Queue<ImageData> imageque;
|
||||||
private Thread backgroundloader;
|
private Thread backgroundloader;
|
||||||
|
private volatile bool updatedusedtextures;
|
||||||
|
|
||||||
// Image previews
|
// Image previews
|
||||||
private PreviewManager previews;
|
private PreviewManager previews;
|
||||||
|
|
||||||
// Special images
|
// Special images
|
||||||
private ImageData missingtexture3d;
|
private ImageData missingtexture3d;
|
||||||
|
private ImageData hourglass3d;
|
||||||
|
|
||||||
// Disposing
|
// Disposing
|
||||||
private bool isdisposed = false;
|
private bool isdisposed = false;
|
||||||
|
@ -77,21 +80,22 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
#region ================== Properties
|
#region ================== Properties
|
||||||
|
|
||||||
public Playpal Palette { get { return palette; } }
|
public Playpal Palette { get { return palette; } }
|
||||||
internal PreviewManager Previews { get { return previews; } }
|
public PreviewManager Previews { get { return previews; } }
|
||||||
public ICollection<ImageData> Textures { get { return textures.Values; } }
|
public ICollection<ImageData> Textures { get { return textures.Values; } }
|
||||||
public ICollection<ImageData> Flats { get { return flats.Values; } }
|
public ICollection<ImageData> Flats { get { return flats.Values; } }
|
||||||
public List<string> TextureNames { get { return texturenames; } }
|
public List<string> TextureNames { get { return texturenames; } }
|
||||||
public List<string> FlatNames { get { return flatnames; } }
|
public List<string> FlatNames { get { return flatnames; } }
|
||||||
public bool IsDisposed { get { return isdisposed; } }
|
public bool IsDisposed { get { return isdisposed; } }
|
||||||
public ImageData MissingTexture3D { get { return missingtexture3d; } }
|
public ImageData MissingTexture3D { get { return missingtexture3d; } }
|
||||||
|
public ImageData Hourglass3D { get { return hourglass3d; } }
|
||||||
|
|
||||||
public bool IsLoading
|
public bool IsLoading
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if(loadlist != null)
|
if(imageque != null)
|
||||||
{
|
{
|
||||||
return (backgroundloader != null) && backgroundloader.IsAlive && (loadlist.Count > 0);
|
return (backgroundloader != null) && backgroundloader.IsAlive && ((imageque.Count > 0) || previews.IsLoading);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -113,6 +117,8 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
// Load special images
|
// Load special images
|
||||||
missingtexture3d = new ResourceImage("MissingTexture3D.png");
|
missingtexture3d = new ResourceImage("MissingTexture3D.png");
|
||||||
missingtexture3d.LoadImage();
|
missingtexture3d.LoadImage();
|
||||||
|
hourglass3d = new ResourceImage("Hourglass3D.png");
|
||||||
|
hourglass3d.LoadImage();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disposer
|
// Disposer
|
||||||
|
@ -163,7 +169,7 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
sprites = new Dictionary<long, ImageData>();
|
sprites = new Dictionary<long, ImageData>();
|
||||||
texturenames = new List<string>();
|
texturenames = new List<string>();
|
||||||
flatnames = new List<string>();
|
flatnames = new List<string>();
|
||||||
loadlist = new LinkedList<ImageData>();
|
imageque = new Queue<ImageData>();
|
||||||
previews = new PreviewManager();
|
previews = new PreviewManager();
|
||||||
|
|
||||||
// Go for all locations
|
// Go for all locations
|
||||||
|
@ -252,7 +258,7 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
sprites = null;
|
sprites = null;
|
||||||
texturenames = null;
|
texturenames = null;
|
||||||
flatnames = null;
|
flatnames = null;
|
||||||
loadlist = null;
|
imageque = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -310,7 +316,7 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
// Start a low priority thread to load images in background
|
// Start a low priority thread to load images in background
|
||||||
General.WriteLogLine("Starting background resource loading...");
|
General.WriteLogLine("Starting background resource loading...");
|
||||||
backgroundloader = new Thread(new ThreadStart(BackgroundLoad));
|
backgroundloader = new Thread(new ThreadStart(BackgroundLoad));
|
||||||
backgroundloader.Name = "BackgroundLoader";
|
backgroundloader.Name = "Background Loader";
|
||||||
backgroundloader.Priority = ThreadPriority.Lowest;
|
backgroundloader.Priority = ThreadPriority.Lowest;
|
||||||
backgroundloader.Start();
|
backgroundloader.Start();
|
||||||
}
|
}
|
||||||
|
@ -318,7 +324,7 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
// This stops background loading
|
// This stops background loading
|
||||||
private void StopBackgroundLoader()
|
private void StopBackgroundLoader()
|
||||||
{
|
{
|
||||||
LinkedListNode<ImageData> n;
|
ImageData img;
|
||||||
|
|
||||||
General.WriteLogLine("Stopping background resource loading...");
|
General.WriteLogLine("Stopping background resource loading...");
|
||||||
if(backgroundloader != null)
|
if(backgroundloader != null)
|
||||||
|
@ -328,14 +334,32 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
backgroundloader.Join();
|
backgroundloader.Join();
|
||||||
|
|
||||||
// Reset load states on all images in the list
|
// Reset load states on all images in the list
|
||||||
n = loadlist.First;
|
while(imageque.Count > 0)
|
||||||
while(n != null)
|
|
||||||
{
|
{
|
||||||
n.Value.LoadState = ImageData.LOADSTATE_NONE;
|
img = imageque.Dequeue();
|
||||||
n.Value.LoadingTicket = null;
|
|
||||||
n = n.Next;
|
switch(img.ImageState)
|
||||||
|
{
|
||||||
|
case ImageLoadState.Loading:
|
||||||
|
img.ImageState = ImageLoadState.None;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ImageLoadState.Unloading:
|
||||||
|
img.ImageState = ImageLoadState.Ready;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(img.PreviewState)
|
||||||
|
{
|
||||||
|
case ImageLoadState.Loading:
|
||||||
|
img.PreviewState = ImageLoadState.None;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ImageLoadState.Unloading:
|
||||||
|
img.PreviewState = ImageLoadState.Ready;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
loadlist.Clear();
|
|
||||||
|
|
||||||
// Done
|
// Done
|
||||||
backgroundloader = null;
|
backgroundloader = null;
|
||||||
|
@ -350,11 +374,18 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
// Do we have to update the used-in-map status?
|
||||||
|
if(updatedusedtextures)
|
||||||
|
{
|
||||||
|
BackgroundUpdateUsedTextures();
|
||||||
|
updatedusedtextures = false;
|
||||||
|
}
|
||||||
|
|
||||||
// Get next item
|
// Get next item
|
||||||
ImageData image = null;
|
ImageData image = null;
|
||||||
lock(imageque)
|
lock(imageque)
|
||||||
{
|
{
|
||||||
// Fethc next image to process
|
// Fetch next image to process
|
||||||
if(imageque.Count > 0) image = imageque.Dequeue();
|
if(imageque.Count > 0) image = imageque.Dequeue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -362,23 +393,16 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
if(image != null)
|
if(image != null)
|
||||||
{
|
{
|
||||||
// Load this image?
|
// Load this image?
|
||||||
if(image.ImageState == ImageLoadState.Loading)
|
if(image.IsReferenced && (image.ImageState != ImageLoadState.Ready))
|
||||||
{
|
{
|
||||||
// Still referenced?
|
image.LoadImage();
|
||||||
if(image.IsReferenced)
|
|
||||||
image.LoadImage();
|
|
||||||
else
|
|
||||||
image.ImageState = ImageLoadState.None;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unload this image?
|
// Unload this image?
|
||||||
if(image.ImageState == ImageLoadState.Unloading)
|
if(!image.IsReferenced && (image.ImageState != ImageLoadState.None))
|
||||||
{
|
{
|
||||||
// Still unreferenced?
|
// Still unreferenced?
|
||||||
if(!image.IsReferenced)
|
image.UnloadImage();
|
||||||
image.UnloadImage();
|
|
||||||
else
|
|
||||||
image.ImageState = ImageLoadState.Ready;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -405,9 +429,6 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
Thread.Sleep(50);
|
Thread.Sleep(50);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Done
|
|
||||||
image = null;
|
|
||||||
}
|
}
|
||||||
while(true);
|
while(true);
|
||||||
}
|
}
|
||||||
|
@ -439,6 +460,41 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
// Update icon
|
// Update icon
|
||||||
General.MainWindow.UpdateStatusIcon();
|
General.MainWindow.UpdateStatusIcon();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This updates the used-in-map status on all textures and flats
|
||||||
|
private void BackgroundUpdateUsedTextures()
|
||||||
|
{
|
||||||
|
Dictionary<long, long> useditems = new Dictionary<long, long>();
|
||||||
|
|
||||||
|
// Go through the map to find the used textures
|
||||||
|
foreach(Sidedef sd in General.Map.Map.Sidedefs)
|
||||||
|
{
|
||||||
|
// Add used textures to dictionary
|
||||||
|
if(sd.HighTexture.Length > 0) useditems[sd.LongHighTexture] = 0;
|
||||||
|
if(sd.LowTexture.Length > 0) useditems[sd.LongMiddleTexture] = 0;
|
||||||
|
if(sd.MiddleTexture.Length > 0) useditems[sd.LongLowTexture] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Go through the map to find the used flats
|
||||||
|
foreach(Sector s in General.Map.Map.Sectors)
|
||||||
|
{
|
||||||
|
// Add used flats to dictionary
|
||||||
|
useditems[s.LongFloorTexture] = 0;
|
||||||
|
useditems[s.LongCeilTexture] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set used on all textures
|
||||||
|
foreach(KeyValuePair<long, ImageData> i in textures)
|
||||||
|
i.Value.SetUsedInMap(useditems.ContainsKey(i.Key));
|
||||||
|
|
||||||
|
// Flats are not already included with the textures?
|
||||||
|
if(!General.Map.Config.MixTexturesFlats)
|
||||||
|
{
|
||||||
|
// Set used on all flats
|
||||||
|
foreach(KeyValuePair<long, ImageData> i in flats)
|
||||||
|
i.Value.SetUsedInMap(useditems.ContainsKey(i.Key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
@ -505,6 +561,9 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
flats.Remove(img.LongName);
|
flats.Remove(img.LongName);
|
||||||
flats.Add(img.LongName, img);
|
flats.Add(img.LongName, img);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add to preview manager
|
||||||
|
previews.AddImage(img);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -554,6 +613,10 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// BAD! These block while loading the image. That is not
|
||||||
|
// what our background loading system is for!
|
||||||
|
/*
|
||||||
// This returns a bitmap by string
|
// This returns a bitmap by string
|
||||||
public Bitmap GetTextureBitmap(string name)
|
public Bitmap GetTextureBitmap(string name)
|
||||||
{
|
{
|
||||||
|
@ -587,6 +650,7 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
img.CreateTexture();
|
img.CreateTexture();
|
||||||
return img.Texture;
|
return img.Texture;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
@ -621,6 +685,9 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
textures.Remove(img.LongName);
|
textures.Remove(img.LongName);
|
||||||
textures.Add(img.LongName, img);
|
textures.Add(img.LongName, img);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add to preview manager
|
||||||
|
previews.AddImage(img);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -670,6 +737,9 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BAD! These block while loading the image. That is not
|
||||||
|
// what our background loading system is for!
|
||||||
|
/*
|
||||||
// This returns a bitmap by string
|
// This returns a bitmap by string
|
||||||
public Bitmap GetFlatBitmap(string name)
|
public Bitmap GetFlatBitmap(string name)
|
||||||
{
|
{
|
||||||
|
@ -703,6 +773,7 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
img.CreateTexture();
|
img.CreateTexture();
|
||||||
return img.Texture;
|
return img.Texture;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
@ -736,6 +807,9 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
|
|
||||||
// Add to collection
|
// Add to collection
|
||||||
sprites.Add(ti.SpriteLongName, image);
|
sprites.Add(ti.SpriteLongName, image);
|
||||||
|
|
||||||
|
// Add to preview manager
|
||||||
|
previews.AddImage(image);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -787,6 +861,9 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BAD! These block while loading the image. That is not
|
||||||
|
// what our background loading system is for!
|
||||||
|
/*
|
||||||
// This returns a bitmap by string
|
// This returns a bitmap by string
|
||||||
public Bitmap GetSpriteBitmap(string name)
|
public Bitmap GetSpriteBitmap(string name)
|
||||||
{
|
{
|
||||||
|
@ -803,6 +880,7 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
img.CreateTexture();
|
img.CreateTexture();
|
||||||
return img.Texture;
|
return img.Texture;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
@ -834,6 +912,13 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This signals the background thread to update the
|
||||||
|
// used-in-map status on all textures and flats
|
||||||
|
public void UpdateUsedTextures()
|
||||||
|
{
|
||||||
|
updatedusedtextures = true;
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,7 +58,7 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
public override void LoadImage()
|
public override void LoadImage()
|
||||||
{
|
{
|
||||||
// Leave when already loaded
|
// Leave when already loaded
|
||||||
if(this.IsLoaded) return;
|
if(this.IsImageLoaded) return;
|
||||||
|
|
||||||
lock(this)
|
lock(this)
|
||||||
{
|
{
|
||||||
|
|
|
@ -57,7 +57,7 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
byte[] membytes;
|
byte[] membytes;
|
||||||
|
|
||||||
// Leave when already loaded
|
// Leave when already loaded
|
||||||
if(this.IsLoaded) return;
|
if(this.IsImageLoaded) return;
|
||||||
|
|
||||||
lock(this)
|
lock(this)
|
||||||
{
|
{
|
||||||
|
@ -85,6 +85,9 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
if(bitmap != null) bitmap.Dispose();
|
if(bitmap != null) bitmap.Dispose();
|
||||||
bitmap = reader.ReadAsBitmap(mem);
|
bitmap = reader.ReadAsBitmap(mem);
|
||||||
if(bitmap == null) return;
|
if(bitmap == null) return;
|
||||||
|
|
||||||
|
// Done
|
||||||
|
mem.Dispose();
|
||||||
|
|
||||||
// Get width and height from image
|
// Get width and height from image
|
||||||
width = bitmap.Size.Width;
|
width = bitmap.Size.Width;
|
||||||
|
|
|
@ -51,13 +51,14 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
protected bool usecolorcorrection;
|
protected bool usecolorcorrection;
|
||||||
|
|
||||||
// Loading
|
// Loading
|
||||||
private LinkedListNode<ImageData> processticket;
|
private volatile ImageLoadState previewstate;
|
||||||
private ImageLoadState previewstate;
|
private volatile ImageLoadState imagestate;
|
||||||
private ImageLoadState imagestate;
|
private volatile int previewindex;
|
||||||
|
protected volatile bool loadfailed;
|
||||||
|
|
||||||
// References
|
// References
|
||||||
private bool usedinmap;
|
private volatile bool usedinmap;
|
||||||
private int references;
|
private volatile int references;
|
||||||
|
|
||||||
// GDI bitmap
|
// GDI bitmap
|
||||||
protected Bitmap bitmap;
|
protected Bitmap bitmap;
|
||||||
|
@ -76,19 +77,21 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
public string Name { get { return name; } }
|
public string Name { get { return name; } }
|
||||||
public long LongName { get { return longname; } }
|
public long LongName { get { return longname; } }
|
||||||
public bool UseColorCorrection { get { return usecolorcorrection; } set { usecolorcorrection = value; } }
|
public bool UseColorCorrection { get { return usecolorcorrection; } set { usecolorcorrection = value; } }
|
||||||
public Bitmap Bitmap { get { lock(this) { if(bitmap != null) return new Bitmap(bitmap); else return CodeImp.DoomBuilder.Properties.Resources.Hourglass; } } }
|
//public Bitmap Bitmap { get { lock(this) { if(bitmap != null) return new Bitmap(bitmap); else return CodeImp.DoomBuilder.Properties.Resources.Hourglass; } } }
|
||||||
|
public Bitmap Bitmap { get { lock(this) { if(bitmap != null) return bitmap; else return CodeImp.DoomBuilder.Properties.Resources.Hourglass; } } }
|
||||||
public Texture Texture { get { lock(this) { return texture; } } }
|
public Texture Texture { get { lock(this) { return texture; } } }
|
||||||
public bool IsPreviewLoaded { get { lock(this) { return (previewstate == ImageLoadState.Ready); } } }
|
public bool IsPreviewLoaded { get { return (previewstate == ImageLoadState.Ready); } }
|
||||||
public bool IsImageLoaded { get { lock(this) { return (imagestate == ImageLoadState.Ready); } } }
|
public bool IsImageLoaded { get { return (imagestate == ImageLoadState.Ready); } }
|
||||||
|
public bool LoadFailed { get { return loadfailed; } }
|
||||||
public bool IsDisposed { get { return isdisposed; } }
|
public bool IsDisposed { get { return isdisposed; } }
|
||||||
internal ImageLoadState ImageState { get { return imagestate; } set { imagestate = value; } }
|
public ImageLoadState ImageState { get { return imagestate; } internal set { imagestate = value; } }
|
||||||
internal ImageLoadState PreviewState { get { return previewstate; } set { previewstate = value; } }
|
public ImageLoadState PreviewState { get { return previewstate; } internal set { previewstate = value; } }
|
||||||
internal LinkedListNode<ImageData> ProcessTicket { get { return processticket; } set { processticket = value; } }
|
public bool IsReferenced { get { return (references > 0) || usedinmap; } }
|
||||||
internal bool IsReferenced { get { return (references > 0) || usedinmap; } }
|
public bool UsedInMap { get { return usedinmap; } }
|
||||||
internal bool UsedInMap { get { return usedinmap; } set { usedinmap = value; } }
|
|
||||||
public int MipMapLevels { get { return mipmaplevels; } set { mipmaplevels = value; } }
|
public int MipMapLevels { get { return mipmaplevels; } set { mipmaplevels = value; } }
|
||||||
public int Width { get { return width; } }
|
public int Width { get { return width; } }
|
||||||
public int Height { get { return height; } }
|
public int Height { get { return height; } }
|
||||||
|
internal int PreviewIndex { get { return previewindex; } set { previewindex = value; } }
|
||||||
public float ScaledWidth { get { return scaledwidth; } }
|
public float ScaledWidth { get { return scaledwidth; } }
|
||||||
public float ScaledHeight { get { return scaledheight; } }
|
public float ScaledHeight { get { return scaledheight; } }
|
||||||
|
|
||||||
|
@ -134,10 +137,21 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
|
|
||||||
#region ================== Management
|
#region ================== Management
|
||||||
|
|
||||||
|
// This sets the status of the texture usage in the map
|
||||||
|
internal void SetUsedInMap(bool used)
|
||||||
|
{
|
||||||
|
if(used != usedinmap)
|
||||||
|
{
|
||||||
|
usedinmap = used;
|
||||||
|
General.Map.Data.ProcessImage(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// This adds a reference
|
// This adds a reference
|
||||||
public void AddReference()
|
public void AddReference()
|
||||||
{
|
{
|
||||||
references++;
|
references++;
|
||||||
|
if(references == 1) General.Map.Data.ProcessImage(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This removes a reference
|
// This removes a reference
|
||||||
|
@ -145,6 +159,7 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
{
|
{
|
||||||
references--;
|
references--;
|
||||||
if(references < 0) General.Fail("FAIL! (references < 0)", "Somewhere this image is dereferenced more than it was referenced.");
|
if(references < 0) General.Fail("FAIL! (references < 0)", "Somewhere this image is dereferenced more than it was referenced.");
|
||||||
|
if(references == 0) General.Map.Data.ProcessImage(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This sets the name
|
// This sets the name
|
||||||
|
@ -172,28 +187,42 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
|
|
||||||
lock(this)
|
lock(this)
|
||||||
{
|
{
|
||||||
// This applies brightness correction on the image
|
// Bitmap loaded successfully?
|
||||||
if((bitmap != null) && usecolorcorrection)
|
if(bitmap != null)
|
||||||
{
|
{
|
||||||
try
|
// This applies brightness correction on the image
|
||||||
|
if(usecolorcorrection)
|
||||||
{
|
{
|
||||||
// Try locking the bitmap
|
try
|
||||||
bmpdata = bitmap.LockBits(new Rectangle(0, 0, bitmap.Size.Width, bitmap.Size.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
|
{
|
||||||
}
|
// Try locking the bitmap
|
||||||
catch(Exception e)
|
bmpdata = bitmap.LockBits(new Rectangle(0, 0, bitmap.Size.Width, bitmap.Size.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
|
||||||
{
|
}
|
||||||
General.WriteLogLine("ERROR: Cannot lock image '" + name + "' for color correction. " + e.GetType().Name + ": " + e.Message);
|
catch(Exception e)
|
||||||
}
|
{
|
||||||
|
General.WriteLogLine("ERROR: Cannot lock image '" + name + "' for color correction. " + e.GetType().Name + ": " + e.Message);
|
||||||
// Bitmap locked?
|
}
|
||||||
if(bmpdata != null)
|
|
||||||
{
|
// Bitmap locked?
|
||||||
// Apply color correction
|
if(bmpdata != null)
|
||||||
PixelColor* pixels = (PixelColor*)(bmpdata.Scan0.ToPointer());
|
{
|
||||||
General.Colors.ApplColorCorrection(pixels, bmpdata.Width * bmpdata.Height);
|
// Apply color correction
|
||||||
bitmap.UnlockBits(bmpdata);
|
PixelColor* pixels = (PixelColor*)(bmpdata.Scan0.ToPointer());
|
||||||
|
General.Colors.ApplColorCorrection(pixels, bmpdata.Width * bmpdata.Height);
|
||||||
|
bitmap.UnlockBits(bmpdata);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Loading failed
|
||||||
|
// We still mark the image as ready so that it will
|
||||||
|
// not try loading again until Reload Resources is used
|
||||||
|
loadfailed = true;
|
||||||
|
bitmap = new Bitmap(Properties.Resources.Failed);
|
||||||
|
width = bitmap.Size.Width;
|
||||||
|
height = bitmap.Size.Height;
|
||||||
|
}
|
||||||
|
|
||||||
// Image is ready
|
// Image is ready
|
||||||
imagestate = ImageLoadState.Ready;
|
imagestate = ImageLoadState.Ready;
|
||||||
|
@ -208,14 +237,18 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
lock(this)
|
lock(this)
|
||||||
{
|
{
|
||||||
// Only do this when texture is not created yet
|
// Only do this when texture is not created yet
|
||||||
if(((texture == null) || (texture.Disposed)) && this.IsLoaded)
|
if(((texture == null) || (texture.Disposed)) && this.IsImageLoaded)
|
||||||
{
|
{
|
||||||
|
Image img = bitmap;
|
||||||
|
if(loadfailed) img = Properties.Resources.Failed;
|
||||||
|
|
||||||
// Write to memory stream and read from memory
|
// Write to memory stream and read from memory
|
||||||
memstream = new MemoryStream();
|
memstream = new MemoryStream();
|
||||||
bitmap.Save(memstream, ImageFormat.Bmp);
|
img.Save(memstream, ImageFormat.Bmp);
|
||||||
memstream.Seek(0, SeekOrigin.Begin);
|
memstream.Seek(0, SeekOrigin.Begin);
|
||||||
texture = Texture.FromStream(General.Map.Graphics.Device, memstream, (int)memstream.Length, bitmap.Size.Width, bitmap.Size.Height, mipmaplevels,
|
texture = Texture.FromStream(General.Map.Graphics.Device, memstream, (int)memstream.Length,
|
||||||
Usage.None, Format.Unknown, Pool.Managed, Filter.Box, Filter.Box, 0);
|
img.Size.Width, img.Size.Height, mipmaplevels, Usage.None, Format.Unknown,
|
||||||
|
Pool.Managed, Filter.Box, Filter.Box, 0);
|
||||||
memstream.Dispose();
|
memstream.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -232,6 +265,88 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This draws a preview
|
||||||
|
public virtual void DrawPreviewCentered(Graphics target, Rectangle targetview)
|
||||||
|
{
|
||||||
|
lock(this)
|
||||||
|
{
|
||||||
|
// Preview ready?
|
||||||
|
if(previewstate == ImageLoadState.Ready)
|
||||||
|
{
|
||||||
|
// Draw preview
|
||||||
|
General.Map.Data.Previews.DrawPreviewCentered(previewindex, target, targetview);
|
||||||
|
}
|
||||||
|
// Loading failed?
|
||||||
|
else if(loadfailed)
|
||||||
|
{
|
||||||
|
// Draw error bitmap
|
||||||
|
RectangleF targetpos = General.MakeZoomedRect(Properties.Resources.Failed.Size, targetview);
|
||||||
|
target.DrawImage(Properties.Resources.Hourglass, targetpos.Location);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Draw loading bitmap
|
||||||
|
RectangleF targetpos = General.MakeZoomedRect(Properties.Resources.Hourglass.Size, targetview);
|
||||||
|
target.DrawImage(Properties.Resources.Hourglass, targetpos.Location);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This draws a preview
|
||||||
|
public virtual void DrawPreview(Graphics target, Point targetpos)
|
||||||
|
{
|
||||||
|
lock(this)
|
||||||
|
{
|
||||||
|
// Preview ready?
|
||||||
|
if(previewstate == ImageLoadState.Ready)
|
||||||
|
{
|
||||||
|
// Draw preview
|
||||||
|
General.Map.Data.Previews.DrawPreview(previewindex, target, targetpos);
|
||||||
|
}
|
||||||
|
// Loading failed?
|
||||||
|
else if(loadfailed)
|
||||||
|
{
|
||||||
|
// Draw error bitmap
|
||||||
|
target.DrawImageUnscaled(Properties.Resources.Failed, targetpos);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Draw loading bitmap
|
||||||
|
target.DrawImageUnscaled(Properties.Resources.Hourglass, targetpos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This returns a preview image
|
||||||
|
public virtual Image GetPreview()
|
||||||
|
{
|
||||||
|
lock(this)
|
||||||
|
{
|
||||||
|
// Preview ready?
|
||||||
|
if(previewstate == ImageLoadState.Ready)
|
||||||
|
{
|
||||||
|
// Make a bitmap and return it
|
||||||
|
Bitmap bmp = new Bitmap(PreviewManager.IMAGE_WIDTH, PreviewManager.IMAGE_HEIGHT);
|
||||||
|
Graphics g = Graphics.FromImage(bmp);
|
||||||
|
g.Clear(Color.Transparent);
|
||||||
|
General.Map.Data.Previews.DrawPreview(previewindex, g, new Point(0, 0));
|
||||||
|
g.Dispose();
|
||||||
|
return bmp;
|
||||||
|
}
|
||||||
|
// Loading failed?
|
||||||
|
else if(loadfailed)
|
||||||
|
{
|
||||||
|
// Return error bitmap
|
||||||
|
return Properties.Resources.Failed;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Return loading bitmap
|
||||||
|
return Properties.Resources.Hourglass;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ using System.Windows.Forms;
|
||||||
|
|
||||||
namespace CodeImp.DoomBuilder.Data
|
namespace CodeImp.DoomBuilder.Data
|
||||||
{
|
{
|
||||||
internal enum ImageLoadState : int
|
public enum ImageLoadState : int
|
||||||
{
|
{
|
||||||
None,
|
None,
|
||||||
Loading,
|
Loading,
|
||||||
|
|
|
@ -53,7 +53,6 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
|
|
||||||
// Dont do anything
|
// Dont do anything
|
||||||
public override void LoadImage() { bitmap = CodeImp.DoomBuilder.Properties.Resources.UnknownImage; }
|
public override void LoadImage() { bitmap = CodeImp.DoomBuilder.Properties.Resources.UnknownImage; }
|
||||||
internal override void CreatePixelData() { }
|
|
||||||
internal override void CreateTexture() { }
|
internal override void CreateTexture() { }
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
|
@ -26,25 +26,26 @@ using System.Drawing.Imaging;
|
||||||
using CodeImp.DoomBuilder.Rendering;
|
using CodeImp.DoomBuilder.Rendering;
|
||||||
using CodeImp.DoomBuilder.IO;
|
using CodeImp.DoomBuilder.IO;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Drawing.Drawing2D;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
namespace CodeImp.DoomBuilder.Data
|
namespace CodeImp.DoomBuilder.Data
|
||||||
{
|
{
|
||||||
internal class PreviewManager : IDisposable
|
public class PreviewManager
|
||||||
{
|
{
|
||||||
#region ================== Constants
|
#region ================== Constants
|
||||||
|
|
||||||
// Image format
|
// Image format
|
||||||
private const PixelFormat IMAGE_FORMAT = PixelFormat.Format16bppArgb1555;
|
private const PixelFormat IMAGE_FORMAT = PixelFormat.Format32bppArgb;
|
||||||
|
|
||||||
// Dimensions of a single preview image
|
// Dimensions of a single preview image
|
||||||
private const int IMAGE_WIDTH = 64;
|
internal const int IMAGE_WIDTH = 64;
|
||||||
private const int IMAGE_HEIGHT = 64;
|
internal const int IMAGE_HEIGHT = 64;
|
||||||
|
|
||||||
// How many previews on a single atlas?
|
// How many previews on a single atlas?
|
||||||
private const int PREVIEWS_X = 8;
|
private const int PREVIEWS_X = 16;
|
||||||
private const int PREVIEWS_Y = 8;
|
private const int PREVIEWS_Y = 16;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
@ -56,6 +57,9 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
// Next preview index
|
// Next preview index
|
||||||
private int nextpreviewindex;
|
private int nextpreviewindex;
|
||||||
|
|
||||||
|
// Processing
|
||||||
|
private Queue<ImageData> imageque;
|
||||||
|
|
||||||
// Disposing
|
// Disposing
|
||||||
private bool isdisposed = false;
|
private bool isdisposed = false;
|
||||||
|
|
||||||
|
@ -63,18 +67,32 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
|
|
||||||
#region ================== Properties
|
#region ================== Properties
|
||||||
|
|
||||||
|
// Constants
|
||||||
|
public int ImageWidth { get { return IMAGE_WIDTH; } }
|
||||||
|
public int ImageHeight { get { return IMAGE_HEIGHT; } }
|
||||||
|
|
||||||
// Disposing
|
// Disposing
|
||||||
public bool IsDisposed { get { return isdisposed; } }
|
internal bool IsDisposed { get { return isdisposed; } }
|
||||||
|
|
||||||
|
// Loading
|
||||||
|
internal bool IsLoading
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return (imageque.Count > 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region ================== Constructor / Disposer
|
#region ================== Constructor / Disposer
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
public PreviewManager()
|
internal PreviewManager()
|
||||||
{
|
{
|
||||||
// Initialize
|
// Initialize
|
||||||
atlases = new List<Bitmap>();
|
atlases = new List<Bitmap>();
|
||||||
|
imageque = new Queue<ImageData>();
|
||||||
nextpreviewindex = 0;
|
nextpreviewindex = 0;
|
||||||
|
|
||||||
// We have no destructor
|
// We have no destructor
|
||||||
|
@ -82,7 +100,7 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disposer
|
// Disposer
|
||||||
public void Dispose()
|
internal void Dispose()
|
||||||
{
|
{
|
||||||
// Not already disposed?
|
// Not already disposed?
|
||||||
if(!isdisposed)
|
if(!isdisposed)
|
||||||
|
@ -97,8 +115,8 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region ================== Calculations
|
#region ================== Private Methods
|
||||||
|
|
||||||
// Returns atlas index for the given preview index
|
// Returns atlas index for the given preview index
|
||||||
private int GetAtlasIndex(int previewindex)
|
private int GetAtlasIndex(int previewindex)
|
||||||
|
@ -119,35 +137,165 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
int localindex = previewindex - GetAtlasIndex(previewindex) * (PREVIEWS_X * PREVIEWS_Y);
|
int localindex = previewindex - GetAtlasIndex(previewindex) * (PREVIEWS_X * PREVIEWS_Y);
|
||||||
return localindex / PREVIEWS_X;
|
return localindex / PREVIEWS_X;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region ================== Loading
|
|
||||||
|
|
||||||
// This makes a new atlas
|
// This makes a new atlas
|
||||||
private void MakeNewAtlas()
|
private void MakeNewAtlas()
|
||||||
{
|
{
|
||||||
Bitmap b = new Bitmap(IMAGE_WIDTH * PREVIEWS_X, IMAGE_HEIGHT * PREVIEWS_Y, IMAGE_FORMAT);
|
lock(atlases)
|
||||||
atlases.Add(b);
|
{
|
||||||
|
Bitmap b = new Bitmap(IMAGE_WIDTH * PREVIEWS_X, IMAGE_HEIGHT * PREVIEWS_Y, IMAGE_FORMAT);
|
||||||
|
Graphics g = Graphics.FromImage(b);
|
||||||
|
g.Clear(Color.Transparent);
|
||||||
|
g.Dispose();
|
||||||
|
atlases.Add(b);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This makes a preview for the given image and updates the image settings
|
// This makes a preview for the given image and updates the image settings
|
||||||
private void MakeImagePreview(Image img)
|
private void MakeImagePreview(ImageData img)
|
||||||
{
|
{
|
||||||
// Do we have to make a new atlas?
|
Bitmap atlas;
|
||||||
if(GetAtlasIndex(nextpreviewindex) > (atlases.Count - 1)) MakeNewAtlas();
|
|
||||||
|
|
||||||
|
// Numbers
|
||||||
|
int atlasindex = GetAtlasIndex(nextpreviewindex);
|
||||||
|
int localx = GetLocalXIndex(nextpreviewindex);
|
||||||
|
int localy = GetLocalYIndex(nextpreviewindex);
|
||||||
|
|
||||||
|
lock(atlases)
|
||||||
|
{
|
||||||
|
// Do we have to make a new atlas?
|
||||||
|
if(atlasindex > (atlases.Count - 1)) MakeNewAtlas();
|
||||||
|
|
||||||
|
// Get the atlas we need
|
||||||
|
atlas = atlases[atlasindex];
|
||||||
|
}
|
||||||
|
|
||||||
|
lock(img)
|
||||||
|
{
|
||||||
|
// Load image if needed
|
||||||
|
if(!img.IsImageLoaded) img.LoadImage();
|
||||||
|
|
||||||
|
lock(atlas)
|
||||||
|
{
|
||||||
|
// Draw image onto atlas
|
||||||
|
Graphics g = Graphics.FromImage(atlas);
|
||||||
|
g.PageUnit = GraphicsUnit.Pixel;
|
||||||
|
g.CompositingQuality = CompositingQuality.HighQuality;
|
||||||
|
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||||
|
g.SmoothingMode = SmoothingMode.HighQuality;
|
||||||
|
g.PixelOffsetMode = PixelOffsetMode.None;
|
||||||
|
Rectangle atlasrect = new Rectangle(localx * IMAGE_WIDTH, localy * IMAGE_HEIGHT, IMAGE_WIDTH, IMAGE_HEIGHT);
|
||||||
|
RectangleF imgrect = General.MakeZoomedRect(new Size(img.Width, img.Height), atlasrect);
|
||||||
|
g.DrawImage(img.Bitmap, imgrect);
|
||||||
|
g.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unload image if no longer needed
|
||||||
|
if(!img.IsReferenced) img.UnloadImage();
|
||||||
|
|
||||||
|
// Set numbers
|
||||||
|
img.PreviewIndex = nextpreviewindex;
|
||||||
|
img.PreviewState = ImageLoadState.Ready;
|
||||||
|
nextpreviewindex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region ================== Public Methods
|
||||||
|
|
||||||
|
// This draws a preview centered in a target
|
||||||
|
internal void DrawPreview(int previewindex, Graphics target, Point targetpos)
|
||||||
|
{
|
||||||
|
Bitmap atlas;
|
||||||
|
|
||||||
|
// Get the atlas we need
|
||||||
|
lock(atlases) { atlas = atlases[GetAtlasIndex(previewindex)]; }
|
||||||
|
|
||||||
|
// Draw from atlas to target
|
||||||
|
lock(atlas)
|
||||||
|
{
|
||||||
|
RectangleF trect = new RectangleF((float)targetpos.X, (float)targetpos.Y,
|
||||||
|
(float)IMAGE_WIDTH, (float)IMAGE_HEIGHT);
|
||||||
|
RectangleF srect = new RectangleF((float)GetLocalXIndex(previewindex) * IMAGE_WIDTH,
|
||||||
|
(float)GetLocalYIndex(previewindex) * IMAGE_HEIGHT,
|
||||||
|
(float)IMAGE_WIDTH, (float)IMAGE_HEIGHT);
|
||||||
|
target.DrawImage(atlas, trect, srect, GraphicsUnit.Pixel);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This draws a preview centered in a target
|
||||||
|
internal void DrawPreviewCentered(int previewindex, Graphics target, Rectangle targetview)
|
||||||
|
{
|
||||||
|
Bitmap atlas;
|
||||||
|
|
||||||
|
// Get the atlas we need
|
||||||
|
lock(atlases) { atlas = atlases[GetAtlasIndex(previewindex)]; }
|
||||||
|
|
||||||
|
// Draw from atlas to target
|
||||||
|
lock(atlas)
|
||||||
|
{
|
||||||
|
RectangleF trect = General.MakeZoomedRect(new Size(64, 64), targetview);
|
||||||
|
RectangleF srect = new RectangleF((float)GetLocalXIndex(previewindex) * IMAGE_WIDTH,
|
||||||
|
(float)GetLocalYIndex(previewindex) * IMAGE_HEIGHT,
|
||||||
|
(float)IMAGE_WIDTH, (float)IMAGE_HEIGHT);
|
||||||
|
target.DrawImage(atlas, trect, srect, GraphicsUnit.Pixel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Background loading
|
// Background loading
|
||||||
// Return true when we have more work to do, so that the
|
// Return true when we have more work to do, so that the
|
||||||
// thread will not wait too long before calling again
|
// thread will not wait too long before calling again
|
||||||
internal bool BackgroundLoad()
|
internal bool BackgroundLoad()
|
||||||
{
|
{
|
||||||
|
// Get next item
|
||||||
|
ImageData image = null;
|
||||||
|
lock(imageque)
|
||||||
|
{
|
||||||
|
// Fetch next image to process
|
||||||
|
if(imageque.Count > 0) image = imageque.Dequeue();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Any image to process?
|
||||||
|
if(image != null)
|
||||||
|
{
|
||||||
|
// Make image preview?
|
||||||
|
if(!image.IsPreviewLoaded) MakeImagePreview(image);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (image != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This adds an image for preview creation
|
||||||
|
internal void AddImage(ImageData image)
|
||||||
|
{
|
||||||
|
lock(imageque)
|
||||||
|
{
|
||||||
|
// Add to list
|
||||||
|
image.PreviewState = ImageLoadState.Loading;
|
||||||
|
imageque.Enqueue(image);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
internal void DumpAtlases()
|
||||||
|
{
|
||||||
|
lock(atlases)
|
||||||
|
{
|
||||||
|
int index = 0;
|
||||||
|
foreach(Bitmap a in atlases)
|
||||||
|
{
|
||||||
|
lock(a)
|
||||||
|
{
|
||||||
|
string file = Path.Combine(General.AppPath, "atlas" + index++ + ".png");
|
||||||
|
a.Save(file, ImageFormat.Png);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,7 +75,7 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
byte[] membytes;
|
byte[] membytes;
|
||||||
|
|
||||||
// Checks
|
// Checks
|
||||||
if(this.IsLoaded) return;
|
if(this.IsImageLoaded) return;
|
||||||
|
|
||||||
lock(this)
|
lock(this)
|
||||||
{
|
{
|
||||||
|
@ -102,6 +102,9 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
mem.Seek(0, SeekOrigin.Begin);
|
mem.Seek(0, SeekOrigin.Begin);
|
||||||
bitmap = reader.ReadAsBitmap(mem);
|
bitmap = reader.ReadAsBitmap(mem);
|
||||||
if(bitmap == null) return;
|
if(bitmap == null) return;
|
||||||
|
|
||||||
|
// Done
|
||||||
|
mem.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pass on to base
|
// Pass on to base
|
||||||
|
|
|
@ -58,7 +58,7 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
byte[] membytes;
|
byte[] membytes;
|
||||||
|
|
||||||
// Leave when already loaded
|
// Leave when already loaded
|
||||||
if(this.IsLoaded) return;
|
if(this.IsImageLoaded) return;
|
||||||
|
|
||||||
lock(this)
|
lock(this)
|
||||||
{
|
{
|
||||||
|
@ -86,6 +86,9 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
if(bitmap != null) bitmap.Dispose();
|
if(bitmap != null) bitmap.Dispose();
|
||||||
bitmap = reader.ReadAsBitmap(mem);
|
bitmap = reader.ReadAsBitmap(mem);
|
||||||
if(bitmap == null) return;
|
if(bitmap == null) return;
|
||||||
|
|
||||||
|
// Done
|
||||||
|
mem.Dispose();
|
||||||
|
|
||||||
// Get width and height from image
|
// Get width and height from image
|
||||||
width = bitmap.Size.Width;
|
width = bitmap.Size.Width;
|
||||||
|
|
|
@ -81,10 +81,9 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
PixelColor* pixels;
|
PixelColor* pixels;
|
||||||
Stream patchdata;
|
Stream patchdata;
|
||||||
byte[] membytes;
|
byte[] membytes;
|
||||||
bool failed = false;
|
|
||||||
|
|
||||||
// Checks
|
// Checks
|
||||||
if(this.IsLoaded) return;
|
if(this.IsImageLoaded) return;
|
||||||
if((width == 0) || (height == 0)) return;
|
if((width == 0) || (height == 0)) return;
|
||||||
|
|
||||||
lock(this)
|
lock(this)
|
||||||
|
@ -125,14 +124,23 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
{
|
{
|
||||||
// Data is in an unknown format!
|
// Data is in an unknown format!
|
||||||
General.WriteLogLine("WARNING: Patch lump '" + p.lumpname + "' data format could not be read, while loading texture '" + this.Name + "'!");
|
General.WriteLogLine("WARNING: Patch lump '" + p.lumpname + "' data format could not be read, while loading texture '" + this.Name + "'!");
|
||||||
failed = true;
|
loadfailed = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Draw the patch
|
// Draw the patch
|
||||||
mem.Seek(0, SeekOrigin.Begin);
|
mem.Seek(0, SeekOrigin.Begin);
|
||||||
reader.DrawToPixelData(mem, pixels, width, height, p.x, p.y);
|
try { reader.DrawToPixelData(mem, pixels, width, height, p.x, p.y); }
|
||||||
|
catch(InvalidDataException)
|
||||||
|
{
|
||||||
|
// Data cannot be read!
|
||||||
|
General.WriteLogLine("WARNING: Patch lump '" + p.lumpname + "' data format could not be read, while loading texture '" + this.Name + "'!");
|
||||||
|
loadfailed = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Done
|
||||||
|
mem.Dispose();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -144,11 +152,11 @@ namespace CodeImp.DoomBuilder.Data
|
||||||
// Done
|
// Done
|
||||||
bitmap.UnlockBits(bitmapdata);
|
bitmap.UnlockBits(bitmapdata);
|
||||||
|
|
||||||
// When failed, use the error picture
|
// Dispose bitmap if load failed
|
||||||
if(failed)
|
if(loadfailed && (bitmap != null))
|
||||||
{
|
{
|
||||||
bitmap.Dispose();
|
bitmap.Dispose();
|
||||||
bitmap = UnknownImageReader.ReadAsBitmap();
|
bitmap = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pass on to base
|
// Pass on to base
|
||||||
|
|
|
@ -38,6 +38,7 @@ using System.Drawing;
|
||||||
using CodeImp.DoomBuilder.Plugins;
|
using CodeImp.DoomBuilder.Plugins;
|
||||||
using CodeImp.DoomBuilder.Types;
|
using CodeImp.DoomBuilder.Types;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
@ -66,26 +67,6 @@ namespace CodeImp.DoomBuilder
|
||||||
|
|
||||||
#region ================== Constants
|
#region ================== Constants
|
||||||
|
|
||||||
// Memory APIs
|
|
||||||
internal const uint MEM_COMMIT = 0x1000;
|
|
||||||
internal const uint MEM_RESERVE = 0x2000;
|
|
||||||
internal const uint MEM_DECOMMIT = 0x4000;
|
|
||||||
internal const uint MEM_RELEASE = 0x8000;
|
|
||||||
internal const uint MEM_RESET = 0x80000;
|
|
||||||
internal const uint MEM_TOP_DOWN = 0x100000;
|
|
||||||
internal const uint MEM_PHYSICAL = 0x400000;
|
|
||||||
internal const uint PAGE_NOACCESS = 0x01;
|
|
||||||
internal const uint PAGE_READONLY = 0x02;
|
|
||||||
internal const uint PAGE_READWRITE = 0x04;
|
|
||||||
internal const uint PAGE_WRITECOPY = 0x08;
|
|
||||||
internal const uint PAGE_EXECUTE = 0x10;
|
|
||||||
internal const uint PAGE_EXECUTE_READ = 0x20;
|
|
||||||
internal const uint PAGE_EXECUTE_READWRITE = 0x40;
|
|
||||||
internal const uint PAGE_EXECUTE_WRITECOPY = 0x80;
|
|
||||||
internal const uint PAGE_GUARD = 0x100;
|
|
||||||
internal const uint PAGE_NOCACHE = 0x200;
|
|
||||||
internal const uint PAGE_WRITECOMBINE = 0x400;
|
|
||||||
|
|
||||||
// SendMessage API
|
// SendMessage API
|
||||||
internal const int CB_SETITEMHEIGHT = 0x153;
|
internal const int CB_SETITEMHEIGHT = 0x153;
|
||||||
|
|
||||||
|
@ -461,6 +442,9 @@ namespace CodeImp.DoomBuilder
|
||||||
// Hook to DLL loading failure event
|
// Hook to DLL loading failure event
|
||||||
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
|
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
|
||||||
|
|
||||||
|
// Set current thread name
|
||||||
|
Thread.CurrentThread.Name = "Main Application";
|
||||||
|
|
||||||
// Get a reference to this assembly
|
// Get a reference to this assembly
|
||||||
thisasm = Assembly.GetExecutingAssembly();
|
thisasm = Assembly.GetExecutingAssembly();
|
||||||
thisversion = thisasm.GetName().Version;
|
thisversion = thisasm.GetName().Version;
|
||||||
|
|
|
@ -329,7 +329,10 @@ namespace CodeImp.DoomBuilder
|
||||||
data = new DataManager();
|
data = new DataManager();
|
||||||
maplocation = new DataLocation(DataLocation.RESOURCE_WAD, filepathname, false, false);
|
maplocation = new DataLocation(DataLocation.RESOURCE_WAD, filepathname, false, false);
|
||||||
data.Load(configinfo.Resources, options.Resources, maplocation);
|
data.Load(configinfo.Resources, options.Resources, maplocation);
|
||||||
|
|
||||||
|
// Update the used textures
|
||||||
|
General.Map.Data.UpdateUsedTextures();
|
||||||
|
|
||||||
// Bind any methods
|
// Bind any methods
|
||||||
General.Actions.BindMethods(this);
|
General.Actions.BindMethods(this);
|
||||||
|
|
||||||
|
@ -1004,6 +1007,7 @@ namespace CodeImp.DoomBuilder
|
||||||
config = null;
|
config = null;
|
||||||
configinfo = null;
|
configinfo = null;
|
||||||
GC.Collect();
|
GC.Collect();
|
||||||
|
GC.WaitForPendingFinalizers();
|
||||||
|
|
||||||
// Reload game configuration
|
// Reload game configuration
|
||||||
General.WriteLogLine("Reloading game configuration...");
|
General.WriteLogLine("Reloading game configuration...");
|
||||||
|
@ -1016,6 +1020,9 @@ namespace CodeImp.DoomBuilder
|
||||||
data = new DataManager();
|
data = new DataManager();
|
||||||
maplocation = new DataLocation(DataLocation.RESOURCE_WAD, filepathname, false, false);
|
maplocation = new DataLocation(DataLocation.RESOURCE_WAD, filepathname, false, false);
|
||||||
data.Load(configinfo.Resources, options.Resources, maplocation);
|
data.Load(configinfo.Resources, options.Resources, maplocation);
|
||||||
|
|
||||||
|
// Update the used textures
|
||||||
|
General.Map.Data.UpdateUsedTextures();
|
||||||
|
|
||||||
// Apply new settings to map elements
|
// Apply new settings to map elements
|
||||||
map.UpdateConfiguration();
|
map.UpdateConfiguration();
|
||||||
|
|
|
@ -120,7 +120,7 @@ namespace CodeImp.DoomBuilder.IO
|
||||||
// Failed loading picture
|
// Failed loading picture
|
||||||
bmp = null;
|
bmp = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return result
|
// Return result
|
||||||
return bmp;
|
return bmp;
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,33 +75,40 @@ namespace CodeImp.DoomBuilder.IO
|
||||||
|
|
||||||
// Get bitmap
|
// Get bitmap
|
||||||
bmp = ReadAsBitmap(stream);
|
bmp = ReadAsBitmap(stream);
|
||||||
width = bmp.Size.Width;
|
if(bmp != null)
|
||||||
height = bmp.Size.Height;
|
|
||||||
|
|
||||||
// Lock bitmap pixels
|
|
||||||
bmpdata = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
|
|
||||||
pixels = (PixelColor*)bmpdata.Scan0.ToPointer();
|
|
||||||
|
|
||||||
// Go for all pixels in the original image
|
|
||||||
for(ox = 0; ox < width; ox++)
|
|
||||||
{
|
{
|
||||||
for(oy = 0; oy < height; oy++)
|
width = bmp.Size.Width;
|
||||||
|
height = bmp.Size.Height;
|
||||||
|
|
||||||
|
// Lock bitmap pixels
|
||||||
|
bmpdata = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
|
||||||
|
pixels = (PixelColor*)bmpdata.Scan0.ToPointer();
|
||||||
|
|
||||||
|
// Go for all pixels in the original image
|
||||||
|
for(ox = 0; ox < width; ox++)
|
||||||
{
|
{
|
||||||
// Copy this pixel?
|
for(oy = 0; oy < height; oy++)
|
||||||
if(pixels[oy * width + ox].a > 0.5f)
|
|
||||||
{
|
{
|
||||||
// Calculate target pixel and copy when within bounds
|
// Copy this pixel?
|
||||||
tx = x + ox;
|
if(pixels[oy * width + ox].a > 0.5f)
|
||||||
ty = y + oy;
|
{
|
||||||
if((tx >= 0) && (tx < targetwidth) && (ty >= 0) && (ty < targetheight))
|
// Calculate target pixel and copy when within bounds
|
||||||
target[ty * targetwidth + tx] = pixels[oy * width + ox];
|
tx = x + ox;
|
||||||
|
ty = y + oy;
|
||||||
|
if((tx >= 0) && (tx < targetwidth) && (ty >= 0) && (ty < targetheight))
|
||||||
|
target[ty * targetwidth + tx] = pixels[oy * width + ox];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Done
|
// Done
|
||||||
bmp.UnlockBits(bmpdata);
|
bmp.UnlockBits(bmpdata);
|
||||||
bmp.Dispose();
|
bmp.Dispose();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new InvalidDataException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
|
@ -51,13 +51,13 @@ namespace CodeImp.DoomBuilder.IO
|
||||||
// This reads the image and returns a Bitmap
|
// This reads the image and returns a Bitmap
|
||||||
public Bitmap ReadAsBitmap(Stream stream)
|
public Bitmap ReadAsBitmap(Stream stream)
|
||||||
{
|
{
|
||||||
return new Bitmap(CodeImp.DoomBuilder.Properties.Resources.UnknownImage);
|
return new Bitmap(CodeImp.DoomBuilder.Properties.Resources.Failed);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This reads the image and returns a Bitmap
|
// This reads the image and returns a Bitmap
|
||||||
public static Bitmap ReadAsBitmap()
|
public static Bitmap ReadAsBitmap()
|
||||||
{
|
{
|
||||||
return new Bitmap(CodeImp.DoomBuilder.Properties.Resources.UnknownImage);
|
return new Bitmap(CodeImp.DoomBuilder.Properties.Resources.Failed);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This draws the picture to the given pixel color data
|
// This draws the picture to the given pixel color data
|
||||||
|
|
|
@ -112,7 +112,7 @@ namespace CodeImp.DoomBuilder.IO
|
||||||
if(writer != null) writer.Close();
|
if(writer != null) writer.Close();
|
||||||
if(reader != null) reader.Close();
|
if(reader != null) reader.Close();
|
||||||
if(file != null) file.Dispose();
|
if(file != null) file.Dispose();
|
||||||
|
|
||||||
// Done
|
// Done
|
||||||
isdisposed = true;
|
isdisposed = true;
|
||||||
}
|
}
|
||||||
|
|
7
Source/Properties/Resources.Designer.cs
generated
7
Source/Properties/Resources.Designer.cs
generated
|
@ -81,6 +81,13 @@ namespace CodeImp.DoomBuilder.Properties {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static System.Drawing.Bitmap Failed {
|
||||||
|
get {
|
||||||
|
object obj = ResourceManager.GetObject("Failed", resourceCulture);
|
||||||
|
return ((System.Drawing.Bitmap)(obj));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal static System.Drawing.Bitmap File {
|
internal static System.Drawing.Bitmap File {
|
||||||
get {
|
get {
|
||||||
object obj = ResourceManager.GetObject("File", resourceCulture);
|
object obj = ResourceManager.GetObject("File", resourceCulture);
|
||||||
|
|
|
@ -220,4 +220,7 @@
|
||||||
<data name="Monster2" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
<data name="Monster2" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
<value>..\Resources\Monster2.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
<value>..\Resources\Monster2.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Failed" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
|
<value>..\Resources\Failed.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
|
@ -178,7 +178,7 @@ namespace CodeImp.DoomBuilder.Rendering
|
||||||
CreateAssistColors();
|
CreateAssistColors();
|
||||||
|
|
||||||
// Create color correction table
|
// Create color correction table
|
||||||
General.Colors.CreateCorrectionTable();
|
CreateCorrectionTable();
|
||||||
|
|
||||||
// We have no destructor
|
// We have no destructor
|
||||||
GC.SuppressFinalize(this);
|
GC.SuppressFinalize(this);
|
||||||
|
|
|
@ -32,31 +32,20 @@ namespace CodeImp.DoomBuilder.Rendering
|
||||||
{
|
{
|
||||||
public unsafe class PixelColorBlock
|
public unsafe class PixelColorBlock
|
||||||
{
|
{
|
||||||
#region ================== API Declarations
|
|
||||||
|
|
||||||
[DllImport("kernel32.dll", SetLastError = true)]
|
|
||||||
private static unsafe extern void* VirtualAlloc(IntPtr lpAddress, UIntPtr dwSize, uint flAllocationType, uint flProtect);
|
|
||||||
|
|
||||||
[DllImport("kernel32.dll", SetLastError = true)]
|
|
||||||
[return: MarshalAs(UnmanagedType.Bool)]
|
|
||||||
private static unsafe extern bool VirtualFree(void* lpAddress, UIntPtr dwSize, uint dwFreeType);
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region ================== Variables
|
#region ================== Variables
|
||||||
|
|
||||||
private int width;
|
private int width;
|
||||||
private int height;
|
private int height;
|
||||||
private uint memorysize;
|
private int memorysize;
|
||||||
private PixelColor* memory;
|
private PixelColor* memory;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region ================== Properties
|
#region ================== Properties
|
||||||
|
|
||||||
public int Width { get { return width; } }
|
public int Width { get { return width; } }
|
||||||
public int Height { get { return height; } }
|
public int Height { get { return height; } }
|
||||||
public uint Length { get { return memorysize; } }
|
public int Length { get { return memorysize; } }
|
||||||
public PixelColor this[int index] { get { return memory[index]; } set { memory[index] = value; } }
|
public PixelColor this[int index] { get { return memory[index]; } set { memory[index] = value; } }
|
||||||
public PixelColor* Pointer { get { return memory; } }
|
public PixelColor* Pointer { get { return memory; } }
|
||||||
|
|
||||||
|
@ -69,12 +58,12 @@ namespace CodeImp.DoomBuilder.Rendering
|
||||||
{
|
{
|
||||||
// Check input
|
// Check input
|
||||||
if((width <= 0) || (height <= 0)) throw new ArgumentException("Cannot allocate a memory block of zero size!");
|
if((width <= 0) || (height <= 0)) throw new ArgumentException("Cannot allocate a memory block of zero size!");
|
||||||
|
|
||||||
// Initialize
|
// Initialize
|
||||||
this.width = width;
|
this.width = width;
|
||||||
this.height = height;
|
this.height = height;
|
||||||
this.memorysize = (uint)width * (uint)height * (uint)sizeof(PixelColor);
|
this.memorysize = width * height * sizeof(PixelColor);
|
||||||
this.memory = (PixelColor*)VirtualAlloc(IntPtr.Zero, new UIntPtr(memorysize), General.MEM_COMMIT, General.PAGE_READWRITE);
|
this.memory = (PixelColor*)Marshal.AllocCoTaskMem(memorysize);
|
||||||
if(this.memory == (PixelColor*)0) throw new OutOfMemoryException();
|
if(this.memory == (PixelColor*)0) throw new OutOfMemoryException();
|
||||||
GC.AddMemoryPressure(memorysize);
|
GC.AddMemoryPressure(memorysize);
|
||||||
}
|
}
|
||||||
|
@ -83,7 +72,7 @@ namespace CodeImp.DoomBuilder.Rendering
|
||||||
~PixelColorBlock()
|
~PixelColorBlock()
|
||||||
{
|
{
|
||||||
// Terminate
|
// Terminate
|
||||||
VirtualFree((void*)memory, new UIntPtr(memorysize), General.MEM_RELEASE);
|
Marshal.FreeCoTaskMem(new IntPtr(memory));
|
||||||
GC.RemoveMemoryPressure(memorysize);
|
GC.RemoveMemoryPressure(memorysize);
|
||||||
memorysize = 0;
|
memorysize = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1080,7 +1080,7 @@ namespace CodeImp.DoomBuilder.Rendering
|
||||||
if(texture != null)
|
if(texture != null)
|
||||||
{
|
{
|
||||||
// Make sure the texture is loaded
|
// Make sure the texture is loaded
|
||||||
if(!texture.IsLoaded) texture.LoadImage();
|
if(!texture.IsImageLoaded) texture.LoadImage();
|
||||||
if(texture.Texture == null) texture.CreateTexture();
|
if(texture.Texture == null) texture.CreateTexture();
|
||||||
t = texture.Texture;
|
t = texture.Texture;
|
||||||
}
|
}
|
||||||
|
|
|
@ -136,9 +136,6 @@ namespace CodeImp.DoomBuilder.Rendering
|
||||||
|
|
||||||
// Make the billboard matrix
|
// Make the billboard matrix
|
||||||
billboard = Matrix.RotationYawPitchRoll(0f, anglexy, anglez - Angle2D.PIHALF);
|
billboard = Matrix.RotationYawPitchRoll(0f, anglexy, anglez - Angle2D.PIHALF);
|
||||||
|
|
||||||
// Apply matrices
|
|
||||||
ApplyMatrices();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This applies the matrices
|
// This applies the matrices
|
||||||
|
@ -168,6 +165,9 @@ namespace CodeImp.DoomBuilder.Rendering
|
||||||
graphics.Device.SetRenderState(RenderState.SourceBlend, Blend.SourceAlpha);
|
graphics.Device.SetRenderState(RenderState.SourceBlend, Blend.SourceAlpha);
|
||||||
graphics.Device.SetRenderState(RenderState.DestinationBlend, Blend.InverseSourceAlpha);
|
graphics.Device.SetRenderState(RenderState.DestinationBlend, Blend.InverseSourceAlpha);
|
||||||
graphics.Device.SetRenderState(RenderState.TextureFactor, -1);
|
graphics.Device.SetRenderState(RenderState.TextureFactor, -1);
|
||||||
|
|
||||||
|
// Matrices
|
||||||
|
ApplyMatrices();
|
||||||
|
|
||||||
// Ready
|
// Ready
|
||||||
return true;
|
return true;
|
||||||
|
@ -233,23 +233,28 @@ namespace CodeImp.DoomBuilder.Rendering
|
||||||
// Go for all geometry in this sector
|
// Go for all geometry in this sector
|
||||||
foreach(VisualGeometry g in s.GeometryList)
|
foreach(VisualGeometry g in s.GeometryList)
|
||||||
{
|
{
|
||||||
|
ImageData curtexture;
|
||||||
|
|
||||||
|
// What texture to use?
|
||||||
|
if((g.Texture != null) && g.Texture.IsImageLoaded && !g.Texture.IsDisposed)
|
||||||
|
curtexture = g.Texture;
|
||||||
|
else
|
||||||
|
curtexture = General.Map.Data.Hourglass3D;
|
||||||
|
|
||||||
// Change texture?
|
// Change texture?
|
||||||
if(g.Texture != lasttexture)
|
if(curtexture != lasttexture)
|
||||||
{
|
{
|
||||||
// Now using this texture
|
// Now using this texture
|
||||||
lasttexture = g.Texture;
|
lasttexture = curtexture;
|
||||||
if(lasttexture != null)
|
|
||||||
{
|
|
||||||
// Load image and make texture
|
|
||||||
if(!lasttexture.IsLoaded) lasttexture.LoadImage();
|
|
||||||
if((lasttexture.Texture == null) || lasttexture.Texture.Disposed)
|
|
||||||
lasttexture.CreateTexture();
|
|
||||||
|
|
||||||
// Apply texture
|
// Create Direct3D texture if still needed
|
||||||
graphics.Device.SetTexture(0, lasttexture.Texture);
|
if((curtexture.Texture == null) || curtexture.Texture.Disposed)
|
||||||
graphics.Shaders.World3D.Texture1 = lasttexture.Texture;
|
curtexture.CreateTexture();
|
||||||
graphics.Shaders.World3D.ApplySettings();
|
|
||||||
}
|
// Apply texture
|
||||||
|
graphics.Device.SetTexture(0, curtexture.Texture);
|
||||||
|
graphics.Shaders.World3D.Texture1 = curtexture.Texture;
|
||||||
|
graphics.Shaders.World3D.ApplySettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render it!
|
// Render it!
|
||||||
|
|
|
@ -139,7 +139,7 @@ namespace CodeImp.DoomBuilder.Rendering
|
||||||
geolist.Sort();
|
geolist.Sort();
|
||||||
|
|
||||||
// Count the number of vertices there are
|
// Count the number of vertices there are
|
||||||
foreach(VisualGeometry g in geolist) numverts += g.Vertices.Length;
|
foreach(VisualGeometry g in geolist) if(g.Vertices != null) numverts += g.Vertices.Length;
|
||||||
|
|
||||||
// Any vertics?
|
// Any vertics?
|
||||||
if(numverts > 0)
|
if(numverts > 0)
|
||||||
|
@ -152,7 +152,7 @@ namespace CodeImp.DoomBuilder.Rendering
|
||||||
bufferstream = geobuffer.Lock(0, WorldVertex.Stride * numverts, LockFlags.Discard);
|
bufferstream = geobuffer.Lock(0, WorldVertex.Stride * numverts, LockFlags.Discard);
|
||||||
foreach(VisualGeometry g in geolist)
|
foreach(VisualGeometry g in geolist)
|
||||||
{
|
{
|
||||||
if(g.Vertices.Length > 0)
|
if((g.Vertices != null) && (g.Vertices.Length > 0))
|
||||||
{
|
{
|
||||||
bufferstream.WriteRange<WorldVertex>(g.Vertices);
|
bufferstream.WriteRange<WorldVertex>(g.Vertices);
|
||||||
g.VertexOffset = v;
|
g.VertexOffset = v;
|
||||||
|
|
BIN
Source/Resources/Failed.png
Normal file
BIN
Source/Resources/Failed.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.5 KiB |
BIN
Source/Resources/Hourglass3D.png
Normal file
BIN
Source/Resources/Hourglass3D.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 406 B |
|
@ -47,7 +47,7 @@ namespace CodeImp.DoomBuilder.Windows
|
||||||
// Constructor
|
// Constructor
|
||||||
public FlatBrowserForm()
|
public FlatBrowserForm()
|
||||||
{
|
{
|
||||||
Dictionary<long, long> useditems = new Dictionary<long,long>();
|
Cursor.Current = Cursors.WaitCursor;
|
||||||
|
|
||||||
// Initialize
|
// Initialize
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
@ -57,43 +57,15 @@ namespace CodeImp.DoomBuilder.Windows
|
||||||
ListViewGroup used = browser.AddGroup("Used Flats");
|
ListViewGroup used = browser.AddGroup("Used Flats");
|
||||||
ListViewGroup avail = browser.AddGroup("Available Flats");
|
ListViewGroup avail = browser.AddGroup("Available Flats");
|
||||||
|
|
||||||
// Go through the map to find the used flats
|
// Update the used textures
|
||||||
foreach(Sector s in General.Map.Map.Sectors)
|
General.Map.Data.UpdateUsedTextures();
|
||||||
{
|
|
||||||
// Add floor flat
|
|
||||||
if(!useditems.ContainsKey(s.LongFloorTexture)) useditems.Add(s.LongFloorTexture, 0);
|
|
||||||
|
|
||||||
// Add ceiling flat
|
|
||||||
if(!useditems.ContainsKey(s.LongCeilTexture)) useditems.Add(s.LongCeilTexture, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// When mixing textures with flats, include textures as well
|
|
||||||
if(General.Map.Config.MixTexturesFlats)
|
|
||||||
{
|
|
||||||
// Go through the map to find the used textures
|
|
||||||
foreach(Sidedef sd in General.Map.Map.Sidedefs)
|
|
||||||
{
|
|
||||||
// Add high texture
|
|
||||||
if(sd.HighTexture.Length > 0)
|
|
||||||
if(!useditems.ContainsKey(sd.LongHighTexture)) useditems.Add(sd.LongHighTexture, 0);
|
|
||||||
|
|
||||||
// Add mid texture
|
|
||||||
if(sd.LowTexture.Length > 0)
|
|
||||||
if(!useditems.ContainsKey(sd.LongMiddleTexture)) useditems.Add(sd.LongMiddleTexture, 0);
|
|
||||||
|
|
||||||
// Add low texture
|
|
||||||
if(sd.MiddleTexture.Length > 0)
|
|
||||||
if(!useditems.ContainsKey(sd.LongLowTexture)) useditems.Add(sd.LongLowTexture, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start adding
|
// Start adding
|
||||||
browser.BeginAdding();
|
browser.BeginAdding();
|
||||||
|
|
||||||
// Add all used flats
|
// Add all used flats
|
||||||
foreach(ImageData img in General.Map.Data.Flats)
|
foreach(ImageData img in General.Map.Data.Flats)
|
||||||
if(useditems.ContainsKey(img.LongName))
|
if(img.UsedInMap) browser.Add(img.Name, img, img, used);
|
||||||
browser.Add(img.Name, img, img, used);
|
|
||||||
|
|
||||||
// Add all available flats
|
// Add all available flats
|
||||||
foreach(ImageData img in General.Map.Data.Flats)
|
foreach(ImageData img in General.Map.Data.Flats)
|
||||||
|
@ -136,6 +108,7 @@ namespace CodeImp.DoomBuilder.Windows
|
||||||
{
|
{
|
||||||
// Focus the textbox
|
// Focus the textbox
|
||||||
browser.FocusTextbox();
|
browser.FocusTextbox();
|
||||||
|
Cursor.Current = Cursors.Default;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loading
|
// Loading
|
||||||
|
|
|
@ -93,7 +93,7 @@ namespace CodeImp.DoomBuilder.Windows
|
||||||
// Set this texture as background
|
// Set this texture as background
|
||||||
backgroundname = result;
|
backgroundname = result;
|
||||||
backgroundsource = GridSetup.SOURCE_TEXTURES;
|
backgroundsource = GridSetup.SOURCE_TEXTURES;
|
||||||
General.DisplayZoomedImage(backgroundimage, General.Map.Data.GetTextureBitmap(result));
|
General.DisplayZoomedImage(backgroundimage, General.Map.Data.GetTextureImage(result).GetPreview());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,7 +109,7 @@ namespace CodeImp.DoomBuilder.Windows
|
||||||
// Set this flat as background
|
// Set this flat as background
|
||||||
backgroundname = result;
|
backgroundname = result;
|
||||||
backgroundsource = GridSetup.SOURCE_FLATS;
|
backgroundsource = GridSetup.SOURCE_FLATS;
|
||||||
General.DisplayZoomedImage(backgroundimage, General.Map.Data.GetFlatBitmap(result));
|
General.DisplayZoomedImage(backgroundimage, General.Map.Data.GetFlatImage(result).GetPreview());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -399,6 +399,9 @@ namespace CodeImp.DoomBuilder.Windows
|
||||||
fieldslist.Apply(l.Fields);
|
fieldslist.Apply(l.Fields);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update the used textures
|
||||||
|
General.Map.Data.UpdateUsedTextures();
|
||||||
|
|
||||||
// Done
|
// Done
|
||||||
General.Map.IsChanged = true;
|
General.Map.IsChanged = true;
|
||||||
this.DialogResult = DialogResult.OK;
|
this.DialogResult = DialogResult.OK;
|
||||||
|
|
|
@ -150,7 +150,10 @@ namespace CodeImp.DoomBuilder.Windows
|
||||||
// Custom fields
|
// Custom fields
|
||||||
fieldslist.Apply(s.Fields);
|
fieldslist.Apply(s.Fields);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update the used textures
|
||||||
|
General.Map.Data.UpdateUsedTextures();
|
||||||
|
|
||||||
// Done
|
// Done
|
||||||
General.Map.IsChanged = true;
|
General.Map.IsChanged = true;
|
||||||
this.DialogResult = DialogResult.OK;
|
this.DialogResult = DialogResult.OK;
|
||||||
|
|
|
@ -47,7 +47,7 @@ namespace CodeImp.DoomBuilder.Windows
|
||||||
// Constructor
|
// Constructor
|
||||||
public TextureBrowserForm()
|
public TextureBrowserForm()
|
||||||
{
|
{
|
||||||
Dictionary<long, long> useditems = new Dictionary<long,long>();
|
Cursor.Current = Cursors.WaitCursor;
|
||||||
|
|
||||||
// Initialize
|
// Initialize
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
@ -57,36 +57,9 @@ namespace CodeImp.DoomBuilder.Windows
|
||||||
ListViewGroup used = browser.AddGroup("Used Textures");
|
ListViewGroup used = browser.AddGroup("Used Textures");
|
||||||
ListViewGroup avail = browser.AddGroup("Available Textures");
|
ListViewGroup avail = browser.AddGroup("Available Textures");
|
||||||
|
|
||||||
// Go through the map to find the used textures
|
// Update the used textures
|
||||||
foreach(Sidedef sd in General.Map.Map.Sidedefs)
|
General.Map.Data.UpdateUsedTextures();
|
||||||
{
|
|
||||||
// Add high texture
|
|
||||||
if(sd.HighTexture.Length > 0)
|
|
||||||
if(!useditems.ContainsKey(sd.LongHighTexture)) useditems.Add(sd.LongHighTexture, 0);
|
|
||||||
|
|
||||||
// Add mid texture
|
|
||||||
if(sd.LowTexture.Length > 0)
|
|
||||||
if(!useditems.ContainsKey(sd.LongMiddleTexture)) useditems.Add(sd.LongMiddleTexture, 0);
|
|
||||||
|
|
||||||
// Add low texture
|
|
||||||
if(sd.MiddleTexture.Length > 0)
|
|
||||||
if(!useditems.ContainsKey(sd.LongLowTexture)) useditems.Add(sd.LongLowTexture, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// When mixing textures with flats, include flats as well
|
|
||||||
if(General.Map.Config.MixTexturesFlats)
|
|
||||||
{
|
|
||||||
// Go through the map to find the used flats
|
|
||||||
foreach(Sector s in General.Map.Map.Sectors)
|
|
||||||
{
|
|
||||||
// Add floor flat
|
|
||||||
if(!useditems.ContainsKey(s.LongFloorTexture)) useditems.Add(s.LongFloorTexture, 0);
|
|
||||||
|
|
||||||
// Add ceil flat
|
|
||||||
if(!useditems.ContainsKey(s.LongCeilTexture)) useditems.Add(s.LongCeilTexture, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start adding
|
// Start adding
|
||||||
browser.BeginAdding();
|
browser.BeginAdding();
|
||||||
|
|
||||||
|
@ -94,17 +67,12 @@ namespace CodeImp.DoomBuilder.Windows
|
||||||
foreach(ImageData img in General.Map.Data.Textures)
|
foreach(ImageData img in General.Map.Data.Textures)
|
||||||
{
|
{
|
||||||
browser.Add(img.Name, img, img, avail);
|
browser.Add(img.Name, img, img, avail);
|
||||||
img.Temporary = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add all used textures and mark the images for permanent loading
|
// Add all used textures and mark the images for permanent loading
|
||||||
foreach(ImageData img in General.Map.Data.Textures)
|
foreach(ImageData img in General.Map.Data.Textures)
|
||||||
{
|
{
|
||||||
if(useditems.ContainsKey(img.LongName))
|
if(img.UsedInMap) browser.Add(img.Name, img, img, used);
|
||||||
{
|
|
||||||
browser.Add(img.Name, img, img, used);
|
|
||||||
img.Temporary = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Done adding
|
// Done adding
|
||||||
|
@ -144,6 +112,7 @@ namespace CodeImp.DoomBuilder.Windows
|
||||||
{
|
{
|
||||||
// Focus the textbox
|
// Focus the textbox
|
||||||
browser.FocusTextbox();
|
browser.FocusTextbox();
|
||||||
|
Cursor.Current = Cursors.Default;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loading
|
// Loading
|
||||||
|
|
|
@ -310,7 +310,7 @@ namespace CodeImp.DoomBuilder.Windows
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show image
|
// Show image
|
||||||
General.DisplayZoomedImage(spritetex, General.Map.Data.GetSpriteBitmap(ti.Sprite));
|
General.DisplayZoomedImage(spritetex, General.Map.Data.GetSpriteImage(ti.Sprite).GetPreview());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue