2007-10-01 20:57:41 +00:00
#region = = = = = = = = = = = = = = = = = = Copyright ( c ) 2007 Pascal vd Heiden
/ *
* Copyright ( c ) 2007 Pascal vd Heiden , www . codeimp . com
* This program is released under GNU General Public License
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* /
#endregion
#region = = = = = = = = = = = = = = = = = = Namespaces
using System ;
using System.Collections ;
using System.Collections.Generic ;
using System.Globalization ;
using System.Text ;
using System.Drawing ;
using System.Drawing.Imaging ;
using System.IO ;
2007-10-07 22:21:47 +00:00
using CodeImp.DoomBuilder.IO ;
2007-10-14 21:31:45 +00:00
using System.Windows.Forms ;
2007-10-26 13:17:20 +00:00
using SlimDX.Direct3D9 ;
2007-10-26 15:28:32 +00:00
using CodeImp.DoomBuilder.Config ;
using System.Threading ;
2008-09-28 21:20:56 +00:00
using CodeImp.DoomBuilder.Map ;
2008-11-18 13:05:04 +00:00
using CodeImp.DoomBuilder.Windows ;
2007-10-01 20:57:41 +00:00
#endregion
namespace CodeImp.DoomBuilder.Data
{
2008-01-02 21:49:43 +00:00
public sealed class DataManager
2007-10-01 20:57:41 +00:00
{
#region = = = = = = = = = = = = = = = = = = Constants
#endregion
#region = = = = = = = = = = = = = = = = = = Variables
2008-10-01 14:17:52 +00:00
2007-10-04 18:16:05 +00:00
// Data containers
2007-10-07 22:21:47 +00:00
private List < DataReader > containers ;
2008-10-01 14:17:52 +00:00
2007-10-07 22:21:47 +00:00
// Palette
private Playpal palette ;
2008-10-01 14:17:52 +00:00
// Textures, Flats and Sprites
2007-10-07 22:21:47 +00:00
private Dictionary < long , ImageData > textures ;
2007-12-27 01:24:11 +00:00
private List < string > texturenames ;
2007-10-07 22:21:47 +00:00
private Dictionary < long , ImageData > flats ;
2007-12-27 01:24:11 +00:00
private List < string > flatnames ;
2007-10-07 22:21:47 +00:00
private Dictionary < long , ImageData > sprites ;
2008-10-01 14:17:52 +00:00
private List < MatchingTextureSet > texturesets ;
private OthersTextureSet othertextures ;
2008-09-26 15:15:56 +00:00
2007-10-26 15:28:32 +00:00
// Background loading
2008-09-26 15:15:56 +00:00
private Queue < ImageData > imageque ;
2007-10-26 15:28:32 +00:00
private Thread backgroundloader ;
2008-09-28 21:20:56 +00:00
private volatile bool updatedusedtextures ;
2007-10-26 15:28:32 +00:00
2008-09-25 18:42:45 +00:00
// Image previews
private PreviewManager previews ;
2008-01-13 21:23:59 +00:00
// Special images
private ImageData missingtexture3d ;
2008-09-28 21:20:56 +00:00
private ImageData hourglass3d ;
2008-01-13 21:23:59 +00:00
2008-10-15 17:26:59 +00:00
// Used images
private Dictionary < long , long > usedimages ;
2007-10-01 20:57:41 +00:00
// Disposing
private bool isdisposed = false ;
#endregion
#region = = = = = = = = = = = = = = = = = = Properties
2007-10-08 14:29:31 +00:00
public Playpal Palette { get { return palette ; } }
2008-09-28 21:20:56 +00:00
public PreviewManager Previews { get { return previews ; } }
2007-10-31 20:34:09 +00:00
public ICollection < ImageData > Textures { get { return textures . Values ; } }
public ICollection < ImageData > Flats { get { return flats . Values ; } }
2007-12-27 01:24:11 +00:00
public List < string > TextureNames { get { return texturenames ; } }
public List < string > FlatNames { get { return flatnames ; } }
2007-10-01 20:57:41 +00:00
public bool IsDisposed { get { return isdisposed ; } }
2008-01-13 21:23:59 +00:00
public ImageData MissingTexture3D { get { return missingtexture3d ; } }
2008-09-28 21:20:56 +00:00
public ImageData Hourglass3D { get { return hourglass3d ; } }
2008-10-01 14:17:52 +00:00
internal ICollection < MatchingTextureSet > TextureSets { get { return texturesets ; } }
internal OthersTextureSet OthersTextureSet { get { return othertextures ; } }
2007-10-26 19:06:59 +00:00
2008-05-05 14:22:36 +00:00
public bool IsLoading
{
get
{
2008-09-28 21:20:56 +00:00
if ( imageque ! = null )
2008-05-05 14:22:36 +00:00
{
2008-09-28 21:20:56 +00:00
return ( backgroundloader ! = null ) & & backgroundloader . IsAlive & & ( ( imageque . Count > 0 ) | | previews . IsLoading ) ;
2008-05-05 14:22:36 +00:00
}
else
{
return false ;
}
}
}
2007-10-01 20:57:41 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Constructor / Disposer
// Constructor
2008-01-02 21:49:43 +00:00
internal DataManager ( )
2007-10-01 20:57:41 +00:00
{
// We have no destructor
GC . SuppressFinalize ( this ) ;
2008-01-13 21:23:59 +00:00
// Load special images
missingtexture3d = new ResourceImage ( "MissingTexture3D.png" ) ;
missingtexture3d . LoadImage ( ) ;
2008-09-28 21:20:56 +00:00
hourglass3d = new ResourceImage ( "Hourglass3D.png" ) ;
hourglass3d . LoadImage ( ) ;
2007-10-01 20:57:41 +00:00
}
2007-10-04 18:16:05 +00:00
// Disposer
2008-01-02 21:49:43 +00:00
internal void Dispose ( )
2007-10-01 20:57:41 +00:00
{
// Not already disposed?
if ( ! isdisposed )
{
// Clean up
2007-10-05 11:17:58 +00:00
Unload ( ) ;
2008-01-13 21:23:59 +00:00
missingtexture3d . Dispose ( ) ;
missingtexture3d = null ;
2007-10-05 11:17:58 +00:00
2007-10-01 20:57:41 +00:00
// Done
isdisposed = true ;
}
}
#endregion
2007-10-04 18:16:05 +00:00
#region = = = = = = = = = = = = = = = = = = Loading / Unloading
2007-10-05 11:17:58 +00:00
// This loads all data resources
2008-01-02 21:49:43 +00:00
internal void Load ( DataLocationList configlist , DataLocationList maplist , DataLocation maplocation )
2007-10-05 11:17:58 +00:00
{
2007-10-07 22:21:47 +00:00
DataLocationList all = DataLocationList . Combined ( configlist , maplist ) ;
2007-10-05 11:17:58 +00:00
all . Add ( maplocation ) ;
Load ( all ) ;
}
// This loads all data resources
2008-01-02 21:49:43 +00:00
internal void Load ( DataLocationList configlist , DataLocationList maplist )
2007-10-05 11:17:58 +00:00
{
2007-10-07 22:21:47 +00:00
DataLocationList all = DataLocationList . Combined ( configlist , maplist ) ;
2007-10-05 11:17:58 +00:00
Load ( all ) ;
}
2007-10-04 18:16:05 +00:00
// This loads all data resources
2008-01-02 21:49:43 +00:00
internal void Load ( DataLocationList locations )
2007-10-04 18:16:05 +00:00
{
2008-05-05 14:22:36 +00:00
int texcount , flatcount , spritecount ;
2007-10-07 22:21:47 +00:00
DataReader c ;
// Create collections
containers = new List < DataReader > ( ) ;
textures = new Dictionary < long , ImageData > ( ) ;
flats = new Dictionary < long , ImageData > ( ) ;
sprites = new Dictionary < long , ImageData > ( ) ;
2007-12-27 01:24:11 +00:00
texturenames = new List < string > ( ) ;
flatnames = new List < string > ( ) ;
2008-09-28 21:20:56 +00:00
imageque = new Queue < ImageData > ( ) ;
2008-09-25 18:42:45 +00:00
previews = new PreviewManager ( ) ;
2008-10-01 14:17:52 +00:00
texturesets = new List < MatchingTextureSet > ( ) ;
2008-10-15 17:26:59 +00:00
usedimages = new Dictionary < long , long > ( ) ;
2008-10-01 14:17:52 +00:00
// Load texture sets
foreach ( DefinedTextureSet ts in General . Map . ConfigSettings . TextureSets )
texturesets . Add ( new MatchingTextureSet ( ts ) ) ;
2008-10-02 18:53:07 +00:00
// Sort the texture sets
texturesets . Sort ( ) ;
2008-10-01 14:17:52 +00:00
// Other textures set
othertextures = new OthersTextureSet ( ) ;
2007-10-04 18:16:05 +00:00
// Go for all locations
foreach ( DataLocation dl in locations )
{
// Nothing chosen yet
c = null ;
2007-10-05 11:17:58 +00:00
2007-10-07 22:21:47 +00:00
// TODO: Make this work more elegant using reflection.
// Make DataLocation.type of type Type and assign the
// types of the desired reader classes.
2007-10-14 21:31:45 +00:00
try
2007-10-04 18:16:05 +00:00
{
2007-10-14 21:31:45 +00:00
// Choose container type
switch ( dl . type )
{
// WAD file container
case DataLocation . RESOURCE_WAD :
c = new WADReader ( dl ) ;
break ;
// Directory container
case DataLocation . RESOURCE_DIRECTORY :
c = new DirectoryReader ( dl ) ;
break ;
2007-10-26 14:16:23 +00:00
// PK3 file container
case DataLocation . RESOURCE_PK3 :
c = new PK3Reader ( dl ) ;
break ;
2007-10-14 21:31:45 +00:00
}
2007-10-04 18:16:05 +00:00
}
2007-10-14 21:31:45 +00:00
catch ( Exception )
{
// Unable to load resource
General . ShowErrorMessage ( "Unable to load resources from location \"" + dl . location + "\". Please make sure the location is accessible and not in use by another program." , MessageBoxButtons . OK ) ;
continue ;
}
2007-10-07 22:21:47 +00:00
// Add container
if ( c ! = null ) containers . Add ( c ) ;
2007-10-04 18:16:05 +00:00
}
2008-10-01 14:17:52 +00:00
2007-10-07 22:21:47 +00:00
// Load stuff
LoadPalette ( ) ;
2008-05-05 14:22:36 +00:00
texcount = LoadTextures ( ) ;
flatcount = LoadFlats ( ) ;
spritecount = LoadSprites ( ) ;
2008-10-01 14:17:52 +00:00
2008-05-05 14:22:36 +00:00
// Sort names
texturenames . Sort ( ) ;
flatnames . Sort ( ) ;
2008-10-01 20:30:29 +00:00
// Update the used textures
General . Map . Data . UpdateUsedTextures ( ) ;
2008-05-05 14:22:36 +00:00
2008-10-01 14:17:52 +00:00
// Add texture names to texture sets
foreach ( KeyValuePair < long , ImageData > img in textures )
{
// Add to all sets where it matches
bool matchfound = false ;
foreach ( MatchingTextureSet ms in texturesets )
matchfound | = ms . AddTexture ( img . Value ) ;
// If not matched in any set, add it to the others
2008-10-01 18:19:53 +00:00
if ( ! matchfound ) othertextures . AddTexture ( img . Value ) ;
2008-10-01 14:17:52 +00:00
}
// Add flat names to texture sets
foreach ( KeyValuePair < long , ImageData > img in flats )
{
// Add to all sets where it matches
bool matchfound = false ;
foreach ( MatchingTextureSet ms in texturesets )
matchfound | = ms . AddFlat ( img . Value ) ;
// If not matched in any set, add it to the others
2008-10-01 18:19:53 +00:00
if ( ! matchfound ) othertextures . AddFlat ( img . Value ) ;
2008-10-01 14:17:52 +00:00
}
2007-10-26 15:28:32 +00:00
// Start background loading
StartBackgroundLoader ( ) ;
2008-10-01 14:17:52 +00:00
2008-05-05 14:22:36 +00:00
// Output info
General . WriteLogLine ( "Loaded " + texcount + " textures, " + flatcount + " flats, " + spritecount + " sprites" ) ;
2007-10-04 18:16:05 +00:00
}
2007-10-01 20:57:41 +00:00
2007-10-04 18:16:05 +00:00
// This unloads all data
2008-01-02 21:49:43 +00:00
internal void Unload ( )
2007-10-04 18:16:05 +00:00
{
2007-10-26 15:28:32 +00:00
// Stop background loader
StopBackgroundLoader ( ) ;
2008-09-25 18:42:45 +00:00
// Dispose preview manager
previews . Dispose ( ) ;
previews = null ;
2007-10-07 22:21:47 +00:00
// Dispose resources
foreach ( KeyValuePair < long , ImageData > i in textures ) i . Value . Dispose ( ) ;
foreach ( KeyValuePair < long , ImageData > i in flats ) i . Value . Dispose ( ) ;
foreach ( KeyValuePair < long , ImageData > i in sprites ) i . Value . Dispose ( ) ;
palette = null ;
2008-10-01 14:17:52 +00:00
2007-10-04 18:16:05 +00:00
// Dispose containers
2007-10-07 22:21:47 +00:00
foreach ( DataReader c in containers ) c . Dispose ( ) ;
2007-10-04 18:16:05 +00:00
containers . Clear ( ) ;
2008-10-01 14:17:52 +00:00
2008-05-05 14:22:36 +00:00
// Trash collections
containers = null ;
textures = null ;
flats = null ;
sprites = null ;
texturenames = null ;
flatnames = null ;
2008-09-28 21:20:56 +00:00
imageque = null ;
2007-10-04 18:16:05 +00:00
}
2008-10-01 14:17:52 +00:00
2007-10-07 22:21:47 +00:00
#endregion
2007-10-04 18:16:05 +00:00
2007-10-07 22:21:47 +00:00
#region = = = = = = = = = = = = = = = = = = Suspend / Resume
2007-10-13 14:05:45 +00:00
// This suspends data resources
2008-01-02 21:49:43 +00:00
internal void Suspend ( )
2007-10-05 11:17:58 +00:00
{
2007-10-26 15:28:32 +00:00
// Stop background loader
StopBackgroundLoader ( ) ;
2007-10-05 11:17:58 +00:00
// Go for all containers
2007-10-07 22:21:47 +00:00
foreach ( DataReader d in containers )
2007-10-05 11:17:58 +00:00
{
2007-10-13 14:05:45 +00:00
// Suspend
General . WriteLogLine ( "Suspended data resource '" + d . Location . location + "'" ) ;
d . Suspend ( ) ;
2007-10-05 11:17:58 +00:00
}
}
2007-10-13 14:05:45 +00:00
// This resumes data resources
2008-01-02 21:49:43 +00:00
internal void Resume ( )
2007-10-05 11:17:58 +00:00
{
// Go for all containers
2007-10-07 22:21:47 +00:00
foreach ( DataReader d in containers )
2007-10-05 11:17:58 +00:00
{
2007-10-14 21:31:45 +00:00
try
{
// Resume
General . WriteLogLine ( "Resumed data resource '" + d . Location . location + "'" ) ;
d . Resume ( ) ;
}
catch ( Exception )
{
// Unable to load resource
General . ShowErrorMessage ( "Unable to load resources from location \"" + d . Location . location + "\". Please make sure the location is accessible and not in use by another program." , MessageBoxButtons . OK ) ;
}
2007-10-05 11:17:58 +00:00
}
2007-10-26 15:28:32 +00:00
// Start background loading
StartBackgroundLoader ( ) ;
2007-10-05 11:17:58 +00:00
}
2007-10-01 20:57:41 +00:00
#endregion
2007-10-07 22:21:47 +00:00
2007-10-26 15:28:32 +00:00
#region = = = = = = = = = = = = = = = = = = Background Loading
2008-10-23 11:23:11 +00:00
2007-10-26 15:28:32 +00:00
// This starts background loading
private void StartBackgroundLoader ( )
{
// If a loader is already running, stop it first
if ( backgroundloader ! = null ) StopBackgroundLoader ( ) ;
2008-02-23 13:12:59 +00:00
2008-05-05 14:22:36 +00:00
// Start a low priority thread to load images in background
General . WriteLogLine ( "Starting background resource loading..." ) ;
backgroundloader = new Thread ( new ThreadStart ( BackgroundLoad ) ) ;
2008-09-28 21:20:56 +00:00
backgroundloader . Name = "Background Loader" ;
2008-05-05 14:22:36 +00:00
backgroundloader . Priority = ThreadPriority . Lowest ;
2008-10-23 11:23:11 +00:00
backgroundloader . IsBackground = true ;
2008-05-05 14:22:36 +00:00
backgroundloader . Start ( ) ;
2007-10-26 15:28:32 +00:00
}
2008-10-23 11:23:11 +00:00
2007-10-26 15:28:32 +00:00
// This stops background loading
private void StopBackgroundLoader ( )
{
2008-09-28 21:20:56 +00:00
ImageData img ;
2008-05-05 14:22:36 +00:00
2007-10-26 15:28:32 +00:00
General . WriteLogLine ( "Stopping background resource loading..." ) ;
2007-10-26 18:04:54 +00:00
if ( backgroundloader ! = null )
{
// Stop the thread and wait for it to end
backgroundloader . Interrupt ( ) ;
backgroundloader . Join ( ) ;
2007-10-26 15:28:32 +00:00
2008-05-05 14:22:36 +00:00
// Reset load states on all images in the list
2008-09-28 21:20:56 +00:00
while ( imageque . Count > 0 )
2008-05-05 14:22:36 +00:00
{
2008-09-28 21:20:56 +00:00
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 ;
}
2008-05-05 14:22:36 +00:00
}
2007-10-26 18:04:54 +00:00
// Done
backgroundloader = null ;
2008-11-18 13:05:04 +00:00
General . SendMessage ( General . MainWindow . Handle , ( int ) MainForm . ThreadMessages . UpdateStatusIcon , 0 , 0 ) ;
2007-10-26 18:04:54 +00:00
}
2007-10-26 15:28:32 +00:00
}
2008-09-26 15:15:56 +00:00
2007-10-26 15:28:32 +00:00
// The background loader
private void BackgroundLoad ( )
{
try
{
2008-05-05 14:22:36 +00:00
do
{
2008-09-28 21:20:56 +00:00
// Do we have to update the used-in-map status?
2008-10-15 17:26:59 +00:00
if ( updatedusedtextures ) BackgroundUpdateUsedTextures ( ) ;
2008-09-28 21:20:56 +00:00
2008-05-05 14:22:36 +00:00
// Get next item
ImageData image = null ;
2008-09-26 15:15:56 +00:00
lock ( imageque )
{
2008-09-28 21:20:56 +00:00
// Fetch next image to process
2008-09-26 15:15:56 +00:00
if ( imageque . Count > 0 ) image = imageque . Dequeue ( ) ;
}
// Any image to process?
if ( image ! = null )
2008-05-05 14:22:36 +00:00
{
2008-09-26 15:15:56 +00:00
// Load this image?
2008-09-28 21:20:56 +00:00
if ( image . IsReferenced & & ( image . ImageState ! = ImageLoadState . Ready ) )
2008-05-05 14:22:36 +00:00
{
2008-09-28 21:20:56 +00:00
image . LoadImage ( ) ;
2008-09-26 15:15:56 +00:00
}
// Unload this image?
2008-09-28 21:20:56 +00:00
if ( ! image . IsReferenced & & ( image . ImageState ! = ImageLoadState . None ) )
2008-09-26 15:15:56 +00:00
{
// Still unreferenced?
2008-09-28 21:20:56 +00:00
image . UnloadImage ( ) ;
2008-05-05 14:22:36 +00:00
}
}
2008-09-26 15:15:56 +00:00
// Doing something?
2008-05-05 14:22:36 +00:00
if ( image ! = null )
{
// Wait a bit and update icon
2008-11-18 13:05:04 +00:00
General . SendMessage ( General . MainWindow . Handle , ( int ) MainForm . ThreadMessages . UpdateStatusIcon , 0 , 0 ) ;
2008-10-08 19:02:35 +00:00
Thread . Sleep ( 0 ) ;
2008-05-05 14:22:36 +00:00
}
else
{
2008-09-26 15:15:56 +00:00
// Process previews only when we don't have images to process
// because these are lower priority than the actual images
if ( previews . BackgroundLoad ( ) )
{
// Wait a bit and update icon
2008-11-18 13:05:04 +00:00
General . SendMessage ( General . MainWindow . Handle , ( int ) MainForm . ThreadMessages . UpdateStatusIcon , 0 , 0 ) ;
2008-10-08 19:02:35 +00:00
Thread . Sleep ( 0 ) ;
2008-09-26 15:15:56 +00:00
}
else
{
// Wait longer to release CPU resources
Thread . Sleep ( 50 ) ;
}
2008-05-05 14:22:36 +00:00
}
}
while ( true ) ;
2007-10-26 15:28:32 +00:00
}
catch ( ThreadInterruptedException )
{
return ;
}
}
2008-09-26 15:15:56 +00:00
2008-05-05 14:22:36 +00:00
// This adds an image for background loading or unloading
2008-09-26 15:15:56 +00:00
internal void ProcessImage ( ImageData img )
2007-10-26 15:28:32 +00:00
{
2008-09-26 15:15:56 +00:00
// Load this image?
if ( ( img . ImageState = = ImageLoadState . None ) & & img . IsReferenced )
{
// Add for loading
img . ImageState = ImageLoadState . Loading ;
lock ( imageque ) { imageque . Enqueue ( img ) ; }
}
2007-10-26 15:28:32 +00:00
2008-09-26 15:15:56 +00:00
// Unload this image?
if ( ( img . ImageState = = ImageLoadState . Ready ) & & ! img . IsReferenced )
2007-10-26 15:28:32 +00:00
{
2008-09-26 15:15:56 +00:00
// Add for unloading
img . ImageState = ImageLoadState . Unloading ;
lock ( imageque ) { imageque . Enqueue ( img ) ; }
2008-05-05 14:22:36 +00:00
}
// Update icon
2008-11-18 13:05:04 +00:00
General . SendMessage ( General . MainWindow . Handle , ( int ) MainForm . ThreadMessages . UpdateStatusIcon , 0 , 0 ) ;
2008-05-05 14:22:36 +00:00
}
2008-09-28 21:20:56 +00:00
// This updates the used-in-map status on all textures and flats
private void BackgroundUpdateUsedTextures ( )
{
2008-10-15 17:26:59 +00:00
lock ( usedimages )
2008-09-28 21:20:56 +00:00
{
2008-10-15 17:26:59 +00:00
// Set used on all textures
foreach ( KeyValuePair < long , ImageData > i in textures )
{
i . Value . SetUsedInMap ( usedimages . ContainsKey ( i . Key ) ) ;
if ( i . Value . IsImageLoaded ! = i . Value . IsReferenced ) ProcessImage ( i . Value ) ;
}
2008-09-28 21:20:56 +00:00
2008-10-15 17:26:59 +00:00
// 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 ( usedimages . ContainsKey ( i . Key ) ) ;
if ( i . Value . IsImageLoaded ! = i . Value . IsReferenced ) ProcessImage ( i . Value ) ;
}
}
2008-09-28 21:20:56 +00:00
2008-10-15 17:26:59 +00:00
// Done
updatedusedtextures = false ;
2008-09-28 21:20:56 +00:00
}
}
2007-10-26 15:28:32 +00:00
#endregion
2007-10-07 22:21:47 +00:00
#region = = = = = = = = = = = = = = = = = = Palette
// This loads the PLAYPAL palette
private void LoadPalette ( )
{
// Go for all opened containers
for ( int i = containers . Count - 1 ; i > = 0 ; i - - )
{
// Load palette
palette = containers [ i ] . LoadPalette ( ) ;
if ( palette ! = null ) break ;
}
2007-12-26 01:14:31 +00:00
// Make empty palette when still no palette found
if ( palette = = null )
{
General . WriteLogLine ( "WARNING: None of the loaded resources define a color palette!" ) ;
palette = new Playpal ( ) ;
}
2007-10-07 22:21:47 +00:00
}
#endregion
#region = = = = = = = = = = = = = = = = = = Textures
// This loads the textures
2008-05-05 14:22:36 +00:00
private int LoadTextures ( )
2007-10-07 22:21:47 +00:00
{
ICollection < ImageData > images ;
2007-10-27 13:59:24 +00:00
PatchNames pnames = new PatchNames ( ) ;
PatchNames newpnames ;
2008-05-05 14:22:36 +00:00
int counter = 0 ;
2008-10-02 18:53:07 +00:00
long firsttexture = 0 ;
2007-10-07 22:21:47 +00:00
// Go for all opened containers
foreach ( DataReader dr in containers )
{
// Load PNAMES info
// Note that pnames is NOT set to null in the loop
// because if a container has no pnames, the pnames
// of the previous (higher) container should be used.
2007-10-27 13:59:24 +00:00
newpnames = dr . LoadPatchNames ( ) ;
if ( newpnames ! = null ) pnames = newpnames ;
// Load textures
images = dr . LoadTextures ( pnames ) ;
if ( images ! = null )
2007-10-07 22:21:47 +00:00
{
2007-10-27 13:59:24 +00:00
// Go for all textures
foreach ( ImageData img in images )
2007-10-07 22:21:47 +00:00
{
2007-10-27 13:59:24 +00:00
// Add or replace in textures list
2007-12-27 01:24:11 +00:00
if ( ! textures . ContainsKey ( img . LongName ) ) texturenames . Add ( img . Name ) ;
2007-10-27 13:59:24 +00:00
textures . Remove ( img . LongName ) ;
textures . Add ( img . LongName , img ) ;
2008-10-02 18:53:07 +00:00
if ( firsttexture = = 0 ) firsttexture = img . LongName ;
2008-05-05 14:22:36 +00:00
counter + + ;
2007-12-27 01:24:11 +00:00
2007-11-04 23:09:21 +00:00
// Also add as flat when using mixed resources
if ( General . Map . Config . MixTexturesFlats )
{
2007-12-27 01:24:11 +00:00
if ( ! flats . ContainsKey ( img . LongName ) ) flatnames . Add ( img . Name ) ;
2007-11-04 23:09:21 +00:00
flats . Remove ( img . LongName ) ;
flats . Add ( img . LongName , img ) ;
}
2008-09-28 21:20:56 +00:00
// Add to preview manager
previews . AddImage ( img ) ;
2007-10-07 22:21:47 +00:00
}
}
}
2008-05-05 14:22:36 +00:00
2008-10-02 18:53:07 +00:00
// The first texture cannot be used, because in the game engine it
// has index 0 which means "no texture", so remove it from the list.
textures . Remove ( firsttexture ) ;
if ( General . Map . Config . MixTexturesFlats ) flats . Remove ( firsttexture ) ;
2008-05-05 14:22:36 +00:00
// Output info
return counter ;
2007-10-07 22:21:47 +00:00
}
// This returns a specific patch stream
2008-01-02 21:49:43 +00:00
internal Stream GetPatchData ( string pname )
2007-10-07 22:21:47 +00:00
{
Stream patch ;
// Go for all opened containers
for ( int i = containers . Count - 1 ; i > = 0 ; i - - )
{
// This contain provides this patch?
patch = containers [ i ] . GetPatchData ( pname ) ;
if ( patch ! = null ) return patch ;
}
// No such patch found
return null ;
}
2007-10-26 13:17:20 +00:00
// This returns an image by string
public ImageData GetTextureImage ( string name )
2007-10-24 17:25:03 +00:00
{
// Get the long name
long longname = Lump . MakeLongName ( name ) ;
2007-10-26 13:17:20 +00:00
return GetTextureImage ( longname ) ;
2007-10-24 17:25:03 +00:00
}
2007-10-26 13:17:20 +00:00
// This returns an image by long
public ImageData GetTextureImage ( long longname )
2007-10-24 17:25:03 +00:00
{
2008-05-05 14:22:36 +00:00
// Does this texture exist?
if ( textures . ContainsKey ( longname ) )
2007-10-24 17:25:03 +00:00
{
2008-05-05 14:22:36 +00:00
// Return texture
return textures [ longname ] ;
}
else
{
// Return null image
return new NullImage ( ) ;
2007-10-24 17:25:03 +00:00
}
}
2007-10-26 15:28:32 +00:00
2008-09-28 21:20:56 +00:00
// BAD! These block while loading the image. That is not
// what our background loading system is for!
/ *
2007-10-26 13:17:20 +00:00
// This returns a bitmap by string
public Bitmap GetTextureBitmap ( string name )
{
ImageData img = GetTextureImage ( name ) ;
img . LoadImage ( ) ;
return img . Bitmap ;
}
// This returns a bitmap by string
public Bitmap GetTextureBitmap ( long longname )
{
ImageData img = GetTextureImage ( longname ) ;
img . LoadImage ( ) ;
return img . Bitmap ;
}
// This returns a texture by string
public Texture GetTextureTexture ( string name )
{
ImageData img = GetTextureImage ( name ) ;
img . LoadImage ( ) ;
img . CreateTexture ( ) ;
return img . Texture ;
}
// This returns a texture by string
public Texture GetTextureTexture ( long longname )
{
ImageData img = GetTextureImage ( longname ) ;
img . LoadImage ( ) ;
img . CreateTexture ( ) ;
return img . Texture ;
}
2008-09-28 21:20:56 +00:00
* /
2007-10-24 17:25:03 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Flats
2007-10-26 13:17:20 +00:00
// This loads the flats
2008-05-05 14:22:36 +00:00
private int LoadFlats ( )
2007-10-26 13:17:20 +00:00
{
ICollection < ImageData > images ;
2008-05-05 14:22:36 +00:00
int counter = 0 ;
2007-10-26 13:17:20 +00:00
// Go for all opened containers
foreach ( DataReader dr in containers )
{
// Load flats
images = dr . LoadFlats ( ) ;
if ( images ! = null )
{
// Go for all flats
foreach ( ImageData img in images )
{
// Add or replace in flats list
2007-12-27 01:24:11 +00:00
if ( ! flats . ContainsKey ( img . LongName ) ) flatnames . Add ( img . Name ) ;
2007-10-26 13:17:20 +00:00
flats . Remove ( img . LongName ) ;
flats . Add ( img . LongName , img ) ;
2008-05-05 14:22:36 +00:00
counter + + ;
2007-11-04 23:09:21 +00:00
// Also add as texture when using mixed resources
if ( General . Map . Config . MixTexturesFlats )
{
2007-12-27 01:24:11 +00:00
if ( ! textures . ContainsKey ( img . LongName ) ) texturenames . Add ( img . Name ) ;
2007-11-04 23:09:21 +00:00
textures . Remove ( img . LongName ) ;
textures . Add ( img . LongName , img ) ;
}
2008-09-28 21:20:56 +00:00
// Add to preview manager
previews . AddImage ( img ) ;
2007-10-26 13:17:20 +00:00
}
}
}
2008-05-05 14:22:36 +00:00
// Output info
return counter ;
2007-10-26 13:17:20 +00:00
}
// This returns a specific flat stream
2008-01-02 21:49:43 +00:00
internal Stream GetFlatData ( string pname )
2007-10-26 13:17:20 +00:00
{
Stream flat ;
// Go for all opened containers
for ( int i = containers . Count - 1 ; i > = 0 ; i - - )
{
// This contain provides this flat?
flat = containers [ i ] . GetFlatData ( pname ) ;
if ( flat ! = null ) return flat ;
}
// No such patch found
return null ;
}
// This returns an image by string
public ImageData GetFlatImage ( string name )
2007-10-24 17:25:03 +00:00
{
// Get the long name
long longname = Lump . MakeLongName ( name ) ;
2007-10-26 13:17:20 +00:00
return GetFlatImage ( longname ) ;
2007-10-24 17:25:03 +00:00
}
2007-10-26 13:17:20 +00:00
// This returns an image by long
public ImageData GetFlatImage ( long longname )
2007-10-24 17:25:03 +00:00
{
2008-05-05 14:22:36 +00:00
// Does this flat exist?
if ( flats . ContainsKey ( longname ) )
2007-10-24 17:25:03 +00:00
{
2008-05-05 14:22:36 +00:00
// Return flat
return flats [ longname ] ;
}
else
{
// Return null image
return new NullImage ( ) ;
2007-10-24 17:25:03 +00:00
}
}
2008-09-28 21:20:56 +00:00
// BAD! These block while loading the image. That is not
// what our background loading system is for!
/ *
2007-10-26 13:17:20 +00:00
// This returns a bitmap by string
public Bitmap GetFlatBitmap ( string name )
{
ImageData img = GetFlatImage ( name ) ;
img . LoadImage ( ) ;
return img . Bitmap ;
}
// This returns a bitmap by string
public Bitmap GetFlatBitmap ( long longname )
{
ImageData img = GetFlatImage ( longname ) ;
img . LoadImage ( ) ;
return img . Bitmap ;
}
// This returns a texture by string
public Texture GetFlatTexture ( string name )
{
ImageData img = GetFlatImage ( name ) ;
img . LoadImage ( ) ;
img . CreateTexture ( ) ;
return img . Texture ;
}
// This returns a texture by string
public Texture GetFlatTexture ( long longname )
{
ImageData img = GetFlatImage ( longname ) ;
img . LoadImage ( ) ;
img . CreateTexture ( ) ;
return img . Texture ;
}
2008-09-28 21:20:56 +00:00
* /
2007-10-26 13:17:20 +00:00
2007-10-24 17:25:03 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Sprites
2007-10-26 15:28:32 +00:00
// This loads the sprites
2008-05-05 14:22:36 +00:00
private int LoadSprites ( )
2007-10-26 15:28:32 +00:00
{
Stream spritedata = null ;
SpriteImage image ;
// Go for all things
foreach ( ThingTypeInfo ti in General . Map . Config . Things )
{
// Sprite not added to collection yet?
if ( ! sprites . ContainsKey ( ti . SpriteLongName ) )
{
// Go for all opened containers
for ( int i = containers . Count - 1 ; i > = 0 ; i - - )
{
// This contain provides this sprite?
spritedata = containers [ i ] . GetSpriteData ( ti . Sprite ) ;
if ( spritedata ! = null ) break ;
}
// Found anything?
if ( spritedata ! = null )
{
// Make new sprite image
image = new SpriteImage ( ti . Sprite ) ;
// Add to collection
sprites . Add ( ti . SpriteLongName , image ) ;
2008-09-28 21:20:56 +00:00
// Add to preview manager
previews . AddImage ( image ) ;
2007-10-26 15:28:32 +00:00
}
}
}
2008-05-05 14:22:36 +00:00
// Output info
return sprites . Count ;
2007-10-26 15:28:32 +00:00
}
2007-10-26 13:31:02 +00:00
// This returns an image by long
2007-10-26 13:17:20 +00:00
public ImageData GetSpriteImage ( string name )
2007-10-24 17:25:03 +00:00
{
2007-10-26 13:31:02 +00:00
Stream spritedata = null ;
2007-10-24 17:25:03 +00:00
long longname = Lump . MakeLongName ( name ) ;
2007-10-26 13:31:02 +00:00
SpriteImage image ;
2007-10-24 17:25:03 +00:00
2008-05-05 14:22:36 +00:00
// Sprite already loaded?
if ( sprites . ContainsKey ( longname ) )
2007-10-24 17:25:03 +00:00
{
2008-05-05 14:22:36 +00:00
// Return exiting sprite
return sprites [ longname ] ;
}
else
{
// Go for all opened containers
for ( int i = containers . Count - 1 ; i > = 0 ; i - - )
2007-10-26 13:31:02 +00:00
{
2008-05-05 14:22:36 +00:00
// This contain provides this sprite?
spritedata = containers [ i ] . GetSpriteData ( name ) ;
if ( spritedata ! = null ) break ;
2007-10-26 13:31:02 +00:00
}
2008-05-05 14:22:36 +00:00
// Found anything?
if ( spritedata ! = null )
{
// Make new sprite image
image = new SpriteImage ( name ) ;
2007-10-26 13:31:02 +00:00
2008-05-05 14:22:36 +00:00
// Add to collection
sprites . Add ( longname , image ) ;
2007-10-26 15:28:32 +00:00
2008-05-05 14:22:36 +00:00
// Return result
return image ;
}
else
{
// Return null image
return new NullImage ( ) ;
2007-10-26 13:31:02 +00:00
}
2007-10-24 17:25:03 +00:00
}
}
2008-09-28 21:20:56 +00:00
// BAD! These block while loading the image. That is not
// what our background loading system is for!
/ *
2007-10-26 13:17:20 +00:00
// This returns a bitmap by string
public Bitmap GetSpriteBitmap ( string name )
{
ImageData img = GetSpriteImage ( name ) ;
img . LoadImage ( ) ;
return img . Bitmap ;
}
// This returns a texture by string
public Texture GetSpriteTexture ( string name )
{
ImageData img = GetSpriteImage ( name ) ;
img . LoadImage ( ) ;
img . CreateTexture ( ) ;
return img . Texture ;
}
2008-09-28 21:20:56 +00:00
* /
2007-10-26 13:17:20 +00:00
2007-10-07 22:21:47 +00:00
#endregion
2008-05-22 12:03:33 +00:00
#region = = = = = = = = = = = = = = = = = = Tools
// This finds the first IWAD resource
// Returns false when not found
internal bool FindFirstIWAD ( out DataLocation result )
{
// Go for all data containers
foreach ( DataReader dr in containers )
{
// Container is a WAD file?
if ( dr is WADReader )
{
// Check if it is an IWAD
WADReader wr = dr as WADReader ;
if ( wr . IsIWAD )
{
// Return location!
result = wr . Location ;
return true ;
}
}
}
// No IWAD found
result = new DataLocation ( ) ;
return false ;
}
2008-09-28 21:20:56 +00:00
// This signals the background thread to update the
// used-in-map status on all textures and flats
public void UpdateUsedTextures ( )
{
2008-10-15 17:26:59 +00:00
lock ( usedimages )
{
usedimages . Clear ( ) ;
// 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 ) usedimages [ sd . LongHighTexture ] = 0 ;
if ( sd . LowTexture . Length > 0 ) usedimages [ sd . LongMiddleTexture ] = 0 ;
if ( sd . MiddleTexture . Length > 0 ) usedimages [ 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
usedimages [ s . LongFloorTexture ] = 0 ;
usedimages [ s . LongCeilTexture ] = 0 ;
}
// Notify the background thread that it needs to update the images
updatedusedtextures = true ;
}
2008-09-28 21:20:56 +00:00
}
2008-05-22 12:03:33 +00:00
#endregion
2007-10-01 20:57:41 +00:00
}
}