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
|
||||
mouse.SetCooperativeLevel(source,
|
||||
CooperativeLevel.Nonexclusive | CooperativeLevel.Foreground);
|
||||
|
||||
|
||||
// Aquire device
|
||||
try { mouse.Acquire(); }
|
||||
catch(Exception) { }
|
||||
|
@ -113,20 +113,30 @@ namespace CodeImp.DoomBuilder.Actions
|
|||
float changex, changey;
|
||||
|
||||
// Poll the device
|
||||
Result result = mouse.Poll();
|
||||
if(result.IsSuccess)
|
||||
try
|
||||
{
|
||||
// Get the changes since previous poll
|
||||
ms = mouse.GetCurrentState();
|
||||
|
||||
// Calculate changes depending on sensitivity
|
||||
changex = (float)ms.X * General.Settings.VisualMouseSensX;
|
||||
changey = (float)ms.Y * General.Settings.VisualMouseSensY;
|
||||
|
||||
// Return changes
|
||||
return new Vector2D(changex, changey);
|
||||
Result result = mouse.Poll();
|
||||
if(result.IsSuccess)
|
||||
{
|
||||
// Get the changes since previous poll
|
||||
ms = mouse.GetCurrentState();
|
||||
|
||||
// Calculate changes depending on sensitivity
|
||||
changex = (float)ms.X * General.Settings.VisualMouseSensX;
|
||||
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
|
||||
try { mouse.Acquire(); }
|
||||
|
|
|
@ -600,6 +600,8 @@
|
|||
<None Include="Resources\Copy.png" />
|
||||
<None Include="Resources\Cut.png" />
|
||||
<Content Include="Resources\DB2.ico" />
|
||||
<EmbeddedResource Include="Resources\Hourglass3D.png" />
|
||||
<None Include="Resources\Failed.png" />
|
||||
<None Include="Resources\Monster2.png" />
|
||||
<None Include="Resources\Grid2_arrowup.png" />
|
||||
<None Include="Resources\Zoom_arrowup.png" />
|
||||
|
|
|
@ -30,6 +30,7 @@ using CodeImp.DoomBuilder.Map;
|
|||
using CodeImp.DoomBuilder.Rendering;
|
||||
using CodeImp.DoomBuilder.Geometry;
|
||||
using CodeImp.DoomBuilder.Editing;
|
||||
using CodeImp.DoomBuilder.Actions;
|
||||
|
||||
#endregion
|
||||
|
||||
|
@ -215,6 +216,23 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
|
|||
|
||||
#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
|
||||
public override void OnRedrawDisplay()
|
||||
{
|
||||
|
|
|
@ -62,7 +62,6 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
|
|||
|
||||
// Load floor texture
|
||||
base.Texture = General.Map.Data.GetFlatImage(s.LongCeilTexture);
|
||||
base.Texture.LoadImage();
|
||||
|
||||
// Make vertices
|
||||
verts = new WorldVertex[s.Vertices.Length];
|
||||
|
@ -74,9 +73,17 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
|
|||
verts[i].c = -1;
|
||||
|
||||
// Grid aligned texture coordinates
|
||||
verts[i].u = s.Vertices[i].x / base.Texture.ScaledWidth;
|
||||
verts[i].v = s.Vertices[i].y / base.Texture.ScaledHeight;
|
||||
|
||||
if(base.Texture.IsImageLoaded)
|
||||
{
|
||||
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
|
||||
verts[i].x = s.Vertices[i].x;
|
||||
verts[i].y = s.Vertices[i].y;
|
||||
|
|
|
@ -61,7 +61,6 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
|
|||
|
||||
// Load floor texture
|
||||
base.Texture = General.Map.Data.GetFlatImage(s.LongFloorTexture);
|
||||
base.Texture.LoadImage();
|
||||
|
||||
// Make vertices
|
||||
verts = new WorldVertex[s.Vertices.Length];
|
||||
|
@ -73,8 +72,16 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
|
|||
verts[i].c = -1;
|
||||
|
||||
// Grid aligned texture coordinates
|
||||
verts[i].u = s.Vertices[i].x / base.Texture.ScaledWidth;
|
||||
verts[i].v = s.Vertices[i].y / base.Texture.ScaledHeight;
|
||||
if(base.Texture.IsImageLoaded)
|
||||
{
|
||||
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
|
||||
verts[i].x = s.Vertices[i].x;
|
||||
|
|
|
@ -74,7 +74,6 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
|
|||
{
|
||||
// Load texture
|
||||
base.Texture = General.Map.Data.GetTextureImage(s.LongLowTexture);
|
||||
base.Texture.LoadImage();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -83,7 +83,6 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
|
|||
{
|
||||
// Load texture
|
||||
base.Texture = General.Map.Data.GetTextureImage(s.LongMiddleTexture);
|
||||
base.Texture.LoadImage();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -74,7 +74,6 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
|
|||
{
|
||||
// Load texture
|
||||
base.Texture = General.Map.Data.GetTextureImage(s.LongHighTexture);
|
||||
base.Texture.LoadImage();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -59,7 +59,7 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
else
|
||||
{
|
||||
// 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))
|
||||
{
|
||||
CleanUp();
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
|
|
|
@ -40,9 +40,6 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
{
|
||||
#region ================== Constants
|
||||
|
||||
// Maximum loaded items
|
||||
private const int MAX_LOADED_ITEMS = 200;
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Delegates / Events
|
||||
|
@ -61,9 +58,6 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
// All items
|
||||
private List<ImageBrowserItem> items;
|
||||
|
||||
// Loaded items
|
||||
private LinkedList<ImageBrowserItem> loadeditems;
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Properties
|
||||
|
@ -81,7 +75,6 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
// Initialize
|
||||
InitializeComponent();
|
||||
items = new List<ImageBrowserItem>();
|
||||
loadeditems = new LinkedList<ImageBrowserItem>();
|
||||
|
||||
// Move textbox with label
|
||||
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()
|
||||
{
|
||||
// Stop refresh timer
|
||||
|
@ -109,24 +102,16 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
list.SuspendLayout();
|
||||
list.BeginUpdate();
|
||||
|
||||
// Go for all items
|
||||
foreach(ImageBrowserItem i in list.Items)
|
||||
{
|
||||
// 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();
|
||||
}
|
||||
// Dispose items
|
||||
foreach(ImageBrowserItem i in list.Items) i.Dispose();
|
||||
|
||||
// Trash list items
|
||||
list.Clear();
|
||||
loadeditems.Clear();
|
||||
|
||||
// Done updating list
|
||||
updating = false;
|
||||
list.EndUpdate();
|
||||
list.ResumeLayout();
|
||||
updating = false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -136,67 +121,34 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
// Draw item
|
||||
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
|
||||
private void refreshtimer_Tick(object sender, EventArgs e)
|
||||
{
|
||||
bool allpreviewsloaded = true;
|
||||
|
||||
// Go for all items
|
||||
foreach(ImageBrowserItem i in list.Items)
|
||||
{
|
||||
// Bounds within view?
|
||||
if(i.Bounds.IntersectsWith(list.ClientRectangle))
|
||||
// Check if there are still previews that are not loaded
|
||||
allpreviewsloaded &= i.IsPreviewLoaded;
|
||||
|
||||
// Items needs to be redrawn?
|
||||
if(i.CheckRedrawNeeded())
|
||||
{
|
||||
// Remove from loaded list if in there
|
||||
if(i.LoadedTicket != null) loadeditems.Remove(i.LoadedTicket);
|
||||
|
||||
// Image not loaded?
|
||||
if(!i.icon.IsLoaded && !i.IsImageLoaded)
|
||||
// Bounds within view?
|
||||
if(i.Bounds.IntersectsWith(list.ClientRectangle))
|
||||
{
|
||||
// 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
|
||||
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(loadeditems.Count > MAX_LOADED_ITEMS)
|
||||
{
|
||||
// Unload items
|
||||
for(int i = 0; i < (loadeditems.Count - MAX_LOADED_ITEMS); i++)
|
||||
{
|
||||
loadeditems.First.Value.ReleaseImage();
|
||||
loadeditems.First.Value.LoadedTicket = null;
|
||||
loadeditems.RemoveFirst();
|
||||
}
|
||||
}
|
||||
// If all previews were loaded, stop this timer
|
||||
if(allpreviewsloaded) refreshtimer.Stop();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
|
|
@ -46,11 +46,8 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
|
||||
// Group
|
||||
private ListViewGroup listgroup;
|
||||
private LinkedListNode<ImageBrowserItem> loadedticked;
|
||||
|
||||
// Image cache
|
||||
private Image normalimage;
|
||||
private Image selectedimage;
|
||||
private bool imageloaded;
|
||||
|
||||
#endregion
|
||||
|
@ -58,9 +55,7 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
#region ================== Properties
|
||||
|
||||
public ListViewGroup ListGroup { get { return listgroup; } set { listgroup = value; } }
|
||||
public LinkedListNode<ImageBrowserItem> LoadedTicket { get { return loadedticked; } set { loadedticked = value; } }
|
||||
public bool IsImageLoaded { get { return imageloaded; } }
|
||||
public bool HasImage { get { return (normalimage != null); } }
|
||||
public bool IsPreviewLoaded { get { return imageloaded; } }
|
||||
|
||||
#endregion
|
||||
|
||||
|
@ -78,8 +73,6 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
// Disposer
|
||||
public void Dispose()
|
||||
{
|
||||
ReleaseImage();
|
||||
loadedticked = null;
|
||||
icon = null;
|
||||
listgroup = null;
|
||||
}
|
||||
|
@ -89,36 +82,37 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
#region ================== Methods
|
||||
|
||||
// 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
|
||||
private Image DrawImage(Rectangle bounds, bool selected)
|
||||
public void Draw(Graphics g, Rectangle bounds)
|
||||
{
|
||||
Brush forecolor;
|
||||
Brush backcolor;
|
||||
|
||||
// Remember if the preview is loaded
|
||||
imageloaded = icon.IsPreviewLoaded;
|
||||
|
||||
// Make a new image and graphics to draw with
|
||||
Image image = new Bitmap(bounds.Width, bounds.Height, PixelFormat.Format32bppArgb);
|
||||
Graphics g = Graphics.FromImage(image);
|
||||
// Drawing settings
|
||||
g.CompositingQuality = CompositingQuality.HighSpeed;
|
||||
g.InterpolationMode = InterpolationMode.Bilinear;
|
||||
g.SmoothingMode = SmoothingMode.HighQuality;
|
||||
g.InterpolationMode = InterpolationMode.NearestNeighbor;
|
||||
g.SmoothingMode = SmoothingMode.HighSpeed;
|
||||
g.PixelOffsetMode = PixelOffsetMode.None;
|
||||
|
||||
// Determine coordinates
|
||||
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(bordersize.Width, bordersize.Height, 64, 64);
|
||||
PointF textpos = new PointF(((float)bounds.Width - textsize.Width) * 0.5f, bounds.Height - textsize.Height - 2);
|
||||
Rectangle imagerect = new Rectangle(bounds.Left + ((bounds.Width - 64) >> 1),
|
||||
bounds.Top + ((bounds.Height - 64 - (int)textsize.Height) >> 1), 64, 64);
|
||||
PointF textpos = new PointF(bounds.Left + ((float)bounds.Width - textsize.Width) * 0.5f, bounds.Bottom - textsize.Height - 2);
|
||||
|
||||
// Determine colors
|
||||
if(selected)
|
||||
if(this.Selected)
|
||||
{
|
||||
// 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.1f));
|
||||
forecolor = SystemBrushes.HighlightText;
|
||||
|
@ -131,43 +125,9 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
}
|
||||
|
||||
// Draw!
|
||||
g.FillRectangle(backcolor, 0, 0, bounds.Width, bounds.Height);
|
||||
g.DrawImage(icon.Bitmap, General.MakeZoomedRect(icon.Bitmap.Size, imagerect));
|
||||
g.FillRectangle(backcolor, bounds);
|
||||
icon.DrawPreview(g, imagerect.Location);
|
||||
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
|
||||
|
|
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))
|
||||
{
|
||||
bmp.Dispose();
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
|
|
|
@ -38,16 +38,32 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
{
|
||||
public abstract partial class ImageSelectorControl : UserControl
|
||||
{
|
||||
// Properties
|
||||
public string TextureName { get { return name.Text; } set { name.Text = value; } }
|
||||
#region ================== Variables
|
||||
|
||||
private Bitmap bmp;
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Properties
|
||||
|
||||
public string TextureName { get { return name.Text; } set { name.Text = value; } }
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Constructor / Destructor
|
||||
|
||||
// Constructor
|
||||
public ImageSelectorControl()
|
||||
{
|
||||
// Initialize
|
||||
InitializeComponent();
|
||||
bmp = new Bitmap(PreviewManager.IMAGE_WIDTH, PreviewManager.IMAGE_HEIGHT);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Events
|
||||
|
||||
// When resized
|
||||
private void ImageSelectorControl_Resize(object sender, EventArgs e)
|
||||
{
|
||||
|
@ -74,9 +90,27 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
// Name text changed
|
||||
private void name_TextChanged(object sender, EventArgs e)
|
||||
{
|
||||
// Show it centered
|
||||
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
|
||||
protected abstract Image FindImage(string imagename);
|
||||
|
||||
|
@ -98,5 +132,7 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
return original;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -259,7 +259,7 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
else
|
||||
{
|
||||
// Set the image
|
||||
panel.BackgroundImage = General.Map.Data.GetTextureBitmap(name);
|
||||
panel.BackgroundImage = General.Map.Data.GetTextureImage(name).GetPreview();
|
||||
}
|
||||
|
||||
// Image not null?
|
||||
|
|
|
@ -65,8 +65,8 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
brightness.Text = s.Brightness.ToString();
|
||||
floorname.Text = s.FloorTexture;
|
||||
ceilingname.Text = s.CeilTexture;
|
||||
General.DisplayZoomedImage(floortex, General.Map.Data.GetFlatBitmap(s.FloorTexture));
|
||||
General.DisplayZoomedImage(ceilingtex, General.Map.Data.GetFlatBitmap(s.CeilTexture));
|
||||
General.DisplayZoomedImage(floortex, General.Map.Data.GetFlatImage(s.FloorTexture).GetPreview());
|
||||
General.DisplayZoomedImage(ceilingtex, General.Map.Data.GetFlatImage(s.CeilTexture).GetPreview());
|
||||
|
||||
// Show the whole thing
|
||||
this.Show();
|
||||
|
|
|
@ -68,7 +68,7 @@ namespace CodeImp.DoomBuilder.Controls
|
|||
else
|
||||
{
|
||||
// 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();
|
||||
angle.Text = t.AngleDeg.ToString() + "\u00B0";
|
||||
spritename.Text = ti.Sprite;
|
||||
General.DisplayZoomedImage(spritetex, General.Map.Data.GetSpriteBitmap(ti.Sprite));
|
||||
General.DisplayZoomedImage(spritetex, General.Map.Data.GetSpriteImage(ti.Sprite).GetPreview());
|
||||
|
||||
// Arguments
|
||||
if(act != null)
|
||||
|
|
|
@ -29,6 +29,7 @@ using System.Windows.Forms;
|
|||
using SlimDX.Direct3D9;
|
||||
using CodeImp.DoomBuilder.Config;
|
||||
using System.Threading;
|
||||
using CodeImp.DoomBuilder.Map;
|
||||
|
||||
#endregion
|
||||
|
||||
|
@ -62,12 +63,14 @@ namespace CodeImp.DoomBuilder.Data
|
|||
// Background loading
|
||||
private Queue<ImageData> imageque;
|
||||
private Thread backgroundloader;
|
||||
private volatile bool updatedusedtextures;
|
||||
|
||||
// Image previews
|
||||
private PreviewManager previews;
|
||||
|
||||
// Special images
|
||||
private ImageData missingtexture3d;
|
||||
private ImageData hourglass3d;
|
||||
|
||||
// Disposing
|
||||
private bool isdisposed = false;
|
||||
|
@ -77,21 +80,22 @@ namespace CodeImp.DoomBuilder.Data
|
|||
#region ================== Properties
|
||||
|
||||
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> Flats { get { return flats.Values; } }
|
||||
public List<string> TextureNames { get { return texturenames; } }
|
||||
public List<string> FlatNames { get { return flatnames; } }
|
||||
public bool IsDisposed { get { return isdisposed; } }
|
||||
public ImageData MissingTexture3D { get { return missingtexture3d; } }
|
||||
public ImageData Hourglass3D { get { return hourglass3d; } }
|
||||
|
||||
public bool IsLoading
|
||||
{
|
||||
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
|
||||
{
|
||||
|
@ -113,6 +117,8 @@ namespace CodeImp.DoomBuilder.Data
|
|||
// Load special images
|
||||
missingtexture3d = new ResourceImage("MissingTexture3D.png");
|
||||
missingtexture3d.LoadImage();
|
||||
hourglass3d = new ResourceImage("Hourglass3D.png");
|
||||
hourglass3d.LoadImage();
|
||||
}
|
||||
|
||||
// Disposer
|
||||
|
@ -163,7 +169,7 @@ namespace CodeImp.DoomBuilder.Data
|
|||
sprites = new Dictionary<long, ImageData>();
|
||||
texturenames = new List<string>();
|
||||
flatnames = new List<string>();
|
||||
loadlist = new LinkedList<ImageData>();
|
||||
imageque = new Queue<ImageData>();
|
||||
previews = new PreviewManager();
|
||||
|
||||
// Go for all locations
|
||||
|
@ -252,7 +258,7 @@ namespace CodeImp.DoomBuilder.Data
|
|||
sprites = null;
|
||||
texturenames = null;
|
||||
flatnames = null;
|
||||
loadlist = null;
|
||||
imageque = null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -310,7 +316,7 @@ namespace CodeImp.DoomBuilder.Data
|
|||
// Start a low priority thread to load images in background
|
||||
General.WriteLogLine("Starting background resource loading...");
|
||||
backgroundloader = new Thread(new ThreadStart(BackgroundLoad));
|
||||
backgroundloader.Name = "BackgroundLoader";
|
||||
backgroundloader.Name = "Background Loader";
|
||||
backgroundloader.Priority = ThreadPriority.Lowest;
|
||||
backgroundloader.Start();
|
||||
}
|
||||
|
@ -318,7 +324,7 @@ namespace CodeImp.DoomBuilder.Data
|
|||
// This stops background loading
|
||||
private void StopBackgroundLoader()
|
||||
{
|
||||
LinkedListNode<ImageData> n;
|
||||
ImageData img;
|
||||
|
||||
General.WriteLogLine("Stopping background resource loading...");
|
||||
if(backgroundloader != null)
|
||||
|
@ -328,14 +334,32 @@ namespace CodeImp.DoomBuilder.Data
|
|||
backgroundloader.Join();
|
||||
|
||||
// Reset load states on all images in the list
|
||||
n = loadlist.First;
|
||||
while(n != null)
|
||||
while(imageque.Count > 0)
|
||||
{
|
||||
n.Value.LoadState = ImageData.LOADSTATE_NONE;
|
||||
n.Value.LoadingTicket = null;
|
||||
n = n.Next;
|
||||
img = imageque.Dequeue();
|
||||
|
||||
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
|
||||
backgroundloader = null;
|
||||
|
@ -350,11 +374,18 @@ namespace CodeImp.DoomBuilder.Data
|
|||
{
|
||||
do
|
||||
{
|
||||
// Do we have to update the used-in-map status?
|
||||
if(updatedusedtextures)
|
||||
{
|
||||
BackgroundUpdateUsedTextures();
|
||||
updatedusedtextures = false;
|
||||
}
|
||||
|
||||
// Get next item
|
||||
ImageData image = null;
|
||||
lock(imageque)
|
||||
{
|
||||
// Fethc next image to process
|
||||
// Fetch next image to process
|
||||
if(imageque.Count > 0) image = imageque.Dequeue();
|
||||
}
|
||||
|
||||
|
@ -362,23 +393,16 @@ namespace CodeImp.DoomBuilder.Data
|
|||
if(image != null)
|
||||
{
|
||||
// Load this image?
|
||||
if(image.ImageState == ImageLoadState.Loading)
|
||||
if(image.IsReferenced && (image.ImageState != ImageLoadState.Ready))
|
||||
{
|
||||
// Still referenced?
|
||||
if(image.IsReferenced)
|
||||
image.LoadImage();
|
||||
else
|
||||
image.ImageState = ImageLoadState.None;
|
||||
image.LoadImage();
|
||||
}
|
||||
|
||||
// Unload this image?
|
||||
if(image.ImageState == ImageLoadState.Unloading)
|
||||
if(!image.IsReferenced && (image.ImageState != ImageLoadState.None))
|
||||
{
|
||||
// Still unreferenced?
|
||||
if(!image.IsReferenced)
|
||||
image.UnloadImage();
|
||||
else
|
||||
image.ImageState = ImageLoadState.Ready;
|
||||
image.UnloadImage();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -405,9 +429,6 @@ namespace CodeImp.DoomBuilder.Data
|
|||
Thread.Sleep(50);
|
||||
}
|
||||
}
|
||||
|
||||
// Done
|
||||
image = null;
|
||||
}
|
||||
while(true);
|
||||
}
|
||||
|
@ -439,6 +460,41 @@ namespace CodeImp.DoomBuilder.Data
|
|||
// Update icon
|
||||
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
|
||||
|
||||
|
@ -505,6 +561,9 @@ namespace CodeImp.DoomBuilder.Data
|
|||
flats.Remove(img.LongName);
|
||||
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
|
||||
public Bitmap GetTextureBitmap(string name)
|
||||
{
|
||||
|
@ -587,6 +650,7 @@ namespace CodeImp.DoomBuilder.Data
|
|||
img.CreateTexture();
|
||||
return img.Texture;
|
||||
}
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
|
@ -621,6 +685,9 @@ namespace CodeImp.DoomBuilder.Data
|
|||
textures.Remove(img.LongName);
|
||||
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
|
||||
public Bitmap GetFlatBitmap(string name)
|
||||
{
|
||||
|
@ -703,6 +773,7 @@ namespace CodeImp.DoomBuilder.Data
|
|||
img.CreateTexture();
|
||||
return img.Texture;
|
||||
}
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
|
@ -736,6 +807,9 @@ namespace CodeImp.DoomBuilder.Data
|
|||
|
||||
// Add to collection
|
||||
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
|
||||
public Bitmap GetSpriteBitmap(string name)
|
||||
{
|
||||
|
@ -803,6 +880,7 @@ namespace CodeImp.DoomBuilder.Data
|
|||
img.CreateTexture();
|
||||
return img.Texture;
|
||||
}
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
|
@ -834,6 +912,13 @@ namespace CodeImp.DoomBuilder.Data
|
|||
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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ namespace CodeImp.DoomBuilder.Data
|
|||
public override void LoadImage()
|
||||
{
|
||||
// Leave when already loaded
|
||||
if(this.IsLoaded) return;
|
||||
if(this.IsImageLoaded) return;
|
||||
|
||||
lock(this)
|
||||
{
|
||||
|
|
|
@ -57,7 +57,7 @@ namespace CodeImp.DoomBuilder.Data
|
|||
byte[] membytes;
|
||||
|
||||
// Leave when already loaded
|
||||
if(this.IsLoaded) return;
|
||||
if(this.IsImageLoaded) return;
|
||||
|
||||
lock(this)
|
||||
{
|
||||
|
@ -85,6 +85,9 @@ namespace CodeImp.DoomBuilder.Data
|
|||
if(bitmap != null) bitmap.Dispose();
|
||||
bitmap = reader.ReadAsBitmap(mem);
|
||||
if(bitmap == null) return;
|
||||
|
||||
// Done
|
||||
mem.Dispose();
|
||||
|
||||
// Get width and height from image
|
||||
width = bitmap.Size.Width;
|
||||
|
|
|
@ -51,13 +51,14 @@ namespace CodeImp.DoomBuilder.Data
|
|||
protected bool usecolorcorrection;
|
||||
|
||||
// Loading
|
||||
private LinkedListNode<ImageData> processticket;
|
||||
private ImageLoadState previewstate;
|
||||
private ImageLoadState imagestate;
|
||||
private volatile ImageLoadState previewstate;
|
||||
private volatile ImageLoadState imagestate;
|
||||
private volatile int previewindex;
|
||||
protected volatile bool loadfailed;
|
||||
|
||||
// References
|
||||
private bool usedinmap;
|
||||
private int references;
|
||||
private volatile bool usedinmap;
|
||||
private volatile int references;
|
||||
|
||||
// GDI bitmap
|
||||
protected Bitmap bitmap;
|
||||
|
@ -76,19 +77,21 @@ namespace CodeImp.DoomBuilder.Data
|
|||
public string Name { get { return name; } }
|
||||
public long LongName { get { return longname; } }
|
||||
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 bool IsPreviewLoaded { get { lock(this) { return (previewstate == ImageLoadState.Ready); } } }
|
||||
public bool IsImageLoaded { get { lock(this) { return (imagestate == ImageLoadState.Ready); } } }
|
||||
public bool IsPreviewLoaded { get { return (previewstate == ImageLoadState.Ready); } }
|
||||
public bool IsImageLoaded { get { return (imagestate == ImageLoadState.Ready); } }
|
||||
public bool LoadFailed { get { return loadfailed; } }
|
||||
public bool IsDisposed { get { return isdisposed; } }
|
||||
internal ImageLoadState ImageState { get { return imagestate; } set { imagestate = value; } }
|
||||
internal ImageLoadState PreviewState { get { return previewstate; } set { previewstate = value; } }
|
||||
internal LinkedListNode<ImageData> ProcessTicket { get { return processticket; } set { processticket = value; } }
|
||||
internal bool IsReferenced { get { return (references > 0) || usedinmap; } }
|
||||
internal bool UsedInMap { get { return usedinmap; } set { usedinmap = value; } }
|
||||
public ImageLoadState ImageState { get { return imagestate; } internal set { imagestate = value; } }
|
||||
public ImageLoadState PreviewState { get { return previewstate; } internal set { previewstate = value; } }
|
||||
public bool IsReferenced { get { return (references > 0) || usedinmap; } }
|
||||
public bool UsedInMap { get { return usedinmap; } }
|
||||
public int MipMapLevels { get { return mipmaplevels; } set { mipmaplevels = value; } }
|
||||
public int Width { get { return width; } }
|
||||
public int Height { get { return height; } }
|
||||
internal int PreviewIndex { get { return previewindex; } set { previewindex = value; } }
|
||||
public float ScaledWidth { get { return scaledwidth; } }
|
||||
public float ScaledHeight { get { return scaledheight; } }
|
||||
|
||||
|
@ -134,10 +137,21 @@ namespace CodeImp.DoomBuilder.Data
|
|||
|
||||
#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
|
||||
public void AddReference()
|
||||
{
|
||||
references++;
|
||||
if(references == 1) General.Map.Data.ProcessImage(this);
|
||||
}
|
||||
|
||||
// This removes a reference
|
||||
|
@ -145,6 +159,7 @@ namespace CodeImp.DoomBuilder.Data
|
|||
{
|
||||
references--;
|
||||
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
|
||||
|
@ -172,28 +187,42 @@ namespace CodeImp.DoomBuilder.Data
|
|||
|
||||
lock(this)
|
||||
{
|
||||
// This applies brightness correction on the image
|
||||
if((bitmap != null) && usecolorcorrection)
|
||||
// Bitmap loaded successfully?
|
||||
if(bitmap != null)
|
||||
{
|
||||
try
|
||||
// This applies brightness correction on the image
|
||||
if(usecolorcorrection)
|
||||
{
|
||||
// Try locking the bitmap
|
||||
bmpdata = bitmap.LockBits(new Rectangle(0, 0, bitmap.Size.Width, bitmap.Size.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
General.WriteLogLine("ERROR: Cannot lock image '" + name + "' for color correction. " + e.GetType().Name + ": " + e.Message);
|
||||
}
|
||||
|
||||
// Bitmap locked?
|
||||
if(bmpdata != null)
|
||||
{
|
||||
// Apply color correction
|
||||
PixelColor* pixels = (PixelColor*)(bmpdata.Scan0.ToPointer());
|
||||
General.Colors.ApplColorCorrection(pixels, bmpdata.Width * bmpdata.Height);
|
||||
bitmap.UnlockBits(bmpdata);
|
||||
try
|
||||
{
|
||||
// Try locking the bitmap
|
||||
bmpdata = bitmap.LockBits(new Rectangle(0, 0, bitmap.Size.Width, bitmap.Size.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
General.WriteLogLine("ERROR: Cannot lock image '" + name + "' for color correction. " + e.GetType().Name + ": " + e.Message);
|
||||
}
|
||||
|
||||
// Bitmap locked?
|
||||
if(bmpdata != null)
|
||||
{
|
||||
// Apply color correction
|
||||
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
|
||||
imagestate = ImageLoadState.Ready;
|
||||
|
@ -208,14 +237,18 @@ namespace CodeImp.DoomBuilder.Data
|
|||
lock(this)
|
||||
{
|
||||
// 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
|
||||
memstream = new MemoryStream();
|
||||
bitmap.Save(memstream, ImageFormat.Bmp);
|
||||
img.Save(memstream, ImageFormat.Bmp);
|
||||
memstream.Seek(0, SeekOrigin.Begin);
|
||||
texture = Texture.FromStream(General.Map.Graphics.Device, memstream, (int)memstream.Length, bitmap.Size.Width, bitmap.Size.Height, mipmaplevels,
|
||||
Usage.None, Format.Unknown, Pool.Managed, Filter.Box, Filter.Box, 0);
|
||||
texture = Texture.FromStream(General.Map.Graphics.Device, memstream, (int)memstream.Length,
|
||||
img.Size.Width, img.Size.Height, mipmaplevels, Usage.None, Format.Unknown,
|
||||
Pool.Managed, Filter.Box, Filter.Box, 0);
|
||||
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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ using System.Windows.Forms;
|
|||
|
||||
namespace CodeImp.DoomBuilder.Data
|
||||
{
|
||||
internal enum ImageLoadState : int
|
||||
public enum ImageLoadState : int
|
||||
{
|
||||
None,
|
||||
Loading,
|
||||
|
|
|
@ -53,7 +53,6 @@ namespace CodeImp.DoomBuilder.Data
|
|||
|
||||
// Dont do anything
|
||||
public override void LoadImage() { bitmap = CodeImp.DoomBuilder.Properties.Resources.UnknownImage; }
|
||||
internal override void CreatePixelData() { }
|
||||
internal override void CreateTexture() { }
|
||||
|
||||
#endregion
|
||||
|
|
|
@ -26,25 +26,26 @@ using System.Drawing.Imaging;
|
|||
using CodeImp.DoomBuilder.Rendering;
|
||||
using CodeImp.DoomBuilder.IO;
|
||||
using System.IO;
|
||||
using System.Drawing.Drawing2D;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace CodeImp.DoomBuilder.Data
|
||||
{
|
||||
internal class PreviewManager : IDisposable
|
||||
public class PreviewManager
|
||||
{
|
||||
#region ================== Constants
|
||||
|
||||
// Image format
|
||||
private const PixelFormat IMAGE_FORMAT = PixelFormat.Format16bppArgb1555;
|
||||
private const PixelFormat IMAGE_FORMAT = PixelFormat.Format32bppArgb;
|
||||
|
||||
// Dimensions of a single preview image
|
||||
private const int IMAGE_WIDTH = 64;
|
||||
private const int IMAGE_HEIGHT = 64;
|
||||
internal const int IMAGE_WIDTH = 64;
|
||||
internal const int IMAGE_HEIGHT = 64;
|
||||
|
||||
// How many previews on a single atlas?
|
||||
private const int PREVIEWS_X = 8;
|
||||
private const int PREVIEWS_Y = 8;
|
||||
private const int PREVIEWS_X = 16;
|
||||
private const int PREVIEWS_Y = 16;
|
||||
|
||||
#endregion
|
||||
|
||||
|
@ -56,6 +57,9 @@ namespace CodeImp.DoomBuilder.Data
|
|||
// Next preview index
|
||||
private int nextpreviewindex;
|
||||
|
||||
// Processing
|
||||
private Queue<ImageData> imageque;
|
||||
|
||||
// Disposing
|
||||
private bool isdisposed = false;
|
||||
|
||||
|
@ -63,18 +67,32 @@ namespace CodeImp.DoomBuilder.Data
|
|||
|
||||
#region ================== Properties
|
||||
|
||||
// Constants
|
||||
public int ImageWidth { get { return IMAGE_WIDTH; } }
|
||||
public int ImageHeight { get { return IMAGE_HEIGHT; } }
|
||||
|
||||
// Disposing
|
||||
public bool IsDisposed { get { return isdisposed; } }
|
||||
|
||||
internal bool IsDisposed { get { return isdisposed; } }
|
||||
|
||||
// Loading
|
||||
internal bool IsLoading
|
||||
{
|
||||
get
|
||||
{
|
||||
return (imageque.Count > 0);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Constructor / Disposer
|
||||
|
||||
// Constructor
|
||||
public PreviewManager()
|
||||
internal PreviewManager()
|
||||
{
|
||||
// Initialize
|
||||
atlases = new List<Bitmap>();
|
||||
imageque = new Queue<ImageData>();
|
||||
nextpreviewindex = 0;
|
||||
|
||||
// We have no destructor
|
||||
|
@ -82,7 +100,7 @@ namespace CodeImp.DoomBuilder.Data
|
|||
}
|
||||
|
||||
// Disposer
|
||||
public void Dispose()
|
||||
internal void Dispose()
|
||||
{
|
||||
// Not already disposed?
|
||||
if(!isdisposed)
|
||||
|
@ -97,8 +115,8 @@ namespace CodeImp.DoomBuilder.Data
|
|||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Calculations
|
||||
|
||||
#region ================== Private Methods
|
||||
|
||||
// Returns atlas index for the given preview index
|
||||
private int GetAtlasIndex(int previewindex)
|
||||
|
@ -119,35 +137,165 @@ namespace CodeImp.DoomBuilder.Data
|
|||
int localindex = previewindex - GetAtlasIndex(previewindex) * (PREVIEWS_X * PREVIEWS_Y);
|
||||
return localindex / PREVIEWS_X;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Loading
|
||||
|
||||
// This makes a new atlas
|
||||
private void MakeNewAtlas()
|
||||
{
|
||||
Bitmap b = new Bitmap(IMAGE_WIDTH * PREVIEWS_X, IMAGE_HEIGHT * PREVIEWS_Y, IMAGE_FORMAT);
|
||||
atlases.Add(b);
|
||||
lock(atlases)
|
||||
{
|
||||
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
|
||||
private void MakeImagePreview(Image img)
|
||||
private void MakeImagePreview(ImageData img)
|
||||
{
|
||||
// Do we have to make a new atlas?
|
||||
if(GetAtlasIndex(nextpreviewindex) > (atlases.Count - 1)) MakeNewAtlas();
|
||||
Bitmap atlas;
|
||||
|
||||
// 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
|
||||
// Return true when we have more work to do, so that the
|
||||
// thread will not wait too long before calling again
|
||||
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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -75,7 +75,7 @@ namespace CodeImp.DoomBuilder.Data
|
|||
byte[] membytes;
|
||||
|
||||
// Checks
|
||||
if(this.IsLoaded) return;
|
||||
if(this.IsImageLoaded) return;
|
||||
|
||||
lock(this)
|
||||
{
|
||||
|
@ -102,6 +102,9 @@ namespace CodeImp.DoomBuilder.Data
|
|||
mem.Seek(0, SeekOrigin.Begin);
|
||||
bitmap = reader.ReadAsBitmap(mem);
|
||||
if(bitmap == null) return;
|
||||
|
||||
// Done
|
||||
mem.Dispose();
|
||||
}
|
||||
|
||||
// Pass on to base
|
||||
|
|
|
@ -58,7 +58,7 @@ namespace CodeImp.DoomBuilder.Data
|
|||
byte[] membytes;
|
||||
|
||||
// Leave when already loaded
|
||||
if(this.IsLoaded) return;
|
||||
if(this.IsImageLoaded) return;
|
||||
|
||||
lock(this)
|
||||
{
|
||||
|
@ -86,6 +86,9 @@ namespace CodeImp.DoomBuilder.Data
|
|||
if(bitmap != null) bitmap.Dispose();
|
||||
bitmap = reader.ReadAsBitmap(mem);
|
||||
if(bitmap == null) return;
|
||||
|
||||
// Done
|
||||
mem.Dispose();
|
||||
|
||||
// Get width and height from image
|
||||
width = bitmap.Size.Width;
|
||||
|
|
|
@ -81,10 +81,9 @@ namespace CodeImp.DoomBuilder.Data
|
|||
PixelColor* pixels;
|
||||
Stream patchdata;
|
||||
byte[] membytes;
|
||||
bool failed = false;
|
||||
|
||||
// Checks
|
||||
if(this.IsLoaded) return;
|
||||
if(this.IsImageLoaded) return;
|
||||
if((width == 0) || (height == 0)) return;
|
||||
|
||||
lock(this)
|
||||
|
@ -125,14 +124,23 @@ namespace CodeImp.DoomBuilder.Data
|
|||
{
|
||||
// Data is in an unknown format!
|
||||
General.WriteLogLine("WARNING: Patch lump '" + p.lumpname + "' data format could not be read, while loading texture '" + this.Name + "'!");
|
||||
failed = true;
|
||||
loadfailed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Draw the patch
|
||||
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
|
||||
{
|
||||
|
@ -144,11 +152,11 @@ namespace CodeImp.DoomBuilder.Data
|
|||
// Done
|
||||
bitmap.UnlockBits(bitmapdata);
|
||||
|
||||
// When failed, use the error picture
|
||||
if(failed)
|
||||
// Dispose bitmap if load failed
|
||||
if(loadfailed && (bitmap != null))
|
||||
{
|
||||
bitmap.Dispose();
|
||||
bitmap = UnknownImageReader.ReadAsBitmap();
|
||||
bitmap = null;
|
||||
}
|
||||
|
||||
// Pass on to base
|
||||
|
|
|
@ -38,6 +38,7 @@ using System.Drawing;
|
|||
using CodeImp.DoomBuilder.Plugins;
|
||||
using CodeImp.DoomBuilder.Types;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Threading;
|
||||
|
||||
#endregion
|
||||
|
||||
|
@ -66,26 +67,6 @@ namespace CodeImp.DoomBuilder
|
|||
|
||||
#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
|
||||
internal const int CB_SETITEMHEIGHT = 0x153;
|
||||
|
||||
|
@ -461,6 +442,9 @@ namespace CodeImp.DoomBuilder
|
|||
// Hook to DLL loading failure event
|
||||
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
|
||||
|
||||
// Set current thread name
|
||||
Thread.CurrentThread.Name = "Main Application";
|
||||
|
||||
// Get a reference to this assembly
|
||||
thisasm = Assembly.GetExecutingAssembly();
|
||||
thisversion = thisasm.GetName().Version;
|
||||
|
|
|
@ -329,7 +329,10 @@ namespace CodeImp.DoomBuilder
|
|||
data = new DataManager();
|
||||
maplocation = new DataLocation(DataLocation.RESOURCE_WAD, filepathname, false, false);
|
||||
data.Load(configinfo.Resources, options.Resources, maplocation);
|
||||
|
||||
|
||||
// Update the used textures
|
||||
General.Map.Data.UpdateUsedTextures();
|
||||
|
||||
// Bind any methods
|
||||
General.Actions.BindMethods(this);
|
||||
|
||||
|
@ -1004,6 +1007,7 @@ namespace CodeImp.DoomBuilder
|
|||
config = null;
|
||||
configinfo = null;
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
|
||||
// Reload game configuration
|
||||
General.WriteLogLine("Reloading game configuration...");
|
||||
|
@ -1016,6 +1020,9 @@ namespace CodeImp.DoomBuilder
|
|||
data = new DataManager();
|
||||
maplocation = new DataLocation(DataLocation.RESOURCE_WAD, filepathname, false, false);
|
||||
data.Load(configinfo.Resources, options.Resources, maplocation);
|
||||
|
||||
// Update the used textures
|
||||
General.Map.Data.UpdateUsedTextures();
|
||||
|
||||
// Apply new settings to map elements
|
||||
map.UpdateConfiguration();
|
||||
|
|
|
@ -120,7 +120,7 @@ namespace CodeImp.DoomBuilder.IO
|
|||
// Failed loading picture
|
||||
bmp = null;
|
||||
}
|
||||
|
||||
|
||||
// Return result
|
||||
return bmp;
|
||||
}
|
||||
|
|
|
@ -75,33 +75,40 @@ namespace CodeImp.DoomBuilder.IO
|
|||
|
||||
// Get bitmap
|
||||
bmp = ReadAsBitmap(stream);
|
||||
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++)
|
||||
if(bmp != null)
|
||||
{
|
||||
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?
|
||||
if(pixels[oy * width + ox].a > 0.5f)
|
||||
for(oy = 0; oy < height; oy++)
|
||||
{
|
||||
// Calculate target pixel and copy when within bounds
|
||||
tx = x + ox;
|
||||
ty = y + oy;
|
||||
if((tx >= 0) && (tx < targetwidth) && (ty >= 0) && (ty < targetheight))
|
||||
target[ty * targetwidth + tx] = pixels[oy * width + ox];
|
||||
// Copy this pixel?
|
||||
if(pixels[oy * width + ox].a > 0.5f)
|
||||
{
|
||||
// Calculate target pixel and copy when within bounds
|
||||
tx = x + ox;
|
||||
ty = y + oy;
|
||||
if((tx >= 0) && (tx < targetwidth) && (ty >= 0) && (ty < targetheight))
|
||||
target[ty * targetwidth + tx] = pixels[oy * width + ox];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Done
|
||||
bmp.UnlockBits(bmpdata);
|
||||
bmp.Dispose();
|
||||
// Done
|
||||
bmp.UnlockBits(bmpdata);
|
||||
bmp.Dispose();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidDataException();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
|
|
@ -51,13 +51,13 @@ namespace CodeImp.DoomBuilder.IO
|
|||
// This reads the image and returns a Bitmap
|
||||
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
|
||||
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
|
||||
|
|
|
@ -112,7 +112,7 @@ namespace CodeImp.DoomBuilder.IO
|
|||
if(writer != null) writer.Close();
|
||||
if(reader != null) reader.Close();
|
||||
if(file != null) file.Dispose();
|
||||
|
||||
|
||||
// Done
|
||||
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 {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("File", resourceCulture);
|
||||
|
|
|
@ -220,4 +220,7 @@
|
|||
<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>
|
||||
</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>
|
|
@ -178,7 +178,7 @@ namespace CodeImp.DoomBuilder.Rendering
|
|||
CreateAssistColors();
|
||||
|
||||
// Create color correction table
|
||||
General.Colors.CreateCorrectionTable();
|
||||
CreateCorrectionTable();
|
||||
|
||||
// We have no destructor
|
||||
GC.SuppressFinalize(this);
|
||||
|
|
|
@ -32,31 +32,20 @@ namespace CodeImp.DoomBuilder.Rendering
|
|||
{
|
||||
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
|
||||
|
||||
private int width;
|
||||
private int height;
|
||||
private uint memorysize;
|
||||
private int memorysize;
|
||||
private PixelColor* memory;
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Properties
|
||||
|
||||
public int Width { get { return width; } }
|
||||
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* Pointer { get { return memory; } }
|
||||
|
||||
|
@ -69,12 +58,12 @@ namespace CodeImp.DoomBuilder.Rendering
|
|||
{
|
||||
// Check input
|
||||
if((width <= 0) || (height <= 0)) throw new ArgumentException("Cannot allocate a memory block of zero size!");
|
||||
|
||||
|
||||
// Initialize
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.memorysize = (uint)width * (uint)height * (uint)sizeof(PixelColor);
|
||||
this.memory = (PixelColor*)VirtualAlloc(IntPtr.Zero, new UIntPtr(memorysize), General.MEM_COMMIT, General.PAGE_READWRITE);
|
||||
this.memorysize = width * height * sizeof(PixelColor);
|
||||
this.memory = (PixelColor*)Marshal.AllocCoTaskMem(memorysize);
|
||||
if(this.memory == (PixelColor*)0) throw new OutOfMemoryException();
|
||||
GC.AddMemoryPressure(memorysize);
|
||||
}
|
||||
|
@ -83,7 +72,7 @@ namespace CodeImp.DoomBuilder.Rendering
|
|||
~PixelColorBlock()
|
||||
{
|
||||
// Terminate
|
||||
VirtualFree((void*)memory, new UIntPtr(memorysize), General.MEM_RELEASE);
|
||||
Marshal.FreeCoTaskMem(new IntPtr(memory));
|
||||
GC.RemoveMemoryPressure(memorysize);
|
||||
memorysize = 0;
|
||||
}
|
||||
|
|
|
@ -1080,7 +1080,7 @@ namespace CodeImp.DoomBuilder.Rendering
|
|||
if(texture != null)
|
||||
{
|
||||
// Make sure the texture is loaded
|
||||
if(!texture.IsLoaded) texture.LoadImage();
|
||||
if(!texture.IsImageLoaded) texture.LoadImage();
|
||||
if(texture.Texture == null) texture.CreateTexture();
|
||||
t = texture.Texture;
|
||||
}
|
||||
|
|
|
@ -136,9 +136,6 @@ namespace CodeImp.DoomBuilder.Rendering
|
|||
|
||||
// Make the billboard matrix
|
||||
billboard = Matrix.RotationYawPitchRoll(0f, anglexy, anglez - Angle2D.PIHALF);
|
||||
|
||||
// Apply matrices
|
||||
ApplyMatrices();
|
||||
}
|
||||
|
||||
// This applies the matrices
|
||||
|
@ -168,6 +165,9 @@ namespace CodeImp.DoomBuilder.Rendering
|
|||
graphics.Device.SetRenderState(RenderState.SourceBlend, Blend.SourceAlpha);
|
||||
graphics.Device.SetRenderState(RenderState.DestinationBlend, Blend.InverseSourceAlpha);
|
||||
graphics.Device.SetRenderState(RenderState.TextureFactor, -1);
|
||||
|
||||
// Matrices
|
||||
ApplyMatrices();
|
||||
|
||||
// Ready
|
||||
return true;
|
||||
|
@ -233,23 +233,28 @@ namespace CodeImp.DoomBuilder.Rendering
|
|||
// Go for all geometry in this sector
|
||||
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?
|
||||
if(g.Texture != lasttexture)
|
||||
if(curtexture != lasttexture)
|
||||
{
|
||||
// Now using this texture
|
||||
lasttexture = g.Texture;
|
||||
if(lasttexture != null)
|
||||
{
|
||||
// Load image and make texture
|
||||
if(!lasttexture.IsLoaded) lasttexture.LoadImage();
|
||||
if((lasttexture.Texture == null) || lasttexture.Texture.Disposed)
|
||||
lasttexture.CreateTexture();
|
||||
lasttexture = curtexture;
|
||||
|
||||
// Apply texture
|
||||
graphics.Device.SetTexture(0, lasttexture.Texture);
|
||||
graphics.Shaders.World3D.Texture1 = lasttexture.Texture;
|
||||
graphics.Shaders.World3D.ApplySettings();
|
||||
}
|
||||
// Create Direct3D texture if still needed
|
||||
if((curtexture.Texture == null) || curtexture.Texture.Disposed)
|
||||
curtexture.CreateTexture();
|
||||
|
||||
// Apply texture
|
||||
graphics.Device.SetTexture(0, curtexture.Texture);
|
||||
graphics.Shaders.World3D.Texture1 = curtexture.Texture;
|
||||
graphics.Shaders.World3D.ApplySettings();
|
||||
}
|
||||
|
||||
// Render it!
|
||||
|
|
|
@ -139,7 +139,7 @@ namespace CodeImp.DoomBuilder.Rendering
|
|||
geolist.Sort();
|
||||
|
||||
// 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?
|
||||
if(numverts > 0)
|
||||
|
@ -152,7 +152,7 @@ namespace CodeImp.DoomBuilder.Rendering
|
|||
bufferstream = geobuffer.Lock(0, WorldVertex.Stride * numverts, LockFlags.Discard);
|
||||
foreach(VisualGeometry g in geolist)
|
||||
{
|
||||
if(g.Vertices.Length > 0)
|
||||
if((g.Vertices != null) && (g.Vertices.Length > 0))
|
||||
{
|
||||
bufferstream.WriteRange<WorldVertex>(g.Vertices);
|
||||
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
|
||||
public FlatBrowserForm()
|
||||
{
|
||||
Dictionary<long, long> useditems = new Dictionary<long,long>();
|
||||
Cursor.Current = Cursors.WaitCursor;
|
||||
|
||||
// Initialize
|
||||
InitializeComponent();
|
||||
|
@ -57,43 +57,15 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
ListViewGroup used = browser.AddGroup("Used Flats");
|
||||
ListViewGroup avail = browser.AddGroup("Available Flats");
|
||||
|
||||
// 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 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);
|
||||
}
|
||||
}
|
||||
// Update the used textures
|
||||
General.Map.Data.UpdateUsedTextures();
|
||||
|
||||
// Start adding
|
||||
browser.BeginAdding();
|
||||
|
||||
// Add all used flats
|
||||
foreach(ImageData img in General.Map.Data.Flats)
|
||||
if(useditems.ContainsKey(img.LongName))
|
||||
browser.Add(img.Name, img, img, used);
|
||||
if(img.UsedInMap) browser.Add(img.Name, img, img, used);
|
||||
|
||||
// Add all available flats
|
||||
foreach(ImageData img in General.Map.Data.Flats)
|
||||
|
@ -136,6 +108,7 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
{
|
||||
// Focus the textbox
|
||||
browser.FocusTextbox();
|
||||
Cursor.Current = Cursors.Default;
|
||||
}
|
||||
|
||||
// Loading
|
||||
|
|
|
@ -93,7 +93,7 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
// Set this texture as background
|
||||
backgroundname = result;
|
||||
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
|
||||
backgroundname = result;
|
||||
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);
|
||||
}
|
||||
|
||||
// Update the used textures
|
||||
General.Map.Data.UpdateUsedTextures();
|
||||
|
||||
// Done
|
||||
General.Map.IsChanged = true;
|
||||
this.DialogResult = DialogResult.OK;
|
||||
|
|
|
@ -150,7 +150,10 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
// Custom fields
|
||||
fieldslist.Apply(s.Fields);
|
||||
}
|
||||
|
||||
|
||||
// Update the used textures
|
||||
General.Map.Data.UpdateUsedTextures();
|
||||
|
||||
// Done
|
||||
General.Map.IsChanged = true;
|
||||
this.DialogResult = DialogResult.OK;
|
||||
|
|
|
@ -47,7 +47,7 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
// Constructor
|
||||
public TextureBrowserForm()
|
||||
{
|
||||
Dictionary<long, long> useditems = new Dictionary<long,long>();
|
||||
Cursor.Current = Cursors.WaitCursor;
|
||||
|
||||
// Initialize
|
||||
InitializeComponent();
|
||||
|
@ -57,36 +57,9 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
ListViewGroup used = browser.AddGroup("Used Textures");
|
||||
ListViewGroup avail = browser.AddGroup("Available Textures");
|
||||
|
||||
// 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);
|
||||
// Update the used textures
|
||||
General.Map.Data.UpdateUsedTextures();
|
||||
|
||||
// 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
|
||||
browser.BeginAdding();
|
||||
|
||||
|
@ -94,17 +67,12 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
foreach(ImageData img in General.Map.Data.Textures)
|
||||
{
|
||||
browser.Add(img.Name, img, img, avail);
|
||||
img.Temporary = true;
|
||||
}
|
||||
|
||||
|
||||
// Add all used textures and mark the images for permanent loading
|
||||
foreach(ImageData img in General.Map.Data.Textures)
|
||||
{
|
||||
if(useditems.ContainsKey(img.LongName))
|
||||
{
|
||||
browser.Add(img.Name, img, img, used);
|
||||
img.Temporary = false;
|
||||
}
|
||||
if(img.UsedInMap) browser.Add(img.Name, img, img, used);
|
||||
}
|
||||
|
||||
// Done adding
|
||||
|
@ -144,6 +112,7 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
{
|
||||
// Focus the textbox
|
||||
browser.FocusTextbox();
|
||||
Cursor.Current = Cursors.Default;
|
||||
}
|
||||
|
||||
// Loading
|
||||
|
|
|
@ -310,7 +310,7 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
}
|
||||
|
||||
// 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