Added remaster units support, Image_t now supports multiple image resolutions per shape.

This commit is contained in:
Justin Marshall
2020-06-21 14:56:25 -07:00
parent c124589708
commit 95e0bbb3aa
14 changed files with 223 additions and 38 deletions
+1
View File
@@ -427,6 +427,7 @@ set(src_redalert
./RedAlert/OPTIONS.H
./RedAlert/OVERLAY.CPP
./RedAlert/OVERLAY.H
./RedAlert/UNITXML.CPP
./RedAlert/PACKET.CPP
./RedAlert/PACKET.H
./RedAlert/PALETTEC.CPP
+13 -10
View File
@@ -3173,15 +3173,18 @@ void BuildingTypeClass::One_Time(void)
}
image->numFrames = numBuildingAnims;
((void const*&)building.HDImageData) = image;
}
if (building.ImageData != NULL && building.HDImageData != NULL) {
int width = Get_Build_Frame_Width(building.ImageData);
int height = Get_Build_Frame_Height(building.ImageData);
if (building.ImageData != NULL && building.HDImageData != NULL) {
int width = Get_Build_Frame_Width(building.ImageData);
int height = Get_Build_Frame_Height(building.ImageData);
building.HDImageData->renderwidth = width;
building.HDImageData->renderheight = height;
}
for (int d = 0; d < shapeId; d++)
{
building.HDImageData->renderwidth[d] = width;
building.HDImageData->renderheight[d] = height;
}
}
}
}
}
@@ -3261,7 +3264,7 @@ void BuildingTypeClass::Display(int x, int y, WindowNumberType window, HousesTyp
//CC_Draw_Shape((Image_t *)Get_HDImage_Data(), 0, x, y, window, SHAPE_CENTER | SHAPE_WIN_REL, NULL, NULL, DIR_N);
x += WindowList[window][WINDOWX];
y += WindowList[window][WINDOWY];
GL_RenderImage(hdimage, x, y, hdimage->renderwidth, hdimage->renderheight);
GL_RenderImage(hdimage, x, y, hdimage->renderwidth[0], hdimage->renderheight[0]);
}
else {
void const* ptr = Get_Cameo_Data();
@@ -3458,8 +3461,8 @@ void BuildingTypeClass::Init(TheaterType theater)
int width = Get_Build_Frame_Width(classptr->ImageData);
int height = Get_Build_Frame_Height(classptr->ImageData);
classptr->HDImageData->renderwidth = width;
classptr->HDImageData->renderheight = height;
classptr->HDImageData->renderwidth[0] = width;
classptr->HDImageData->renderheight[0] = height;
}
}
// jmarshall end
+2 -2
View File
@@ -3499,8 +3499,8 @@ void CC_Draw_Shape(Image_t* image, int shapenum, int x, int y, WindowNumberType
if (image != NULL && shapenum != -1) {
int width = image->renderwidth;
int height = image->renderheight;
int width = image->renderwidth[shapenum];
int height = image->renderheight[shapenum];
#ifdef NEVER
/*
+3 -3
View File
@@ -229,11 +229,11 @@ void Console_Printf(const char* fmt, ...) {
vsprintf(msg, fmt, argptr);
va_end(argptr);
int len = strlen(msg);
strcpy(&console_text[console_text_len], msg);
//int len = strlen(msg);
//strcpy(&console_text[console_text_len], msg);
OutputDebugStringA(msg);
console_text_len += len;
//console_text_len += len;
}
/*
+3
View File
@@ -1181,11 +1181,14 @@ __forceinline void COM_SetExtension(char* path, int maxSize, const char* extensi
void Tileset_LoadRules(void);
void Buildings_LoadRules(void);
void Units_LoadRules(void);
const char* Tileset_FindHDTexture(int theaterType, const char* shapeFileName, int shapeNum, int frameNum);
int Tileset_GetNumFramesForTile(int theaterType, const char* shapeFileName, int shapeNum);
int Buildings_GetNumFramesForTile(const char* shapeFileName, int shapeNum);
const char* Buildings_FindHDTexture(const char* shapeFileName, int shapeNum, int frameNum);
int Units_GetNumFramesForTile(const char* shapeFileName, int shapeNum);
const char* Units_FindHDTexture(const char* shapeFileName, int shapeNum, int frameNum);
extern bool g_inMainMenu;
extern KeyNumType g_globalKeyNumType;
+4 -2
View File
@@ -19,8 +19,9 @@ struct Image_t {
unsigned int numAnimFrames;
int width;
int height;
int renderwidth;
int renderheight;
int renderwidth[MAX_IMAGE_SHAPES];
int renderheight[MAX_IMAGE_SHAPES];
bool perFrameRenderDimen;
int numFrames;
void* IconMapPtr;
};
@@ -28,6 +29,7 @@ struct Image_t {
__forceinline Image_t::Image_t() {
IconMapPtr = NULL;
numAnimFrames = 0;
perFrameRenderDimen = false;
memset(HouseImages, 0, sizeof(HouseImages));
}
+1
View File
@@ -390,6 +390,7 @@ int PASCAL WinMain ( HINSTANCE instance , HINSTANCE , char * command_line , int
// Load all of the XML files.
Tileset_LoadRules();
Buildings_LoadRules();
Units_LoadRules();
if (Parse_Command_Line(argc, argv)) {
+11 -7
View File
@@ -248,12 +248,14 @@ Image_t* Load_StampHD(int theater, const char* iconName, const void* icondata) {
return image;
}
void Get_Stamp_Size(const void* icondata, int& width, int& height) {
void Get_Stamp_Size(const void* icondata, int* width, int* height) {
IconControlType* tileset = (IconControlType*)icondata;
if (!tileset) {
width = -1;
height = -1;
for (int i = 0; i < MAX_IMAGE_SHAPES; i++) {
*width = -1;
*height = -1;
}
return;
}
@@ -261,8 +263,10 @@ void Get_Stamp_Size(const void* icondata, int& width, int& height) {
Init_Stamps(tileset);
}
width = IconWidth;
height = IconHeight;
for (int i = 0; i < MAX_IMAGE_SHAPES; i++) {
width[i] = IconWidth;
height[i] = IconHeight;
}
}
Image_t * Load_Stamp(const char *name, const void* icondata)
@@ -314,8 +318,8 @@ void __cdecl Buffer_Draw_Stamp_Clip2(GraphicViewPortClass& viewport, const void
uint8_t* MapPtr = (uint8_t * )iconImage->IconMapPtr;
int icon_index = MapPtr != nullptr ? MapPtr[icon] : icon;
{
int blit_height = iconImage->renderheight;
int blit_width = iconImage->renderwidth;
int blit_height = iconImage->renderheight[0];
int blit_width = iconImage->renderwidth[0];
int width = left + right;
int xstart = left + x;
+43 -1
View File
@@ -48,6 +48,7 @@
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "function.h"
#include "image.h"
/*
** This is the list of animation stages to use when the harvester
@@ -1113,10 +1114,51 @@ void UnitTypeClass::One_Time(void)
((void const *&)uclass.ImageData) = ptr;
if (ptr != NULL) {
largest = max(largest, (int)Get_Build_Frame_Width(ptr));
largest = max(largest, (int)Get_Build_Frame_Height(ptr));
}
{
const char* imageFileName = Units_FindHDTexture(fullname, 0, 0);
if (imageFileName) {
Image_t* image = Image_LoadImage(imageFileName, true, true);
int numUnitsAnims = Units_GetNumFramesForTile(fullname, 0);
int shapeId = 1;
// Load the old school animation pipeline.
{
while (true) {
imageFileName = Units_FindHDTexture(fullname, shapeId, 0);
if (imageFileName == NULL)
break;
for (int d = 0; d < MAX_MPLAYER_COLORS; d++) {
Image_Add32BitImage(imageFileName, image, d, shapeId, 0);
}
shapeId++;
}
}
for (int d = 0; d < shapeId; d++) {
image->renderwidth[d] = image->renderwidth[d] / 5;
image->renderheight[d] = image->renderheight[d] / 5;
}
if (numUnitsAnims > 0)
{
for (int i = 1; i < numUnitsAnims; i++) {
imageFileName = Units_FindHDTexture(fullname, 0, i);
for (int d = 0; d < MAX_MPLAYER_COLORS; d++) {
Image_Add32BitImage(imageFileName, image, d, 0, i);
}
}
}
image->numFrames = numUnitsAnims;
((void const*&)uclass.HDImageData) = image;
}
}
((int &)uclass.MaxSize) = max(largest, 8);
}
+32 -5
View File
@@ -2051,11 +2051,13 @@ void UnitClass::Draw_It(int x, int y, WindowNumberType window) const
int tfacing = Dir_To_32(SecondaryFacing);
DirType rotation = DIR_N;
int scale = 0x0100;
Image_t* hdShapeFile;
/*
** Verify the legality of the unit class.
*/
shapefile = Get_Image_Data();
hdShapeFile = Get_HDImage_Data();
if (shapefile == NULL) return;
/*
@@ -2076,7 +2078,12 @@ void UnitClass::Draw_It(int x, int y, WindowNumberType window) const
/*
** Actually perform the draw. Overlay an optional shimmer effect as necessary.
*/
Techno_Draw_Object(shapefile, shapenum, x, y, window, rotation, scale);
if (hdShapeFile) {
Techno_Draw_Object_HD(hdShapeFile, shapenum, x, y, window, rotation, scale);
}
else {
Techno_Draw_Object(shapefile, shapenum, x, y, window, rotation, scale);
}
/*
** If there is a rotating radar dish, draw it now.
@@ -2086,7 +2093,12 @@ void UnitClass::Draw_It(int x, int y, WindowNumberType window) const
int x2 = x, y2 = y;
shapenum = 32 + (Frame & 7);
Class->Turret_Adjust(PrimaryFacing, x2, y2);
Techno_Draw_Object(shapefile, shapenum, x2, y2, window);
if (hdShapeFile) {
Techno_Draw_Object_HD(hdShapeFile, shapenum, x, y, window);
}
else {
Techno_Draw_Object(shapefile, shapenum, x2, y2, window);
}
} else {
//#ifdef FIXIT_PHASETRANSPORT // checked - ajw 9/28/98
// if (*this == UNIT_PHASE) {
@@ -2099,9 +2111,19 @@ void UnitClass::Draw_It(int x, int y, WindowNumberType window) const
//#endif
#ifdef FIXIT_CSII // checked - ajw 9/28/98
if (*this == UNIT_TESLATANK) {
Techno_Draw_Object(shapefile, shapenum, x, y, window);
if (hdShapeFile) {
Techno_Draw_Object_HD(hdShapeFile, shapenum, x, y, window);
}
else {
Techno_Draw_Object(shapefile, shapenum, x, y, window);
}
} else {
Techno_Draw_Object(shapefile, shapenum, x, y-5, window);
if (hdShapeFile) {
Techno_Draw_Object_HD(hdShapeFile, shapenum, x, y - 5, window);
}
else {
Techno_Draw_Object(shapefile, shapenum, x, y - 5, window);
}
}
#else
Techno_Draw_Object(shapefile, shapenum, x, y-5, window);
@@ -2139,7 +2161,12 @@ void UnitClass::Draw_It(int x, int y, WindowNumberType window) const
/*
** Actually perform the draw. Overlay an optional shimmer effect as necessary.
*/
Techno_Draw_Object(shapefile, shapenum, xx, yy, window);
if (hdShapeFile) {
Techno_Draw_Object_HD(hdShapeFile, shapenum, xx, yy - 4, window); // jmarshall - 4 pixel offset for turrets feels wrong, but visually looks alright.
}
else {
Techno_Draw_Object(shapefile, shapenum, xx, yy, window);
}
}
}
+99
View File
@@ -0,0 +1,99 @@
// UNITXML.CPP
//
#include "FUNCTION.H"
#include "tinyxml2.h"
#include <string>
#include <vector>
int64_t generateHashValue(const char* fname, const int size);
struct UnitsTileRule_t {
std::string name;
int64_t hash;
int shape;
std::vector<std::string> frames;
};
struct UnitsXMLInfo_t {
std::vector<UnitsTileRule_t> tiles;
};
UnitsXMLInfo_t unitsXmlRules;
const char* Units_FindHDTexture(const char* shapeFileName, int shapeNum, int frameNum) {
char tmpFileName[2048];
strcpy(tmpFileName, shapeFileName);
COM_SetExtension(tmpFileName, strlen(tmpFileName), "");
int64_t hash = generateHashValue(tmpFileName, strlen(tmpFileName));
for (int i = 0; i < unitsXmlRules.tiles.size(); i++) {
if (unitsXmlRules.tiles[i].hash == hash && unitsXmlRules.tiles[i].shape == shapeNum) {
static char hdTexturePath[2048];
if (unitsXmlRules.tiles[i].frames.size() == 0)
return NULL;
sprintf(hdTexturePath, "DATA/ART/TEXTURES/SRGB/RED_ALERT/UNITS/%s", unitsXmlRules.tiles[i].frames[frameNum].c_str());
return &hdTexturePath[0];
}
}
return NULL;
}
int Units_GetNumFramesForTile(const char* shapeFileName, int shapeNum) {
char tmpFileName[2048];
strcpy(tmpFileName, shapeFileName);
COM_SetExtension(tmpFileName, strlen(tmpFileName), "");
int64_t hash = generateHashValue(tmpFileName, strlen(tmpFileName));
for (int i = 0; i < unitsXmlRules.tiles.size(); i++) {
if (unitsXmlRules.tiles[i].hash == hash && unitsXmlRules.tiles[i].shape == shapeNum) {
return unitsXmlRules.tiles[i].frames.size();
}
}
return 0;
}
void Units_ParseTile(tinyxml2::XMLNode* tile, UnitsTileRule_t& tileRule) {
tinyxml2::XMLNode* KeyNode = tile->FirstChildElement("Key");
tinyxml2::XMLNode* NameNode = KeyNode->FirstChildElement("Name");
tinyxml2::XMLNode* ShapeNode = KeyNode->FirstChildElement("Shape");
tinyxml2::XMLNode* ValueNode = tile->FirstChildElement("Value");
tinyxml2::XMLNode* FramesNode = ValueNode->FirstChildElement("Frames");
tinyxml2::XMLNode* FrameNode = FramesNode->FirstChildElement("Frame");
tileRule.name = NameNode->FirstChild()->ToText()->Value();
tileRule.hash = generateHashValue(tileRule.name.c_str(), tileRule.name.size());
tileRule.shape = atoi(ShapeNode->FirstChild()->ToText()->Value());
while (FrameNode != NULL) {
if (FrameNode->FirstChild() != NULL) {
tileRule.frames.push_back(FrameNode->FirstChild()->ToText()->Value());
}
FrameNode = FrameNode->NextSiblingElement("Frame");
}
}
void Units_LoadRuleXML(const char* path, UnitsXMLInfo_t& info) {
tinyxml2::XMLDocument doc;
doc.LoadFile(path);
tinyxml2::XMLElement* root = doc.FirstChildElement();
if (root == NULL)
return;
tinyxml2::XMLNode* tilesetTypeClassNode = root->FirstChild();
tinyxml2::XMLNode* tilesParent = tilesetTypeClassNode->FirstChildElement("Tiles");
tinyxml2::XMLNode* tile = tilesParent->FirstChildElement("Tile");
while (tile != NULL) {
UnitsTileRule_t tileRule;
Units_ParseTile(tile, tileRule);
info.tiles.push_back(tileRule);
tile = tile->NextSiblingElement("Tile");
}
}
void Units_LoadRules(void) {
Units_LoadRuleXML("data/xml/tilesets/RA_UNITS.XML", unitsXmlRules);
}
+1 -1
View File
@@ -64,7 +64,7 @@ extern "C" {
struct Image_t;
Image_t* Load_Stamp(const char* name, const void* icondata);
void Get_Stamp_Size(const void* icondata, int &width, int &height);
void Get_Stamp_Size(const void* icondata, int *width, int *height);
Image_t* Load_StampHD(int theater, const char* iconName, const void *icondata);
extern GraphicViewPortClass *LogicPage;
+9 -6
View File
@@ -241,14 +241,17 @@ static bool Image_loadHDImage(Image_t *image, const char* name, int houseid, int
else
image->HouseImages[houseid].image[animid][frameId] = texture;
image->namehash = hash;
image->renderwidth = image->width = Width;
image->renderheight = image->height = Height;
image->renderwidth[animid] = image->width = Width;
image->renderheight[animid] = image->height = Height;
//image->buffer[houseid][animid] = new unsigned char[Width * Height * Bpp];
//memcpy(image->buffer[houseid][animid], Data, Width * Height * Bpp);
if (!writeGenerated && Bpp == 4 && houseid >= 0) {
char* generatedImageName = Image_GetGeneratedName(image, name, houseid, animid, frameId, hash);
Image_WriteTGA(generatedImageName, Data, Width, Height, false);
Console_Printf("Writing %s to cache %s\n", image->name, name);
Sleep(0);
}
ilDeleteImages(1, &ImageName);
@@ -376,8 +379,8 @@ Image_t* Image_CreateImageFrom8Bit(const char* name, int Width, int Height, unsi
image->HouseImages[0].image[0][0] = texture;
image->numAnimFrames = -1;
image->namehash = hash;
image->renderwidth = image->width = Width;
image->renderheight = image->height = Height;
image->renderwidth[0] = image->width = Width;
image->renderheight[0] = image->height = Height;
loaded_images.push_back(image);
delete buffer;
return image;
@@ -431,8 +434,8 @@ void Image_Add8BitImage(Image_t *image, int HouseId, int ShapeID, int Width, int
image->HouseImages[HouseId].image[ShapeID][0] = texture;
image->numAnimFrames = -1;
image->renderwidth = image->width = Width;
image->renderheight = image->height = Height;
image->renderwidth[ShapeID] = image->width = Width;
image->renderheight[ShapeID] = image->height = Height;
delete buffer;
}
+1 -1
View File
@@ -1684,7 +1684,7 @@ void UnitTypeClass::One_Time(void)
}
#endif //PETROGLYPH_EXAMPLE_MOD
((void const *&)uclass.ImageData) = ptr;
((void const *&)uclass.ImageData) = ptr;
if (ptr) {
if (index == UNIT_MLRS || index == UNIT_MSAM) {