- change a lot in the resources system

- fixed memory leak in PixelColorBlock
- several small changes and bugfixes
This commit is contained in:
codeimp 2008-09-28 21:20:56 +00:00
parent 2784090aca
commit 1dad4b68c6
51 changed files with 712 additions and 407 deletions

BIN
Resources/Failed.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

BIN
Resources/Hourglass3D.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 406 B

View file

@ -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(); }

View file

@ -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" />

View file

@ -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()
{ {

View file

@ -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;

View file

@ -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;

View file

@ -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
{ {

View file

@ -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
{ {

View file

@ -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
{ {

View file

@ -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();
} }
} }

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -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);

View file

@ -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
} }
} }

View file

@ -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?

View file

@ -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();

View file

@ -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();
} }
} }

View file

@ -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)

View file

@ -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
} }
} }

View file

@ -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)
{ {

View file

@ -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;

View file

@ -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
} }
} }

View file

@ -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,

View file

@ -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

View file

@ -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
} }
} }

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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;

View file

@ -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();

View file

@ -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;
} }

View file

@ -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

View file

@ -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

View file

@ -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;
} }

View file

@ -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);

View file

@ -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>

View file

@ -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);

View file

@ -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;
} }

View file

@ -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;
} }

View file

@ -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!

View file

@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 406 B

View file

@ -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

View file

@ -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());
} }
} }

View file

@ -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;

View file

@ -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;

View file

@ -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

View file

@ -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());
} }
} }