2009-04-19 18:07:22 +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.Generic ;
using System.Drawing ;
using System.Drawing.Imaging ;
using CodeImp.DoomBuilder.Rendering ;
using CodeImp.DoomBuilder.IO ;
using System.IO ;
2019-12-29 02:54:12 +00:00
using System.Linq ;
2009-04-19 18:07:22 +00:00
#endregion
namespace CodeImp.DoomBuilder.Data
{
internal sealed unsafe class TextureImage : ImageData
{
#region = = = = = = = = = = = = = = = = = = Variables
private List < TexturePatch > patches ;
#endregion
#region = = = = = = = = = = = = = = = = = = Constructor / Disposer
// Constructor
2016-06-15 14:48:21 +00:00
public TextureImage ( string group , string name , int width , int height , float scalex , float scaley , bool worldpanning )
2009-04-19 18:07:22 +00:00
{
// Initialize
this . width = width ;
this . height = height ;
2010-01-02 20:22:05 +00:00
this . scale . x = scalex ;
this . scale . y = scaley ;
2016-06-15 14:48:21 +00:00
this . worldpanning = worldpanning ; //mxd
2009-04-19 18:07:22 +00:00
this . patches = new List < TexturePatch > ( ) ;
SetName ( name ) ;
2015-03-22 20:43:05 +00:00
virtualname = "[" + group + "]/" + this . name ; //mxd
2009-04-19 18:07:22 +00:00
// We have no destructor
GC . SuppressFinalize ( this ) ;
}
#endregion
#region = = = = = = = = = = = = = = = = = = Methods
// This adds a patch to the texture
public void AddPatch ( TexturePatch patch )
{
// Add it
patches . Add ( patch ) ;
2014-07-15 08:08:57 +00:00
2016-03-16 23:26:53 +00:00
if ( patch . LumpName = = Name ) hasPatchWithSameName = true ; //mxd
2009-04-19 18:07:22 +00:00
}
// This loads the image
2019-12-29 02:54:12 +00:00
protected override LocalLoadResult LocalLoadImage ( )
2009-04-19 18:07:22 +00:00
{
2015-12-28 15:01:53 +00:00
// Checks
2019-12-29 02:54:12 +00:00
if ( width = = 0 | | height = = 0 ) return new LocalLoadResult ( null ) ;
2015-12-28 15:01:53 +00:00
2009-04-19 18:07:22 +00:00
BitmapData bitmapdata = null ;
PixelColor * pixels = ( PixelColor * ) 0 ;
2019-12-29 02:54:12 +00:00
Bitmap bitmap = null ;
List < LogMessage > messages = new List < LogMessage > ( ) ;
// Create texture bitmap
try
2009-04-19 18:07:22 +00:00
{
2019-12-29 02:54:12 +00:00
if ( bitmap ! = null ) bitmap . Dispose ( ) ;
bitmap = new Bitmap ( width , height , PixelFormat . Format32bppArgb ) ;
bitmapdata = bitmap . LockBits ( new Rectangle ( 0 , 0 , width , height ) , ImageLockMode . WriteOnly , PixelFormat . Format32bppArgb ) ;
pixels = ( PixelColor * ) bitmapdata . Scan0 . ToPointer ( ) ;
2020-09-11 20:39:18 +00:00
General . ZeroPixels ( pixels , width * height ) ;
2019-12-29 02:54:12 +00:00
}
catch ( Exception e )
{
// Unable to make bitmap
messages . Add ( new LogMessage ( ErrorType . Error , "Unable to load texture image \"" + this . Name + "\". " + e . GetType ( ) . Name + ": " + e . Message ) ) ;
}
2009-04-19 18:07:22 +00:00
2019-12-29 02:54:12 +00:00
int missingpatches = 0 ; //mxd
2013-07-29 08:50:50 +00:00
2019-12-29 02:54:12 +00:00
if ( ! messages . Any ( x = > x . Type = = ErrorType . Error ) )
{
// Go for all patches
foreach ( TexturePatch p in patches )
2009-04-19 18:07:22 +00:00
{
2019-12-29 02:54:12 +00:00
// Get the patch data stream
string patchlocation = string . Empty ; //mxd
Stream patchdata = General . Map . Data . GetPatchData ( p . LumpName , p . HasLongName , ref patchlocation ) ;
if ( patchdata ! = null )
2009-04-19 18:07:22 +00:00
{
2019-12-29 02:54:12 +00:00
// Get a reader for the data
2020-01-14 16:25:35 +00:00
Bitmap patchbmp = ImageDataFormat . TryLoadImage ( patchdata , ImageDataFormat . DOOMPICTURE , General . Map . Data . Palette ) ;
2020-02-16 17:57:19 +00:00
if ( patchbmp = = null )
2019-12-29 02:54:12 +00:00
{
//mxd. Probably that's a flat?..
if ( General . Map . Config . MixTexturesFlats )
2009-04-19 18:07:22 +00:00
{
2020-01-14 16:25:35 +00:00
patchbmp = ImageDataFormat . TryLoadImage ( patchdata , ImageDataFormat . DOOMFLAT , General . Map . Data . Palette ) ;
2009-04-19 18:07:22 +00:00
}
2020-01-14 16:25:35 +00:00
if ( patchbmp = = null )
2014-12-03 23:15:26 +00:00
{
2019-12-29 02:54:12 +00:00
// Data is in an unknown format!
messages . Add ( new LogMessage ( ErrorType . Error , "Patch lump \"" + Path . Combine ( patchlocation , p . LumpName ) + "\" data format could not be read, while loading texture \"" + this . Name + "\". Does this lump contain valid picture data at all?" ) ) ;
missingpatches + + ; //mxd
2009-04-19 18:07:22 +00:00
}
}
2019-12-29 02:54:12 +00:00
2020-01-14 16:25:35 +00:00
if ( patchbmp ! = null )
2009-04-19 18:07:22 +00:00
{
2019-12-29 14:38:53 +00:00
// Draw the patch
2020-01-14 16:25:35 +00:00
DrawToPixelData ( patchbmp , pixels , width , height , p . X , p . Y ) ;
patchbmp . Dispose ( ) ;
2009-04-19 18:07:22 +00:00
}
2019-12-29 14:38:53 +00:00
// Done
patchdata . Dispose ( ) ;
2019-12-29 02:54:12 +00:00
}
else
{
// Missing a patch lump!
messages . Add ( new LogMessage ( ErrorType . Error , "Missing patch lump \"" + p . LumpName + "\" while loading texture \"" + this . Name + "\". Did you forget to include required resources?" ) ) ;
missingpatches + + ; //mxd
}
2009-04-19 18:07:22 +00:00
}
2019-12-29 02:54:12 +00:00
// Done
bitmap . UnlockBits ( bitmapdata ) ;
2009-04-19 18:07:22 +00:00
}
2019-12-29 02:54:12 +00:00
// Dispose bitmap if load failed
if ( ( bitmap ! = null ) & & ( messages . Any ( x = > x . Type = = ErrorType . Error ) | | missingpatches > = patches . Count ) ) //mxd. We can still display texture if at least one of the patches was loaded
{
bitmap . Dispose ( ) ;
bitmap = null ;
}
return new LocalLoadResult ( bitmap , messages ) ;
2009-04-19 18:07:22 +00:00
}
2020-01-14 16:25:35 +00:00
// This draws the picture to the given pixel color data
static unsafe void DrawToPixelData ( Bitmap bmp , PixelColor * target , int targetwidth , int targetheight , int x , int y )
{
// Get bitmap
int width = bmp . Size . Width ;
int height = bmp . Size . Height ;
// Lock bitmap pixels
BitmapData bmpdata = bmp . LockBits ( new Rectangle ( 0 , 0 , width , height ) , ImageLockMode . ReadOnly , PixelFormat . Format32bppArgb ) ;
PixelColor * pixels = ( PixelColor * ) bmpdata . Scan0 . ToPointer ( ) ;
// Go for all pixels in the original image
for ( int ox = 0 ; ox < width ; ox + + )
{
for ( int oy = 0 ; oy < height ; oy + + )
{
// Copy this pixel?
if ( pixels [ oy * width + ox ] . a > 0.5f )
{
// Calculate target pixel and copy when within bounds
int tx = x + ox ;
int ty = y + oy ;
if ( ( tx > = 0 ) & & ( tx < targetwidth ) & & ( ty > = 0 ) & & ( ty < targetheight ) )
target [ ty * targetwidth + tx ] = pixels [ oy * width + ox ] ;
}
}
}
// Done
bmp . UnlockBits ( bmpdata ) ;
}
#endregion
}
2009-04-19 18:07:22 +00:00
}