mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-10 14:51:40 +00:00
- Added translation support to multipatch textures. Incomplete and not tested yet!
- Added Martin Howe's morph weapon update. SVN r916 (trunk)
This commit is contained in:
parent
ce5d4dba02
commit
b2bfad0c50
19 changed files with 698 additions and 195 deletions
|
@ -1,4 +1,6 @@
|
||||||
April 15, 2008 (Changes by Graf Zahl)
|
April 15, 2008 (Changes by Graf Zahl)
|
||||||
|
- Added translation support to multipatch textures. Not tested yet!
|
||||||
|
- Added Martin Howe's morph weapon update.
|
||||||
- Changed true color texture creation to use a newly defined Bitmap class
|
- Changed true color texture creation to use a newly defined Bitmap class
|
||||||
instead of having the copy functions in the frame buffer class.
|
instead of having the copy functions in the frame buffer class.
|
||||||
- Fixed: The WolfSS didn't have its obituary defined.
|
- Fixed: The WolfSS didn't have its obituary defined.
|
||||||
|
|
|
@ -224,7 +224,7 @@ private:
|
||||||
|
|
||||||
FTexture *BaseTexture;
|
FTexture *BaseTexture;
|
||||||
BYTE *Pixels;
|
BYTE *Pixels;
|
||||||
FRemapTable *STBFremap;
|
FRemapTable *STFBRemap;
|
||||||
}
|
}
|
||||||
StatusBarTex;
|
StatusBarTex;
|
||||||
|
|
||||||
|
@ -1044,7 +1044,7 @@ DDoomStatusBar::FDoomStatusBarTexture::FDoomStatusBarTexture ()
|
||||||
// now copy all the properties from the base texture
|
// now copy all the properties from the base texture
|
||||||
CopySize(BaseTexture);
|
CopySize(BaseTexture);
|
||||||
Pixels = NULL;
|
Pixels = NULL;
|
||||||
STBFremap = NULL;
|
STFBRemap = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
const BYTE *DDoomStatusBar::FDoomStatusBarTexture::GetColumn (unsigned int column, const Span **spans_out)
|
const BYTE *DDoomStatusBar::FDoomStatusBarTexture::GetColumn (unsigned int column, const Span **spans_out)
|
||||||
|
@ -1090,7 +1090,7 @@ void DDoomStatusBar::FDoomStatusBarTexture::MakeTexture ()
|
||||||
if (!deathmatch) DrawToBar("STARMS", 104, 0, NULL);
|
if (!deathmatch) DrawToBar("STARMS", 104, 0, NULL);
|
||||||
DrawToBar("STTPRCNT", 90, 3, NULL);
|
DrawToBar("STTPRCNT", 90, 3, NULL);
|
||||||
DrawToBar("STTPRCNT", 221, 3, NULL);
|
DrawToBar("STTPRCNT", 221, 3, NULL);
|
||||||
if (multiplayer) DrawToBar("STFBANY", 143, 1, STBFremap? STBFremap->Remap : NULL);
|
if (multiplayer) DrawToBar("STFBANY", 143, 1, STFBRemap? STFBRemap->Remap : NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
int DDoomStatusBar::FDoomStatusBarTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate)
|
int DDoomStatusBar::FDoomStatusBarTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate)
|
||||||
|
@ -1119,7 +1119,7 @@ int DDoomStatusBar::FDoomStatusBarTexture::CopyTrueColorPixels(FBitmap *bmp, int
|
||||||
tex = TexMan["STFBANY"];
|
tex = TexMan["STFBANY"];
|
||||||
if (tex != NULL)
|
if (tex != NULL)
|
||||||
{
|
{
|
||||||
tex->CopyTrueColorTranslated(bmp, x+143, y+1, STBFremap);
|
tex->CopyTrueColorTranslated(bmp, x+143, y+1, 0, STFBRemap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1141,7 +1141,7 @@ void DDoomStatusBar::FDoomStatusBarTexture::SetPlayerRemap(FRemapTable *remap)
|
||||||
{
|
{
|
||||||
Unload();
|
Unload();
|
||||||
KillNative();
|
KillNative();
|
||||||
STBFremap = remap;
|
STFBRemap = remap;
|
||||||
}
|
}
|
||||||
|
|
||||||
DBaseStatusBar *CreateDoomStatusBar ()
|
DBaseStatusBar *CreateDoomStatusBar ()
|
||||||
|
|
|
@ -206,6 +206,7 @@ bool P_UndoPlayerMorph (player_t *player, bool force)
|
||||||
mo->flags3 = (mo->flags3 & ~MF3_GHOST) | (pmo->flags3 & MF3_GHOST);
|
mo->flags3 = (mo->flags3 & ~MF3_GHOST) | (pmo->flags3 & MF3_GHOST);
|
||||||
|
|
||||||
const PClass *exit_flash = player->MorphExitFlash;
|
const PClass *exit_flash = player->MorphExitFlash;
|
||||||
|
bool correctweapon = ((player->MorphStyle & MORPH_LOSEACTUALWEAPON) == 0);
|
||||||
|
|
||||||
player->morphTics = 0;
|
player->morphTics = 0;
|
||||||
player->MorphedPlayerClass = 0;
|
player->MorphedPlayerClass = 0;
|
||||||
|
@ -267,13 +268,32 @@ bool P_UndoPlayerMorph (player_t *player, bool force)
|
||||||
{
|
{
|
||||||
player->ReadyWeapon = player->PendingWeapon = NULL;
|
player->ReadyWeapon = player->PendingWeapon = NULL;
|
||||||
}
|
}
|
||||||
if (beastweap != NULL)
|
if (correctweapon)
|
||||||
{ // You don't get to keep your morphed weapon.
|
{ // Better "lose morphed weapon" semantics
|
||||||
if (beastweap->SisterWeapon != NULL)
|
const PClass *morphweapon = PClass::FindClass (mo->MorphWeapon);
|
||||||
|
if (morphweapon != NULL && morphweapon->IsDescendantOf (RUNTIME_CLASS(AWeapon)))
|
||||||
{
|
{
|
||||||
beastweap->SisterWeapon->Destroy ();
|
AWeapon *OriginalMorphWeapon = static_cast<AWeapon *>(mo->FindInventory (morphweapon));
|
||||||
|
if ((OriginalMorphWeapon != NULL) && (OriginalMorphWeapon->GivenAsMorphWeapon))
|
||||||
|
{ // You don't get to keep your morphed weapon.
|
||||||
|
if (OriginalMorphWeapon->SisterWeapon != NULL)
|
||||||
|
{
|
||||||
|
OriginalMorphWeapon->SisterWeapon->Destroy ();
|
||||||
|
}
|
||||||
|
OriginalMorphWeapon->Destroy ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // old behaviour (not really useful now)
|
||||||
|
{ // Assumptions made here are no longer valid
|
||||||
|
if (beastweap != NULL)
|
||||||
|
{ // You don't get to keep your morphed weapon.
|
||||||
|
if (beastweap->SisterWeapon != NULL)
|
||||||
|
{
|
||||||
|
beastweap->SisterWeapon->Destroy ();
|
||||||
|
}
|
||||||
|
beastweap->Destroy ();
|
||||||
}
|
}
|
||||||
beastweap->Destroy ();
|
|
||||||
}
|
}
|
||||||
pmo->tracer = NULL;
|
pmo->tracer = NULL;
|
||||||
pmo->Destroy ();
|
pmo->Destroy ();
|
||||||
|
|
|
@ -17,7 +17,8 @@ enum
|
||||||
MORPH_UNDOBYCHAOSDEVICE = 0x00000008, // Player unmorphs upon activating a Chaos Device
|
MORPH_UNDOBYCHAOSDEVICE = 0x00000008, // Player unmorphs upon activating a Chaos Device
|
||||||
MORPH_FAILNOTELEFRAG = 0x00000010, // Player stays morphed if unmorph by Tome of Power fails
|
MORPH_FAILNOTELEFRAG = 0x00000010, // Player stays morphed if unmorph by Tome of Power fails
|
||||||
MORPH_FAILNOLAUGH = 0x00000020, // Player doesn't laugh if unmorph by Chaos Device fails
|
MORPH_FAILNOLAUGH = 0x00000020, // Player doesn't laugh if unmorph by Chaos Device fails
|
||||||
MORPH_WHENINVULNERABLE = 0x00000040 // Player can morph when invulnerable but ONLY if doing it to themselves
|
MORPH_WHENINVULNERABLE = 0x00000040, // Player can morph when invulnerable but ONLY if doing it to themselves
|
||||||
|
MORPH_LOSEACTUALWEAPON = 0X00000080 // Player loses specified morph weapon only (not "whichever they have when unmorphing")
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PClass;
|
struct PClass;
|
||||||
|
|
|
@ -221,6 +221,7 @@ public:
|
||||||
// In-inventory instance variables
|
// In-inventory instance variables
|
||||||
TObjPtr<AAmmo> Ammo1, Ammo2;
|
TObjPtr<AAmmo> Ammo1, Ammo2;
|
||||||
TObjPtr<AWeapon> SisterWeapon;
|
TObjPtr<AWeapon> SisterWeapon;
|
||||||
|
bool GivenAsMorphWeapon;
|
||||||
|
|
||||||
bool bAltFire; // Set when this weapon's alternate fire is used.
|
bool bAltFire; // Set when this weapon's alternate fire is used.
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@ void AWeapon::Serialize (FArchive &arc)
|
||||||
<< ProjectileType << AltProjectileType
|
<< ProjectileType << AltProjectileType
|
||||||
<< SelectionOrder
|
<< SelectionOrder
|
||||||
<< MoveCombatDist
|
<< MoveCombatDist
|
||||||
<< Ammo1 << Ammo2 << SisterWeapon
|
<< Ammo1 << Ammo2 << SisterWeapon << GivenAsMorphWeapon
|
||||||
<< bAltFire;
|
<< bAltFire;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,6 +230,7 @@ void AWeapon::AttachToOwner (AActor *other)
|
||||||
StatusBar->ReceivedWeapon (this);
|
StatusBar->ReceivedWeapon (this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
GivenAsMorphWeapon = false; // will be set explicitly by morphing code
|
||||||
}
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
|
@ -5342,21 +5342,18 @@ int DLevelScript::RunScript ()
|
||||||
|
|
||||||
case PCD_CHECKPLAYERCAMERA:
|
case PCD_CHECKPLAYERCAMERA:
|
||||||
{
|
{
|
||||||
AActor *actor = SingleActorFromTID(STACK(1), activator);
|
int playernum = STACK(1);
|
||||||
|
|
||||||
if(actor != NULL && actor->player != NULL)
|
if (playernum < 0 || playernum >= MAXPLAYERS || !playeringame[playernum] || players[playernum].camera == NULL)
|
||||||
{
|
{
|
||||||
if(actor->player->camera != actor->player->mo)
|
STACK(1) = -1;
|
||||||
{
|
}
|
||||||
STACK(1) = actor->player->camera->tid;
|
else
|
||||||
}
|
{
|
||||||
else
|
STACK(1) = players[playernum].camera->tid;
|
||||||
{
|
|
||||||
STACK(1) = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else STACK(1) = 0;
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1050,6 +1050,10 @@ void APlayerPawn::ActivateMorphWeapon ()
|
||||||
if (player->ReadyWeapon == NULL)
|
if (player->ReadyWeapon == NULL)
|
||||||
{
|
{
|
||||||
player->ReadyWeapon = static_cast<AWeapon *>(player->mo->GiveInventoryType (morphweapon));
|
player->ReadyWeapon = static_cast<AWeapon *>(player->mo->GiveInventoryType (morphweapon));
|
||||||
|
if (player->ReadyWeapon != NULL)
|
||||||
|
{
|
||||||
|
player->ReadyWeapon->GivenAsMorphWeapon = true; // flag is used only by new beastweap semantics in P_UndoPlayerMorph
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (player->ReadyWeapon != NULL)
|
if (player->ReadyWeapon != NULL)
|
||||||
{
|
{
|
||||||
|
|
|
@ -107,6 +107,8 @@ protected:
|
||||||
SWORD OriginX, OriginY;
|
SWORD OriginX, OriginY;
|
||||||
BYTE Rotate;
|
BYTE Rotate;
|
||||||
bool textureOwned;
|
bool textureOwned;
|
||||||
|
FRemapTable *Translation;
|
||||||
|
PalEntry Blend;
|
||||||
FTexture *Texture;
|
FTexture *Texture;
|
||||||
|
|
||||||
TexPart();
|
TexPart();
|
||||||
|
|
|
@ -796,7 +796,7 @@ public:
|
||||||
virtual const BYTE *GetPixels () = 0;
|
virtual const BYTE *GetPixels () = 0;
|
||||||
|
|
||||||
virtual int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate=0);
|
virtual int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate=0);
|
||||||
int CopyTrueColorTranslated(FBitmap *bmp, int x, int y, FRemapTable *remap);
|
int CopyTrueColorTranslated(FBitmap *bmp, int x, int y, int rotate, FRemapTable *remap);
|
||||||
virtual bool UseBasePalette();
|
virtual bool UseBasePalette();
|
||||||
virtual int GetSourceLump() { return -1; }
|
virtual int GetSourceLump() { return -1; }
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,26 @@
|
||||||
|
|
||||||
TAutoGrowArray<FRemapTablePtr, FRemapTable *> translationtables[NUM_TRANSLATION_TABLES];
|
TAutoGrowArray<FRemapTablePtr, FRemapTable *> translationtables[NUM_TRANSLATION_TABLES];
|
||||||
|
|
||||||
|
const BYTE IcePalette[16][3] =
|
||||||
|
{
|
||||||
|
{ 10, 8, 18 },
|
||||||
|
{ 15, 15, 26 },
|
||||||
|
{ 20, 16, 36 },
|
||||||
|
{ 30, 26, 46 },
|
||||||
|
{ 40, 36, 57 },
|
||||||
|
{ 50, 46, 67 },
|
||||||
|
{ 59, 57, 78 },
|
||||||
|
{ 69, 67, 88 },
|
||||||
|
{ 79, 77, 99 },
|
||||||
|
{ 89, 87,109 },
|
||||||
|
{ 99, 97,120 },
|
||||||
|
{ 109,107,130 },
|
||||||
|
{ 118,118,141 },
|
||||||
|
{ 128,128,151 },
|
||||||
|
{ 138,138,162 },
|
||||||
|
{ 148,148,172 }
|
||||||
|
};
|
||||||
|
|
||||||
/****************************************************/
|
/****************************************************/
|
||||||
/****************************************************/
|
/****************************************************/
|
||||||
|
|
||||||
|
@ -428,25 +448,6 @@ void R_InitTranslationTables ()
|
||||||
// Doom palette has no good substitutes for these bluish-tinted grays, so
|
// Doom palette has no good substitutes for these bluish-tinted grays, so
|
||||||
// they will just look gray unless you use a different PLAYPAL with Doom.
|
// they will just look gray unless you use a different PLAYPAL with Doom.
|
||||||
|
|
||||||
static const BYTE IcePalette[16][3] =
|
|
||||||
{
|
|
||||||
{ 10, 8, 18 },
|
|
||||||
{ 15, 15, 26 },
|
|
||||||
{ 20, 16, 36 },
|
|
||||||
{ 30, 26, 46 },
|
|
||||||
{ 40, 36, 57 },
|
|
||||||
{ 50, 46, 67 },
|
|
||||||
{ 59, 57, 78 },
|
|
||||||
{ 69, 67, 88 },
|
|
||||||
{ 79, 77, 99 },
|
|
||||||
{ 89, 87,109 },
|
|
||||||
{ 99, 97,120 },
|
|
||||||
{ 109,107,130 },
|
|
||||||
{ 118,118,141 },
|
|
||||||
{ 128,128,151 },
|
|
||||||
{ 138,138,162 },
|
|
||||||
{ 148,148,172 }
|
|
||||||
};
|
|
||||||
BYTE IcePaletteRemap[16];
|
BYTE IcePaletteRemap[16];
|
||||||
for (i = 0; i < 16; ++i)
|
for (i = 0; i < 16; ++i)
|
||||||
{
|
{
|
||||||
|
|
|
@ -97,6 +97,8 @@ void R_DeinitTranslationTables();
|
||||||
// [RH] Actually create a player's translation table.
|
// [RH] Actually create a player's translation table.
|
||||||
void R_BuildPlayerTranslation (int player);
|
void R_BuildPlayerTranslation (int player);
|
||||||
|
|
||||||
|
extern const BYTE IcePalette[16][3];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif // __R_TRANSLATE_H
|
#endif // __R_TRANSLATE_H
|
||||||
|
|
|
@ -34,41 +34,217 @@
|
||||||
|
|
||||||
#include "bitmap.h"
|
#include "bitmap.h"
|
||||||
#include "templates.h"
|
#include "templates.h"
|
||||||
|
#include "r_translate.h"
|
||||||
|
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
// multi-format pixel copy with colormap application
|
// multi-format pixel copy with colormap application
|
||||||
// requires one of the previously defined conversion classes to work
|
// requires the previously defined conversion classes to work
|
||||||
//
|
//
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
template<class T>
|
template<class TSrc, class TDest, class TBlend>
|
||||||
void iCopyColors(BYTE *pout, const BYTE *pin, int count, int step)
|
void iCopyColors(BYTE *pout, const BYTE *pin, int count, int step, FCopyInfo *inf)
|
||||||
{
|
{
|
||||||
for(int i=0;i<count;i++)
|
int i;
|
||||||
|
int fac;
|
||||||
|
BYTE r,g,b;
|
||||||
|
int gray;
|
||||||
|
int a;
|
||||||
|
|
||||||
|
switch(inf? inf->blend : BLEND_NONE)
|
||||||
{
|
{
|
||||||
pout[0]=T::B(pin);
|
case BLEND_NONE:
|
||||||
pout[1]=T::G(pin);
|
for(i=0;i<count;i++)
|
||||||
pout[2]=T::R(pin);
|
{
|
||||||
pout[3]=T::A(pin);
|
if ((a = TSrc::A(pin)))
|
||||||
pout+=4;
|
{
|
||||||
pin+=step;
|
TBlend::OpC(pout[TDest::RED], TSrc::R(pin), a, inf);
|
||||||
|
TBlend::OpC(pout[TDest::GREEN], TSrc::G(pin), a, inf);
|
||||||
|
TBlend::OpC(pout[TDest::BLUE], TSrc::B(pin), a, inf);
|
||||||
|
TBlend::OpA(pout[TDest::ALPHA], a, inf);
|
||||||
|
}
|
||||||
|
pout+=4;
|
||||||
|
pin+=step;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BLEND_INVERSEMAP:
|
||||||
|
// Doom's inverted invulnerability map
|
||||||
|
for(i=0;i<count;i++)
|
||||||
|
{
|
||||||
|
if ((a = TSrc::A(pin)))
|
||||||
|
{
|
||||||
|
gray = clamp<int>(255 - TSrc::Gray(pin),0,255);
|
||||||
|
|
||||||
|
TBlend::OpC(pout[TDest::RED], gray, a, inf);
|
||||||
|
TBlend::OpC(pout[TDest::GREEN], gray, a, inf);
|
||||||
|
TBlend::OpC(pout[TDest::BLUE], gray, a, inf);
|
||||||
|
TBlend::OpA(pout[TDest::ALPHA], a, inf);
|
||||||
|
}
|
||||||
|
pout+=4;
|
||||||
|
pin+=step;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BLEND_GOLDMAP:
|
||||||
|
// Heretic's golden invulnerability map
|
||||||
|
for(i=0;i<count;i++)
|
||||||
|
{
|
||||||
|
if ((a = TSrc::A(pin)))
|
||||||
|
{
|
||||||
|
gray = TSrc::Gray(pin);
|
||||||
|
r=clamp<int>(gray+(gray>>1),0,255);
|
||||||
|
g=clamp<int>(gray-(gray>>2),0,255);
|
||||||
|
|
||||||
|
TBlend::OpC(pout[TDest::RED], r, a, inf);
|
||||||
|
TBlend::OpC(pout[TDest::GREEN], g, a, inf);
|
||||||
|
TBlend::OpC(pout[TDest::BLUE], 0, a, inf);
|
||||||
|
TBlend::OpA(pout[TDest::ALPHA], a, inf);
|
||||||
|
}
|
||||||
|
pout+=4;
|
||||||
|
pin+=step;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BLEND_REDMAP:
|
||||||
|
// Skulltag's red Doomsphere map
|
||||||
|
for(i=0;i<count;i++)
|
||||||
|
{
|
||||||
|
if ((a = TSrc::A(pin)))
|
||||||
|
{
|
||||||
|
gray = TSrc::Gray(pin);
|
||||||
|
r=clamp<int>(gray+(gray>>1),0,255);
|
||||||
|
|
||||||
|
TBlend::OpC(pout[TDest::RED], r, a, inf);
|
||||||
|
TBlend::OpC(pout[TDest::GREEN], 0, a, inf);
|
||||||
|
TBlend::OpC(pout[TDest::BLUE], 0, a, inf);
|
||||||
|
TBlend::OpA(pout[TDest::ALPHA], a, inf);
|
||||||
|
}
|
||||||
|
pout+=4;
|
||||||
|
pin+=step;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BLEND_GREENMAP:
|
||||||
|
// Skulltags's Guardsphere map
|
||||||
|
for(i=0;i<count;i++)
|
||||||
|
{
|
||||||
|
if ((a = TSrc::A(pin)))
|
||||||
|
{
|
||||||
|
gray = TSrc::Gray(pin);
|
||||||
|
r=clamp<int>(gray+(gray>>1),0,255);
|
||||||
|
|
||||||
|
TBlend::OpC(pout[TDest::RED], r, a, inf);
|
||||||
|
TBlend::OpC(pout[TDest::GREEN], r, a, inf);
|
||||||
|
TBlend::OpC(pout[TDest::BLUE], gray, a, inf);
|
||||||
|
TBlend::OpA(pout[TDest::ALPHA], a, inf);
|
||||||
|
}
|
||||||
|
pout+=4;
|
||||||
|
pin+=step;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BLEND_ICEMAP:
|
||||||
|
// Create the ice translation table, based on Hexen's.
|
||||||
|
// Since this is done in True Color the purplish tint is fully preserved - even in Doom!
|
||||||
|
for(i=0;i<count;i++)
|
||||||
|
{
|
||||||
|
if ((a = TSrc::A(pin)))
|
||||||
|
{
|
||||||
|
int gray = TSrc::Gray(pin)>>4;
|
||||||
|
|
||||||
|
TBlend::OpC(pout[TDest::RED], IcePalette[gray][0], a, inf);
|
||||||
|
TBlend::OpC(pout[TDest::GREEN], IcePalette[gray][1], a, inf);
|
||||||
|
TBlend::OpC(pout[TDest::BLUE], IcePalette[gray][2], a, inf);
|
||||||
|
TBlend::OpA(pout[TDest::ALPHA], a, inf);
|
||||||
|
}
|
||||||
|
pout+=4;
|
||||||
|
pin+=step;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (inf->blend >= BLEND_DESATURATE1 && inf->blend<=BLEND_DESATURATE31)
|
||||||
|
{
|
||||||
|
// Desaturated light settings.
|
||||||
|
fac=inf->blend-BLEND_DESATURATE1+1;
|
||||||
|
for(i=0;i<count;i++)
|
||||||
|
{
|
||||||
|
if ((a = TSrc::A(pin)))
|
||||||
|
{
|
||||||
|
gray = TSrc::Gray(pin);
|
||||||
|
r = (TSrc::R(pin)*(31-fac) + gray*fac)/31;
|
||||||
|
g = (TSrc::G(pin)*(31-fac) + gray*fac)/31;
|
||||||
|
b = (TSrc::B(pin)*(31-fac) + gray*fac)/31;
|
||||||
|
|
||||||
|
TBlend::OpC(pout[TDest::RED], r, a, inf);
|
||||||
|
TBlend::OpC(pout[TDest::GREEN], g, a, inf);
|
||||||
|
TBlend::OpC(pout[TDest::BLUE], b, a, inf);
|
||||||
|
TBlend::OpA(pout[TDest::ALPHA], a, inf);
|
||||||
|
}
|
||||||
|
pout+=4;
|
||||||
|
pin+=step;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BLEND_MODULATE:
|
||||||
|
for(i=0;i<count;i++)
|
||||||
|
{
|
||||||
|
if ((a = TSrc::A(pin)))
|
||||||
|
{
|
||||||
|
r = (TSrc::R(pin)*inf->blendcolor[0])>>FRACBITS;
|
||||||
|
g = (TSrc::G(pin)*inf->blendcolor[1])>>FRACBITS;
|
||||||
|
b = (TSrc::B(pin)*inf->blendcolor[2])>>FRACBITS;
|
||||||
|
|
||||||
|
TBlend::OpC(pout[TDest::RED], r, a, inf);
|
||||||
|
TBlend::OpC(pout[TDest::GREEN], g, a, inf);
|
||||||
|
TBlend::OpC(pout[TDest::BLUE], b, a, inf);
|
||||||
|
TBlend::OpA(pout[TDest::ALPHA], a, inf);
|
||||||
|
}
|
||||||
|
pout+=4;
|
||||||
|
pin+=step;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BLEND_OVERLAY:
|
||||||
|
for(i=0;i<count;i++)
|
||||||
|
{
|
||||||
|
// color blend
|
||||||
|
if ((a = TSrc::A(pin)))
|
||||||
|
{
|
||||||
|
r = (TSrc::R(pin)*inf->blendcolor[3] + inf->blendcolor[0]) >> FRACBITS;
|
||||||
|
g = (TSrc::G(pin)*inf->blendcolor[3] + inf->blendcolor[1]) >> FRACBITS;
|
||||||
|
b = (TSrc::B(pin)*inf->blendcolor[3] + inf->blendcolor[2]) >> FRACBITS;
|
||||||
|
|
||||||
|
TBlend::OpC(pout[TDest::RED], r, a, inf);
|
||||||
|
TBlend::OpC(pout[TDest::GREEN], g, a, inf);
|
||||||
|
TBlend::OpC(pout[TDest::BLUE], b, a, inf);
|
||||||
|
TBlend::OpA(pout[TDest::ALPHA], a, inf);
|
||||||
|
}
|
||||||
|
pout+=4;
|
||||||
|
pin+=step;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef void (*CopyFunc)(BYTE *pout, const BYTE *pin, int count, int step);
|
typedef void (*CopyFunc)(BYTE *pout, const BYTE *pin, int count, int step, FCopyInfo *inf);
|
||||||
|
|
||||||
static CopyFunc copyfuncs[]={
|
static CopyFunc copyfuncs[9]=
|
||||||
iCopyColors<cRGB>,
|
{
|
||||||
iCopyColors<cRGBA>,
|
iCopyColors<cRGB, cBGRA, bCopy>,
|
||||||
iCopyColors<cIA>,
|
iCopyColors<cRGBA, cBGRA, bCopy>,
|
||||||
iCopyColors<cCMYK>,
|
iCopyColors<cIA, cBGRA, bCopy>,
|
||||||
iCopyColors<cBGR>,
|
iCopyColors<cCMYK, cBGRA, bCopy>,
|
||||||
iCopyColors<cBGRA>,
|
iCopyColors<cBGR, cBGRA, bCopy>,
|
||||||
iCopyColors<cI16>,
|
iCopyColors<cBGRA, cBGRA, bCopy>,
|
||||||
iCopyColors<cRGB555>,
|
iCopyColors<cI16, cBGRA, bCopy>,
|
||||||
iCopyColors<cPalEntry>
|
iCopyColors<cRGB555, cBGRA, bCopy>,
|
||||||
};
|
iCopyColors<cPalEntry, cBGRA, bCopy>
|
||||||
|
};
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
|
@ -199,7 +375,7 @@ void FBitmap::CopyPixelDataRGB(int originx, int originy, const BYTE *patch, int
|
||||||
BYTE *buffer = data + 4 * originx + Pitch * originy;
|
BYTE *buffer = data + 4 * originx + Pitch * originy;
|
||||||
for (int y=0;y<srcheight;y++)
|
for (int y=0;y<srcheight;y++)
|
||||||
{
|
{
|
||||||
copyfuncs[ct](&buffer[y*Pitch], &patch[y*step_y], srcwidth, step_x);
|
copyfuncs[ct](&buffer[y*Pitch], &patch[y*step_y], srcwidth, step_x, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,83 +108,113 @@ bool ClipCopyPixelRect(int texwidth, int texheight, int &originx, int &originy,
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
struct cRGB
|
struct cRGB
|
||||||
{
|
{
|
||||||
static unsigned char R(const unsigned char * p) { return p[0]; }
|
static __forceinline unsigned char R(const unsigned char * p) { return p[0]; }
|
||||||
static unsigned char G(const unsigned char * p) { return p[1]; }
|
static __forceinline unsigned char G(const unsigned char * p) { return p[1]; }
|
||||||
static unsigned char B(const unsigned char * p) { return p[2]; }
|
static __forceinline unsigned char B(const unsigned char * p) { return p[2]; }
|
||||||
static unsigned char A(const unsigned char * p) { return 255; }
|
static __forceinline unsigned char A(const unsigned char * p) { return 255; }
|
||||||
static int Gray(const unsigned char * p) { return (p[0]*77 + p[1]*143 + p[2]*36)>>8; }
|
static __forceinline int Gray(const unsigned char * p) { return (p[0]*77 + p[1]*143 + p[2]*36)>>8; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cRGBA
|
struct cRGBA
|
||||||
{
|
{
|
||||||
static unsigned char R(const unsigned char * p) { return p[0]; }
|
enum
|
||||||
static unsigned char G(const unsigned char * p) { return p[1]; }
|
{
|
||||||
static unsigned char B(const unsigned char * p) { return p[2]; }
|
RED = 0,
|
||||||
static unsigned char A(const unsigned char * p) { return p[3]; }
|
GREEN = 1,
|
||||||
static int Gray(const unsigned char * p) { return (p[0]*77 + p[1]*143 + p[2]*36)>>8; }
|
BLUE = 1,
|
||||||
|
ALPHA = 3
|
||||||
|
};
|
||||||
|
static __forceinline unsigned char R(const unsigned char * p) { return p[0]; }
|
||||||
|
static __forceinline unsigned char G(const unsigned char * p) { return p[1]; }
|
||||||
|
static __forceinline unsigned char B(const unsigned char * p) { return p[2]; }
|
||||||
|
static __forceinline unsigned char A(const unsigned char * p) { return p[3]; }
|
||||||
|
static __forceinline int Gray(const unsigned char * p) { return (p[0]*77 + p[1]*143 + p[2]*36)>>8; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cIA
|
struct cIA
|
||||||
{
|
{
|
||||||
static unsigned char R(const unsigned char * p) { return p[0]; }
|
static __forceinline unsigned char R(const unsigned char * p) { return p[0]; }
|
||||||
static unsigned char G(const unsigned char * p) { return p[0]; }
|
static __forceinline unsigned char G(const unsigned char * p) { return p[0]; }
|
||||||
static unsigned char B(const unsigned char * p) { return p[0]; }
|
static __forceinline unsigned char B(const unsigned char * p) { return p[0]; }
|
||||||
static unsigned char A(const unsigned char * p) { return p[1]; }
|
static __forceinline unsigned char A(const unsigned char * p) { return p[1]; }
|
||||||
static int Gray(const unsigned char * p) { return p[0]; }
|
static __forceinline int Gray(const unsigned char * p) { return p[0]; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cCMYK
|
struct cCMYK
|
||||||
{
|
{
|
||||||
static unsigned char R(const unsigned char * p) { return p[3] - (((256-p[0])*p[3]) >> 8); }
|
static __forceinline unsigned char R(const unsigned char * p) { return p[3] - (((256-p[0])*p[3]) >> 8); }
|
||||||
static unsigned char G(const unsigned char * p) { return p[3] - (((256-p[1])*p[3]) >> 8); }
|
static __forceinline unsigned char G(const unsigned char * p) { return p[3] - (((256-p[1])*p[3]) >> 8); }
|
||||||
static unsigned char B(const unsigned char * p) { return p[3] - (((256-p[2])*p[3]) >> 8); }
|
static __forceinline unsigned char B(const unsigned char * p) { return p[3] - (((256-p[2])*p[3]) >> 8); }
|
||||||
static unsigned char A(const unsigned char * p) { return 255; }
|
static __forceinline unsigned char A(const unsigned char * p) { return 255; }
|
||||||
static int Gray(const unsigned char * p) { return (R(p)*77 + G(p)*143 + B(p)*36)>>8; }
|
static __forceinline int Gray(const unsigned char * p) { return (R(p)*77 + G(p)*143 + B(p)*36)>>8; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cBGR
|
struct cBGR
|
||||||
{
|
{
|
||||||
static unsigned char R(const unsigned char * p) { return p[2]; }
|
static __forceinline unsigned char R(const unsigned char * p) { return p[2]; }
|
||||||
static unsigned char G(const unsigned char * p) { return p[1]; }
|
static __forceinline unsigned char G(const unsigned char * p) { return p[1]; }
|
||||||
static unsigned char B(const unsigned char * p) { return p[0]; }
|
static __forceinline unsigned char B(const unsigned char * p) { return p[0]; }
|
||||||
static unsigned char A(const unsigned char * p) { return 255; }
|
static __forceinline unsigned char A(const unsigned char * p) { return 255; }
|
||||||
static int Gray(const unsigned char * p) { return (p[2]*77 + p[1]*143 + p[0]*36)>>8; }
|
static __forceinline int Gray(const unsigned char * p) { return (p[2]*77 + p[1]*143 + p[0]*36)>>8; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cBGRA
|
struct cBGRA
|
||||||
{
|
{
|
||||||
static unsigned char R(const unsigned char * p) { return p[2]; }
|
enum
|
||||||
static unsigned char G(const unsigned char * p) { return p[1]; }
|
{
|
||||||
static unsigned char B(const unsigned char * p) { return p[0]; }
|
RED = 2,
|
||||||
static unsigned char A(const unsigned char * p) { return p[3]; }
|
GREEN = 1,
|
||||||
static int Gray(const unsigned char * p) { return (p[2]*77 + p[1]*143 + p[0]*36)>>8; }
|
BLUE = 0,
|
||||||
|
ALPHA = 3
|
||||||
|
};
|
||||||
|
static __forceinline unsigned char R(const unsigned char * p) { return p[2]; }
|
||||||
|
static __forceinline unsigned char G(const unsigned char * p) { return p[1]; }
|
||||||
|
static __forceinline unsigned char B(const unsigned char * p) { return p[0]; }
|
||||||
|
static __forceinline unsigned char A(const unsigned char * p) { return p[3]; }
|
||||||
|
static __forceinline int Gray(const unsigned char * p) { return (p[2]*77 + p[1]*143 + p[0]*36)>>8; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct cARGB
|
||||||
|
{
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
RED = 1,
|
||||||
|
GREEN = 2,
|
||||||
|
BLUE = 3,
|
||||||
|
ALPHA = 0
|
||||||
|
};
|
||||||
|
static __forceinline unsigned char R(const unsigned char * p) { return p[1]; }
|
||||||
|
static __forceinline unsigned char G(const unsigned char * p) { return p[2]; }
|
||||||
|
static __forceinline unsigned char B(const unsigned char * p) { return p[3]; }
|
||||||
|
static __forceinline unsigned char A(const unsigned char * p) { return p[0]; }
|
||||||
|
static __forceinline int Gray(const unsigned char * p) { return (p[1]*77 + p[2]*143 + p[3]*36)>>8; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cI16
|
struct cI16
|
||||||
{
|
{
|
||||||
static unsigned char R(const unsigned char * p) { return p[1]; }
|
static __forceinline unsigned char R(const unsigned char * p) { return p[1]; }
|
||||||
static unsigned char G(const unsigned char * p) { return p[1]; }
|
static __forceinline unsigned char G(const unsigned char * p) { return p[1]; }
|
||||||
static unsigned char B(const unsigned char * p) { return p[1]; }
|
static __forceinline unsigned char B(const unsigned char * p) { return p[1]; }
|
||||||
static unsigned char A(const unsigned char * p) { return 255; }
|
static __forceinline unsigned char A(const unsigned char * p) { return 255; }
|
||||||
static int Gray(const unsigned char * p) { return p[1]; }
|
static __forceinline int Gray(const unsigned char * p) { return p[1]; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cRGB555
|
struct cRGB555
|
||||||
{
|
{
|
||||||
static unsigned char R(const unsigned char * p) { return (((*(WORD*)p)&0x1f)<<3); }
|
static __forceinline unsigned char R(const unsigned char * p) { return (((*(WORD*)p)&0x1f)<<3); }
|
||||||
static unsigned char G(const unsigned char * p) { return (((*(WORD*)p)&0x3e0)>>2); }
|
static __forceinline unsigned char G(const unsigned char * p) { return (((*(WORD*)p)&0x3e0)>>2); }
|
||||||
static unsigned char B(const unsigned char * p) { return (((*(WORD*)p)&0x7c00)>>7); }
|
static __forceinline unsigned char B(const unsigned char * p) { return (((*(WORD*)p)&0x7c00)>>7); }
|
||||||
static unsigned char A(const unsigned char * p) { return p[1]; }
|
static __forceinline unsigned char A(const unsigned char * p) { return 255; }
|
||||||
static int Gray(const unsigned char * p) { return (R(p)*77 + G(p)*143 + B(p)*36)>>8; }
|
static __forceinline int Gray(const unsigned char * p) { return (R(p)*77 + G(p)*143 + B(p)*36)>>8; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cPalEntry
|
struct cPalEntry
|
||||||
{
|
{
|
||||||
static unsigned char R(const unsigned char * p) { return ((PalEntry*)p)->r; }
|
static __forceinline unsigned char R(const unsigned char * p) { return ((PalEntry*)p)->r; }
|
||||||
static unsigned char G(const unsigned char * p) { return ((PalEntry*)p)->g; }
|
static __forceinline unsigned char G(const unsigned char * p) { return ((PalEntry*)p)->g; }
|
||||||
static unsigned char B(const unsigned char * p) { return ((PalEntry*)p)->b; }
|
static __forceinline unsigned char B(const unsigned char * p) { return ((PalEntry*)p)->b; }
|
||||||
static unsigned char A(const unsigned char * p) { return ((PalEntry*)p)->a; }
|
static __forceinline unsigned char A(const unsigned char * p) { return ((PalEntry*)p)->a; }
|
||||||
static int Gray(const unsigned char * p) { return (R(p)*77 + G(p)*143 + B(p)*36)>>8; }
|
static __forceinline int Gray(const unsigned char * p) { return (R(p)*77 + G(p)*143 + B(p)*36)>>8; }
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ColorType
|
enum ColorType
|
||||||
|
@ -200,5 +230,37 @@ enum ColorType
|
||||||
CF_PalEntry
|
CF_PalEntry
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum EBlend
|
||||||
|
{
|
||||||
|
BLEND_NONE = 0,
|
||||||
|
BLEND_INVERSEMAP = 1,
|
||||||
|
BLEND_GOLDMAP = 2,
|
||||||
|
BLEND_REDMAP = 3,
|
||||||
|
BLEND_GREENMAP = 4,
|
||||||
|
BLEND_ICEMAP = 5,
|
||||||
|
BLEND_DESATURATE1 = 6,
|
||||||
|
BLEND_DESATURATE31 = 36,
|
||||||
|
BLEND_MODULATE = -1,
|
||||||
|
BLEND_OVERLAY = -2,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FCopyInfo
|
||||||
|
{
|
||||||
|
//ECopyOp op;
|
||||||
|
EBlend blend;
|
||||||
|
fixed_t blendcolor[4];
|
||||||
|
// fixed_t alpha;
|
||||||
|
// fixed_t invalpha;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
struct bCopy
|
||||||
|
{
|
||||||
|
static __forceinline void OpC(BYTE &d, BYTE s, BYTE a, FCopyInfo *i) { d = s; }
|
||||||
|
static __forceinline void OpA(BYTE &d, BYTE s, FCopyInfo *i) { d = s; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -44,6 +44,8 @@
|
||||||
#include "sc_man.h"
|
#include "sc_man.h"
|
||||||
#include "templates.h"
|
#include "templates.h"
|
||||||
#include "vectors.h"
|
#include "vectors.h"
|
||||||
|
#include "r_translate.h"
|
||||||
|
#include "bitmap.h"
|
||||||
|
|
||||||
// On the Alpha, accessing the shorts directly if they aren't aligned on a
|
// On the Alpha, accessing the shorts directly if they aren't aligned on a
|
||||||
// 4-byte boundary causes unaligned access warnings. Why it does this at
|
// 4-byte boundary causes unaligned access warnings. Why it does this at
|
||||||
|
@ -274,6 +276,70 @@ const BYTE *FMultiPatchTexture::GetColumn (unsigned int column, const Span **spa
|
||||||
return Pixels + column*Height;
|
return Pixels + column*Height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FMultiPatchTexture :: GetColumn
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
BYTE * GetBlendMap(PalEntry blend, BYTE *blendwork)
|
||||||
|
{
|
||||||
|
|
||||||
|
switch (blend)
|
||||||
|
{
|
||||||
|
case BLEND_INVERSEMAP:
|
||||||
|
return InverseColormap;
|
||||||
|
|
||||||
|
case BLEND_GOLDMAP:
|
||||||
|
return GoldColormap;
|
||||||
|
|
||||||
|
case BLEND_REDMAP:
|
||||||
|
return RedColormap;
|
||||||
|
|
||||||
|
case BLEND_GREENMAP:
|
||||||
|
return GreenColormap;
|
||||||
|
|
||||||
|
case BLEND_ICEMAP:
|
||||||
|
return TranslationToTable(TRANSLATION(TRANSLATION_Standard, 7))->Remap;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (blend >= BLEND_DESATURATE1 && blend <= BLEND_DESATURATE31)
|
||||||
|
{
|
||||||
|
return DesaturateColormap[blend - BLEND_DESATURATE1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
blendwork[0]=0;
|
||||||
|
if (blend.a == 255)
|
||||||
|
{
|
||||||
|
for(int i=1;i<256;i++)
|
||||||
|
{
|
||||||
|
int rr = (blend.r * GPalette.BaseColors[i].r) / 255;
|
||||||
|
int gg = (blend.g * GPalette.BaseColors[i].g) / 255;
|
||||||
|
int bb = (blend.b * GPalette.BaseColors[i].b) / 255;
|
||||||
|
|
||||||
|
blendwork[i] = ColorMatcher.Pick(rr, gg, bb);
|
||||||
|
}
|
||||||
|
return blendwork;
|
||||||
|
}
|
||||||
|
else if (blend.a != 0)
|
||||||
|
{
|
||||||
|
for(int i=1;i<256;i++)
|
||||||
|
{
|
||||||
|
int rr = (blend.r * blend.a + GPalette.BaseColors[i].r * (255-blend.a)) / 255;
|
||||||
|
int gg = (blend.g * blend.a + GPalette.BaseColors[i].g * (255-blend.a)) / 255;
|
||||||
|
int bb = (blend.b * blend.a + GPalette.BaseColors[i].b * (255-blend.a)) / 255;
|
||||||
|
|
||||||
|
blendwork[i] = ColorMatcher.Pick(rr, gg, bb);
|
||||||
|
}
|
||||||
|
return blendwork;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// FMultiPatchTexture :: MakeTexture
|
// FMultiPatchTexture :: MakeTexture
|
||||||
|
@ -285,14 +351,20 @@ void FMultiPatchTexture::MakeTexture ()
|
||||||
// Add a little extra space at the end if the texture's height is not
|
// Add a little extra space at the end if the texture's height is not
|
||||||
// a power of 2, in case somebody accidentally makes it repeat vertically.
|
// a power of 2, in case somebody accidentally makes it repeat vertically.
|
||||||
int numpix = Width * Height + (1 << HeightBits) - Height;
|
int numpix = Width * Height + (1 << HeightBits) - Height;
|
||||||
|
BYTE blendwork[256];
|
||||||
|
|
||||||
Pixels = new BYTE[numpix];
|
Pixels = new BYTE[numpix];
|
||||||
memset (Pixels, 0, numpix);
|
memset (Pixels, 0, numpix);
|
||||||
|
|
||||||
for (int i = 0; i < NumParts; ++i)
|
for (int i = 0; i < NumParts; ++i)
|
||||||
{
|
{
|
||||||
|
BYTE *trans = Parts[i].Translation? Parts[i].Translation->Remap : NULL;
|
||||||
|
if (Parts[i].Blend != BLEND_NONE)
|
||||||
|
{
|
||||||
|
trans = GetBlendMap(Parts[i].Blend, blendwork);
|
||||||
|
}
|
||||||
Parts[i].Texture->CopyToBlock (Pixels, Width, Height,
|
Parts[i].Texture->CopyToBlock (Pixels, Width, Height,
|
||||||
Parts[i].OriginX, Parts[i].OriginY, Parts[i].Rotate);
|
Parts[i].OriginX, Parts[i].OriginY, Parts[i].Rotate, trans);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -310,7 +382,29 @@ int FMultiPatchTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rota
|
||||||
|
|
||||||
for(int i=0;i<NumParts;i++)
|
for(int i=0;i<NumParts;i++)
|
||||||
{
|
{
|
||||||
int ret = Parts[i].Texture->CopyTrueColorPixels(bmp, x+Parts[i].OriginX, y+Parts[i].OriginY, Parts[i].Rotate);
|
int ret;
|
||||||
|
|
||||||
|
if (!Parts[i].Texture->bComplex)
|
||||||
|
{
|
||||||
|
if (Parts[i].Translation != NULL)
|
||||||
|
{
|
||||||
|
// Using a translation forces downconversion to the base palette
|
||||||
|
ret = Parts[i].Texture->CopyTrueColorTranslated(bmp, x+Parts[i].OriginX, y+Parts[i].OriginY, Parts[i].Rotate, Parts[i].Translation);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (Parts[i].Blend != BLEND_NONE)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
ret = Parts[i].Texture->CopyTrueColorPixels(bmp, x+Parts[i].OriginX, y+Parts[i].OriginY, Parts[i].Rotate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If the patch is a texture with some kind of processing involved
|
||||||
|
// the copying must be done in 2 steps: First create a complete image of the patch
|
||||||
|
// including all processing and then copy from that intermediate image to the destination
|
||||||
|
}
|
||||||
|
|
||||||
if (ret > retv) retv = ret;
|
if (ret > retv) retv = ret;
|
||||||
}
|
}
|
||||||
|
@ -327,6 +421,7 @@ int FMultiPatchTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rota
|
||||||
|
|
||||||
FTextureFormat FMultiPatchTexture::GetFormat()
|
FTextureFormat FMultiPatchTexture::GetFormat()
|
||||||
{
|
{
|
||||||
|
if (bComplex) return TEX_RGB;
|
||||||
if (NumParts == 1) return Parts[0].Texture->GetFormat();
|
if (NumParts == 1) return Parts[0].Texture->GetFormat();
|
||||||
return UseBasePalette() ? TEX_Pal : TEX_RGB;
|
return UseBasePalette() ? TEX_Pal : TEX_RGB;
|
||||||
}
|
}
|
||||||
|
@ -343,6 +438,7 @@ FTextureFormat FMultiPatchTexture::GetFormat()
|
||||||
|
|
||||||
bool FMultiPatchTexture::UseBasePalette()
|
bool FMultiPatchTexture::UseBasePalette()
|
||||||
{
|
{
|
||||||
|
if (bComplex) return false;
|
||||||
for(int i=0;i<NumParts;i++)
|
for(int i=0;i<NumParts;i++)
|
||||||
{
|
{
|
||||||
if (!Parts[i].Texture->UseBasePalette()) return false;
|
if (!Parts[i].Texture->UseBasePalette()) return false;
|
||||||
|
@ -489,6 +585,8 @@ FMultiPatchTexture::TexPart::TexPart()
|
||||||
Rotate = 0;
|
Rotate = 0;
|
||||||
textureOwned = false;
|
textureOwned = false;
|
||||||
Texture = NULL;
|
Texture = NULL;
|
||||||
|
Translation = NULL;
|
||||||
|
Blend = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -501,6 +599,7 @@ FMultiPatchTexture::TexPart::~TexPart()
|
||||||
{
|
{
|
||||||
if (textureOwned && Texture != NULL) delete Texture;
|
if (textureOwned && Texture != NULL) delete Texture;
|
||||||
Texture = NULL;
|
Texture = NULL;
|
||||||
|
if (Translation != NULL) delete Translation;
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -673,6 +772,17 @@ void FTextureManager::AddTexturesLumps (int lump1, int lump2, int patcheslump)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool Check(char *& range, char c)
|
||||||
|
{
|
||||||
|
while (isspace(*range)) range++;
|
||||||
|
if (*range==c)
|
||||||
|
{
|
||||||
|
range++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void FMultiPatchTexture::ParsePatch(FScanner &sc, TexPart & part)
|
void FMultiPatchTexture::ParsePatch(FScanner &sc, TexPart & part)
|
||||||
{
|
{
|
||||||
FString patchname;
|
FString patchname;
|
||||||
|
@ -727,6 +837,110 @@ void FMultiPatchTexture::ParsePatch(FScanner &sc, TexPart & part)
|
||||||
}
|
}
|
||||||
part.Rotate = (sc.Number / 90) & 3;
|
part.Rotate = (sc.Number / 90) & 3;
|
||||||
}
|
}
|
||||||
|
else if (sc.Compare("Translation"))
|
||||||
|
{
|
||||||
|
bComplex = true;
|
||||||
|
if (part.Translation != NULL) delete part.Translation;
|
||||||
|
part.Translation = NULL;
|
||||||
|
part.Blend = 0;
|
||||||
|
static const char *maps[] = { "inverse", "gold", "red", "green", "ice", "desaturate", NULL };
|
||||||
|
int match = sc.MatchString(maps);
|
||||||
|
if (match >= 0)
|
||||||
|
{
|
||||||
|
part.Blend.r = 1 + match;
|
||||||
|
if (part.Blend.r == BLEND_DESATURATE1)
|
||||||
|
{
|
||||||
|
sc.MustGetStringName(",");
|
||||||
|
sc.MustGetNumber();
|
||||||
|
part.Blend.r += clamp(sc.Number-1, 0, 30);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
part.Translation = new FRemapTable;
|
||||||
|
part.Translation->MakeIdentity();
|
||||||
|
do
|
||||||
|
{
|
||||||
|
sc.MustGetString();
|
||||||
|
|
||||||
|
char *range = sc.String;
|
||||||
|
int start,end;
|
||||||
|
|
||||||
|
start=strtol(range, &range, 10);
|
||||||
|
if (!Check(range, ':')) return;
|
||||||
|
end=strtol(range, &range, 10);
|
||||||
|
if (!Check(range, '=')) return;
|
||||||
|
if (!Check(range, '['))
|
||||||
|
{
|
||||||
|
int pal1,pal2;
|
||||||
|
|
||||||
|
pal1=strtol(range, &range, 10);
|
||||||
|
if (!Check(range, ':')) return;
|
||||||
|
pal2=strtol(range, &range, 10);
|
||||||
|
|
||||||
|
part.Translation->AddIndexRange(start, end, pal1, pal2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// translation using RGB values
|
||||||
|
int r1,g1,b1,r2,g2,b2;
|
||||||
|
|
||||||
|
r1=strtol(range, &range, 10);
|
||||||
|
if (!Check(range, ',')) return;
|
||||||
|
g1=strtol(range, &range, 10);
|
||||||
|
if (!Check(range, ',')) return;
|
||||||
|
b1=strtol(range, &range, 10);
|
||||||
|
if (!Check(range, ']')) return;
|
||||||
|
if (!Check(range, ':')) return;
|
||||||
|
if (!Check(range, '[')) return;
|
||||||
|
r2=strtol(range, &range, 10);
|
||||||
|
if (!Check(range, ',')) return;
|
||||||
|
g2=strtol(range, &range, 10);
|
||||||
|
if (!Check(range, ',')) return;
|
||||||
|
b2=strtol(range, &range, 10);
|
||||||
|
if (!Check(range, ']')) return;
|
||||||
|
|
||||||
|
part.Translation->AddColorRange(start, end, r1, g1, b1, r2, g2, b2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (sc.CheckString(","));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (sc.Compare("Blend"))
|
||||||
|
{
|
||||||
|
bComplex = true;
|
||||||
|
if (part.Translation != NULL) delete part.Translation;
|
||||||
|
part.Translation = NULL;
|
||||||
|
part.Blend = 0;
|
||||||
|
|
||||||
|
if (!sc.CheckNumber())
|
||||||
|
{
|
||||||
|
part.Blend = V_GetColor(NULL, sc.String);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int r,g,b;
|
||||||
|
|
||||||
|
sc.MustGetNumber();
|
||||||
|
sc.MustGetStringName(",");
|
||||||
|
r = sc.Number;
|
||||||
|
sc.MustGetNumber();
|
||||||
|
sc.MustGetStringName(",");
|
||||||
|
g = sc.Number;
|
||||||
|
sc.MustGetNumber();
|
||||||
|
sc.MustGetStringName(",");
|
||||||
|
b = sc.Number;
|
||||||
|
part.Blend = MAKERGB(r, g, b);
|
||||||
|
}
|
||||||
|
if (sc.CheckString(","))
|
||||||
|
{
|
||||||
|
sc.MustGetFloat();
|
||||||
|
part.Blend.a = clamp<int>(int(sc.Float*255), 1, 254);
|
||||||
|
}
|
||||||
|
else part.Blend.a = 255;
|
||||||
|
bComplex = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Mirror & 2)
|
if (Mirror & 2)
|
||||||
|
|
|
@ -490,11 +490,11 @@ int FTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int FTexture::CopyTrueColorTranslated(FBitmap *bmp, int x, int y, FRemapTable *remap)
|
int FTexture::CopyTrueColorTranslated(FBitmap *bmp, int x, int y, int rotate, FRemapTable *remap)
|
||||||
{
|
{
|
||||||
PalEntry *palette = remap->Palette;
|
PalEntry *palette = remap->Palette;
|
||||||
palette[0].a=255; // temporarily modify the first color's alpha
|
palette[0].a=255; // temporarily modify the first color's alpha
|
||||||
bmp->CopyPixelData(x, y, GetPixels(), Width, Height, Height, 1, 0, palette);
|
bmp->CopyPixelData(x, y, GetPixels(), Width, Height, Height, 1, rotate, palette);
|
||||||
|
|
||||||
palette[0].a=0;
|
palette[0].a=0;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -64,6 +64,7 @@ BYTE GoldColormap[256];
|
||||||
// [BC] New Skulltag colormaps.
|
// [BC] New Skulltag colormaps.
|
||||||
BYTE RedColormap[256];
|
BYTE RedColormap[256];
|
||||||
BYTE GreenColormap[256];
|
BYTE GreenColormap[256];
|
||||||
|
BYTE DesaturateColormap[31][256];
|
||||||
|
|
||||||
static void FreeSpecialLights();;
|
static void FreeSpecialLights();;
|
||||||
|
|
||||||
|
@ -433,6 +434,24 @@ void InitPalette ()
|
||||||
MIN( 255, ( intensity + ( intensity / 2 )) >> 8 ),
|
MIN( 255, ( intensity + ( intensity / 2 )) >> 8 ),
|
||||||
intensity>>8 );
|
intensity>>8 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// desaturated colormaps
|
||||||
|
for(int m = 0; m < 31; m++)
|
||||||
|
{
|
||||||
|
shade = DesaturateColormap[m];
|
||||||
|
for (c = 0; c < 256; c++)
|
||||||
|
{
|
||||||
|
intensity = GPalette.BaseColors[c].r * 77 +
|
||||||
|
GPalette.BaseColors[c].g * 143 +
|
||||||
|
GPalette.BaseColors[c].b * 37;
|
||||||
|
|
||||||
|
int r = (GPalette.BaseColors[c].r * (31-m) + intensity *m) / 31;
|
||||||
|
int g = (GPalette.BaseColors[c].g * (31-m) + intensity *m) / 31;
|
||||||
|
int b = (GPalette.BaseColors[c].b * (31-m) + intensity *m) / 31;
|
||||||
|
shade[c] = ColorMatcher.Pick (r, g, b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
|
|
|
@ -85,6 +85,7 @@ extern BYTE GoldColormap[256];
|
||||||
// [BC] New Skulltag colormaps.
|
// [BC] New Skulltag colormaps.
|
||||||
extern BYTE RedColormap[256];
|
extern BYTE RedColormap[256];
|
||||||
extern BYTE GreenColormap[256];
|
extern BYTE GreenColormap[256];
|
||||||
|
extern BYTE DesaturateColormap[31][256];
|
||||||
extern FPalette GPalette;
|
extern FPalette GPalette;
|
||||||
extern "C" {
|
extern "C" {
|
||||||
extern FDynamicColormap NormalLight;
|
extern FDynamicColormap NormalLight;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<?xml version="1.0" encoding="Windows-1252"?>
|
<?xml version="1.0" encoding="Windows-1252"?>
|
||||||
<VisualStudioProject
|
<VisualStudioProject
|
||||||
ProjectType="Visual C++"
|
ProjectType="Visual C++"
|
||||||
Version="8.00"
|
Version="8,00"
|
||||||
Name="updaterevision"
|
Name="updaterevision"
|
||||||
ProjectGUID="{6077B7D6-349F-4077-B552-3BC302EF5859}"
|
ProjectGUID="{6077B7D6-349F-4077-B552-3BC302EF5859}"
|
||||||
RootNamespace="updaterevision"
|
RootNamespace="updaterevision"
|
||||||
|
@ -95,82 +95,6 @@
|
||||||
Name="VCPostBuildEventTool"
|
Name="VCPostBuildEventTool"
|
||||||
/>
|
/>
|
||||||
</Configuration>
|
</Configuration>
|
||||||
<Configuration
|
|
||||||
Name="Debug|x64"
|
|
||||||
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
|
|
||||||
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
|
|
||||||
ConfigurationType="1"
|
|
||||||
CharacterSet="1"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCPreBuildEventTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCXMLDataGeneratorTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCWebServiceProxyGeneratorTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCMIDLTool"
|
|
||||||
TargetEnvironment="3"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
Optimization="0"
|
|
||||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
|
|
||||||
MinimalRebuild="true"
|
|
||||||
BasicRuntimeChecks="3"
|
|
||||||
RuntimeLibrary="3"
|
|
||||||
UsePrecompiledHeader="0"
|
|
||||||
WarningLevel="3"
|
|
||||||
Detect64BitPortabilityProblems="true"
|
|
||||||
DebugInformationFormat="3"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCManagedResourceCompilerTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCResourceCompilerTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCPreLinkEventTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCLinkerTool"
|
|
||||||
LinkIncremental="2"
|
|
||||||
GenerateDebugInformation="true"
|
|
||||||
SubSystem="1"
|
|
||||||
TargetMachine="17"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCALinkTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCManifestTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCXDCMakeTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCBscMakeTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCFxCopTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCAppVerifierTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCWebDeploymentTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCPostBuildEventTool"
|
|
||||||
/>
|
|
||||||
</Configuration>
|
|
||||||
<Configuration
|
<Configuration
|
||||||
Name="Release|Win32"
|
Name="Release|Win32"
|
||||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||||
|
@ -248,6 +172,82 @@
|
||||||
Name="VCPostBuildEventTool"
|
Name="VCPostBuildEventTool"
|
||||||
/>
|
/>
|
||||||
</Configuration>
|
</Configuration>
|
||||||
|
<Configuration
|
||||||
|
Name="Debug|x64"
|
||||||
|
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
|
||||||
|
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||||
|
ConfigurationType="1"
|
||||||
|
CharacterSet="1"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXMLDataGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
TargetEnvironment="3"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
Optimization="0"
|
||||||
|
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
|
||||||
|
MinimalRebuild="true"
|
||||||
|
BasicRuntimeChecks="3"
|
||||||
|
RuntimeLibrary="3"
|
||||||
|
UsePrecompiledHeader="0"
|
||||||
|
WarningLevel="3"
|
||||||
|
Detect64BitPortabilityProblems="true"
|
||||||
|
DebugInformationFormat="3"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManagedResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
LinkIncremental="2"
|
||||||
|
GenerateDebugInformation="true"
|
||||||
|
SubSystem="1"
|
||||||
|
TargetMachine="17"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCALinkTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManifestTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXDCMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCBscMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCFxCopTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCAppVerifierTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebDeploymentTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"
|
||||||
|
/>
|
||||||
|
</Configuration>
|
||||||
<Configuration
|
<Configuration
|
||||||
Name="Release|x64"
|
Name="Release|x64"
|
||||||
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
|
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
|
||||||
|
|
Loading…
Reference in a new issue