mirror of
https://github.com/jmarshall23/CnC_Remastered_Collection.git
synced 2026-08-12 08:00:55 +02:00
Added remaster units support, Image_t now supports multiple image resolutions per shape.
This commit is contained in:
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
/*
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user