From dac4c157cf543981bf6e20b40a712a1bbf4b1b0f Mon Sep 17 00:00:00 2001 From: Justin Marshall Date: Sat, 20 Jun 2020 20:29:25 -0700 Subject: [PATCH] Added animation support for the HD remaster assets, idle terrain animations work. --- code/REDALERT/CONQUER.CPP | 1 + code/REDALERT/FUNCTION.H | 4 ++- code/REDALERT/Image.h | 15 ++++++++--- code/REDALERT/NEWBLIT.CPP | 12 ++++++++- code/REDALERT/TILESET.CPP | 40 +++++++++++++++++++----------- code/REDALERT/TILESETXML.CPP | 23 ++++++++++++++--- code/REDALERT/WIN32LIB/MOUSEWW.CPP | 2 +- code/REDALERT/WINSTUB.CPP | 23 +++++++++-------- 8 files changed, 84 insertions(+), 36 deletions(-) diff --git a/code/REDALERT/CONQUER.CPP b/code/REDALERT/CONQUER.CPP index 4787c38..dd76f5c 100644 --- a/code/REDALERT/CONQUER.CPP +++ b/code/REDALERT/CONQUER.CPP @@ -2138,6 +2138,7 @@ static void Sync_Delay(void) Map.Render(); } } + animFrameNum+=0.5f; // This is garbage and needs to be fixed with proper delta time bits!!! if (!FrameTimer) { Color_Cycle(); Call_Back(); diff --git a/code/REDALERT/FUNCTION.H b/code/REDALERT/FUNCTION.H index d659732..d90273e 100644 --- a/code/REDALERT/FUNCTION.H +++ b/code/REDALERT/FUNCTION.H @@ -1180,9 +1180,11 @@ __forceinline void COM_SetExtension(char* path, int maxSize, const char* extensi } void Tileset_LoadRules(void); -const char* Tileset_FindHDTexture(int theaterType, const char* shapeFileName, int shapeNum); +const char* Tileset_FindHDTexture(int theaterType, const char* shapeFileName, int shapeNum, int frameNum); +int Tileset_GetNumFramesForTile(int theaterType, const char* shapeFileName, int shapeNum); extern bool g_inMainMenu; extern KeyNumType g_globalKeyNumType; extern int g_globalKeyFlags; +extern float animFrameNum; #endif \ No newline at end of file diff --git a/code/REDALERT/Image.h b/code/REDALERT/Image.h index fe5302f..ff224fa 100644 --- a/code/REDALERT/Image.h +++ b/code/REDALERT/Image.h @@ -1,27 +1,34 @@ // Image.h // -#define MAX_IMAGE_FRAMES 256 +#define MAX_IMAGE_SHAPES 256 +#define MAX_IMAGE_FRAMES 12 #define MAX_HOUSE_COLORS 8 + +struct HouseImage_t { + unsigned int image[MAX_IMAGE_SHAPES][MAX_IMAGE_FRAMES]; +}; + struct Image_t { Image_t(); ~Image_t(); char name[512]; int64_t namehash; - unsigned int image[MAX_HOUSE_COLORS][MAX_IMAGE_FRAMES]; + HouseImage_t HouseImages[MAX_HOUSE_COLORS]; unsigned int numAnimFrames; int width; int height; int renderwidth; int renderheight; + int numFrames; void* IconMapPtr; }; __forceinline Image_t::Image_t() { IconMapPtr = NULL; numAnimFrames = 0; - memset(image, 0, sizeof(image)); + memset(HouseImages, 0, sizeof(HouseImages)); } __forceinline Image_t::~Image_t() { @@ -31,4 +38,4 @@ Image_t* Image_LoadImage(const char* name, bool loadAnims = false, bool loadHous Image_t* Image_CreateImageFrom8Bit(const char* name, int Width, int Height, unsigned char* data, unsigned char *remap = NULL); Image_t* Find_Image(const char* name); void Image_Add8BitImage(Image_t* image, int HouseId, int ShapeID, int Width, int Height, unsigned char* data, unsigned char* remap); -bool Image_Add32BitImage(const char* name, Image_t* image, int HouseId, int ShapeID); \ No newline at end of file +bool Image_Add32BitImage(const char* name, Image_t* image, int HouseId, int ShapeID, int frameId); \ No newline at end of file diff --git a/code/REDALERT/NEWBLIT.CPP b/code/REDALERT/NEWBLIT.CPP index cccf6d0..08610f9 100644 --- a/code/REDALERT/NEWBLIT.CPP +++ b/code/REDALERT/NEWBLIT.CPP @@ -21,7 +21,17 @@ void GL_ResetClipRect(void) { void GL_RenderImage(Image_t* image, int x, int y, int width, int height, int colorRemap, int shapeId) { ImVec2 mi(x, y); ImVec2 ma(x + width, y + height); - ImGui::GetForegroundDrawList()->AddImage((ImTextureID)image->image[colorRemap][shapeId], mi, ma); + + if (image->numFrames > 0) { + if(image->HouseImages[colorRemap].image[shapeId][((int)animFrameNum) % image->numFrames] == 0) + ImGui::GetForegroundDrawList()->AddImage((ImTextureID)image->HouseImages[colorRemap].image[shapeId][0], mi, ma); + else + ImGui::GetForegroundDrawList()->AddImage((ImTextureID)image->HouseImages[colorRemap].image[shapeId][((int)animFrameNum) % image->numFrames], mi, ma); + } + else { + ImGui::GetForegroundDrawList()->AddImage((ImTextureID)image->HouseImages[colorRemap].image[shapeId][0], mi, ma); + } + } void GL_FillRect(int color, int x, int y, int width, int height) { diff --git a/code/REDALERT/TILESET.CPP b/code/REDALERT/TILESET.CPP index 8b92202..b4498dd 100644 --- a/code/REDALERT/TILESET.CPP +++ b/code/REDALERT/TILESET.CPP @@ -207,26 +207,36 @@ Image_t* Load_StampHD(int theater, const char* iconName, const void* icondata) { // This is because were trying to avoid parsing the XML's and the filenames aren't consistant. const char* theaterName = Theaters[theater].Name; for (int i = 0; i < IconCount; i++) - { + { char filename[512]; char fixedIconName[512]; strcpy(fixedIconName, iconName); COM_SetExtension(fixedIconName, strlen(fixedIconName), ""); - const char* tileEntryName = Tileset_FindHDTexture(theater, fixedIconName, i); - sprintf(filename, "DATA/ART/TEXTURES/SRGB/RED_ALERT/TERRAIN/%s/%s", Theaters[theater].Name, tileEntryName); - COM_SetExtension(filename, sizeof(filename), ".dds"); - - if (image == NULL) { - image = Image_LoadImage(filename); - if (image != NULL && i != 0) { - image->image[0][i] = image->image[0][0]; - image->image[0][0] = 0; + int numFrames = Tileset_GetNumFramesForTile(theater, fixedIconName, i); + + for (int d = 0; d < numFrames; d++) + { + const char* tileEntryName = Tileset_FindHDTexture(theater, fixedIconName, i, d); + sprintf(filename, "DATA/ART/TEXTURES/SRGB/RED_ALERT/TERRAIN/%s/%s", Theaters[theater].Name, tileEntryName); + COM_SetExtension(filename, sizeof(filename), ".dds"); + + if (image == NULL) { + image = Image_LoadImage(filename); + + if (image != NULL && i != 0) { + image->HouseImages[0].image[i][d] = image->HouseImages[0].image[0][d]; + image->HouseImages[0].image[0][d] = 0; + } + + if (image != NULL) { + image->numFrames = numFrames; + } } - } - else { - if (!Image_Add32BitImage(filename, image, -1, i)) { - continue; + else { + if (!Image_Add32BitImage(filename, image, -1, i, d)) { + continue; + } } } } @@ -385,7 +395,7 @@ void __cdecl Buffer_Draw_Stamp_Clip2(GraphicViewPortClass& viewport, const void // src += IconWidth; //} - if (iconImage->image[0][icon_index] == 0) + if (iconImage->HouseImages[0].image[icon_index] == 0) return; GL_SetClipRect(xstart, ystart, blit_width, blit_height); diff --git a/code/REDALERT/TILESETXML.CPP b/code/REDALERT/TILESETXML.CPP index e2c94e3..7dd10e9 100644 --- a/code/REDALERT/TILESETXML.CPP +++ b/code/REDALERT/TILESETXML.CPP @@ -22,16 +22,26 @@ struct TilesetXMLInfo_t { TilesetXMLInfo_t theaterXMLRules[3]; -const char* Tileset_FindHDTexture(int theaterType, const char* shapeFileName, int shapeNum) { +const char* Tileset_FindHDTexture(int theaterType, const char* shapeFileName, int shapeNum, int frameNum) { int64_t hash = generateHashValue(shapeFileName, strlen(shapeFileName)); for (int i = 0; i < theaterXMLRules[theaterType].tiles.size(); i++) { if (theaterXMLRules[theaterType].tiles[i].hash == hash && theaterXMLRules[theaterType].tiles[i].shape == shapeNum) { - return theaterXMLRules[theaterType].tiles[i].frames[0].c_str(); + return theaterXMLRules[theaterType].tiles[i].frames[frameNum].c_str(); } } return NULL; } +int Tileset_GetNumFramesForTile(int theaterType, const char* shapeFileName, int shapeNum) { + int64_t hash = generateHashValue(shapeFileName, strlen(shapeFileName)); + for (int i = 0; i < theaterXMLRules[theaterType].tiles.size(); i++) { + if (theaterXMLRules[theaterType].tiles[i].hash == hash && theaterXMLRules[theaterType].tiles[i].shape == shapeNum) { + return theaterXMLRules[theaterType].tiles[i].frames.size(); + } + } + return 0; +} + void Tileset_ParseTile(tinyxml2::XMLNode* tile, TilesetTileRule_t& tileRule) { tinyxml2::XMLNode* KeyNode = tile->FirstChildElement("Key"); tinyxml2::XMLNode* NameNode = KeyNode->FirstChildElement("Name"); @@ -43,7 +53,11 @@ void Tileset_ParseTile(tinyxml2::XMLNode* tile, TilesetTileRule_t& tileRule) { tileRule.name = NameNode->FirstChild()->ToText()->Value(); tileRule.hash = generateHashValue(tileRule.name.c_str(), tileRule.name.size()); tileRule.shape = atoi(ShapeNode->FirstChild()->ToText()->Value()); - tileRule.frames.push_back(FrameNode->FirstChild()->ToText()->Value()); + + while (FrameNode != NULL) { + tileRule.frames.push_back(FrameNode->FirstChild()->ToText()->Value()); + FrameNode = FrameNode->NextSiblingElement("Frame"); + } } void Tileset_LoadRuleXML(const char* path, TilesetXMLInfo_t& info) { @@ -51,6 +65,9 @@ void Tileset_LoadRuleXML(const char* path, TilesetXMLInfo_t& info) { doc.LoadFile(path); tinyxml2::XMLElement* root = doc.FirstChildElement(); + if (root == NULL) + return; + tinyxml2::XMLNode* tilesetTypeClassNode = root->FirstChild(); tinyxml2::XMLNode* tilesParent = tilesetTypeClassNode->FirstChildElement("Tiles"); diff --git a/code/REDALERT/WIN32LIB/MOUSEWW.CPP b/code/REDALERT/WIN32LIB/MOUSEWW.CPP index 91c07fb..0d89cd9 100644 --- a/code/REDALERT/WIN32LIB/MOUSEWW.CPP +++ b/code/REDALERT/WIN32LIB/MOUSEWW.CPP @@ -252,7 +252,7 @@ void WWMouseClass::RenderMouse(void) { ImGui::SetMouseCursor(ImGuiMouseCursor_None); - ImGui::GetForegroundDrawList()->AddImage((ImTextureID)current_cursor->image[0][0], mi, ma); + ImGui::GetForegroundDrawList()->AddImage((ImTextureID)current_cursor->HouseImages[0].image[0][0], mi, ma); } void WWMouseClass::Low_Show_Mouse(int x, int y) diff --git a/code/REDALERT/WINSTUB.CPP b/code/REDALERT/WINSTUB.CPP index ba8614e..a105a1d 100644 --- a/code/REDALERT/WINSTUB.CPP +++ b/code/REDALERT/WINSTUB.CPP @@ -77,6 +77,7 @@ SurfaceMonitorClass AllSurfaces; SDL_Window* game_window; SDL_GLContext game_context; int OverlappedVideoBlits = 0; +float animFrameNum = 0; extern std::vector renderedFrameObjects; @@ -163,12 +164,12 @@ static char* Image_GetGeneratedName(Image_t* image, const char* name, int housei return &generatedFileName[0]; } -static bool Image_loadHDImage(Image_t *image, const char* name, int houseid, int animid, int64_t hash, bool writeGenerated) { +static bool Image_loadHDImage(Image_t *image, const char* name, int houseid, int animid, int frameId, int64_t hash, bool writeGenerated) { // Check to see if we can load a generated image first. // We only generate images that need a houseid if (!writeGenerated && houseid >= 0) { char* generatedImageName = Image_GetGeneratedName(image, name, houseid, animid, hash); - if (Image_loadHDImage(image, generatedImageName, houseid, animid, hash, true)) { + if (Image_loadHDImage(image, generatedImageName, houseid, animid, frameId, hash, true)) { return true; } } @@ -233,9 +234,9 @@ static bool Image_loadHDImage(Image_t *image, const char* name, int houseid, int strcpy(image->name, name); if(houseid == -1) - image->image[0][animid] = texture; + image->HouseImages[0].image[animid][frameId] = texture; else - image->image[houseid][animid] = texture; + image->HouseImages[houseid].image[animid][frameId] = texture; image->namehash = hash; image->renderwidth = image->width = Width; image->renderheight = image->height = Height; @@ -271,7 +272,7 @@ Image_t* Image_LoadImage(const char* name, bool loadAnims, bool loadHouseColor) if (!loadAnims) { unsigned char remap[3] = { 0, 0, 0 }; - if (!Image_loadHDImage(image, name, -1, 0, hash, false)) { + if (!Image_loadHDImage(image, name, -1, 0, 0, hash, false)) { delete image; return NULL; } @@ -279,7 +280,7 @@ Image_t* Image_LoadImage(const char* name, bool loadAnims, bool loadHouseColor) else { byte* palette = (byte *)CCPalette.Get_Data(); for (int i = 0; i < MAX_MPLAYER_COLORS; i++) { - if (!Image_loadHDImage(image, name, i, 0, hash, false)) { + if (!Image_loadHDImage(image, name, i, 0, 0, hash, false)) { delete image; return NULL; } @@ -369,7 +370,7 @@ Image_t* Image_CreateImageFrom8Bit(const char* name, int Width, int Height, unsi strcpy(image->name, name); - image->image[0][0] = texture; + image->HouseImages[0].image[0][0] = texture; image->numAnimFrames = -1; image->namehash = hash; image->renderwidth = image->width = Width; @@ -425,7 +426,7 @@ void Image_Add8BitImage(Image_t *image, int HouseId, int ShapeID, int Width, int glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - image->image[HouseId][ShapeID] = texture; + image->HouseImages[HouseId].image[ShapeID][0] = texture; image->numAnimFrames = -1; image->renderwidth = image->width = Width; image->renderheight = image->height = Height; @@ -433,8 +434,8 @@ void Image_Add8BitImage(Image_t *image, int HouseId, int ShapeID, int Width, int delete buffer; } -bool Image_Add32BitImage(const char *name, Image_t* image, int HouseId, int ShapeID) { - return Image_loadHDImage(image, name, HouseId, ShapeID, image->namehash, false); +bool Image_Add32BitImage(const char *name, Image_t* image, int HouseId, int ShapeID, int frameId) { + return Image_loadHDImage(image, name, HouseId, ShapeID, frameId, image->namehash, false); } BOOL Set_Video_Mode(HWND hwnd, int w, int h, int bits_per_pixel) { @@ -526,7 +527,7 @@ void Device_Present(void) { // Last thing we do is execute any console commands Console_Tick(); - ImGui_NewFrame(); + ImGui_NewFrame(); }