From c8f7c99c805bca2f5de54c879aaefbaf34d9af92 Mon Sep 17 00:00:00 2001 From: Zero Fanker Date: Tue, 7 May 2024 00:50:43 -0400 Subject: [PATCH 01/13] made some progress, but SHP image position is not always correct . --- 3rdParty/xcc/misc/cc_file.cpp | 2 +- 3rdParty/xcc/misc/cc_file.h | 8 +- 3rdParty/xcc/misc/cc_structures.h | 4 +- 3rdParty/xcc/misc/mix_file.cpp | 2 +- 3rdParty/xcc/misc/mix_file.h | 14 +- 3rdParty/xcc/misc/tmp_file.h | 2 +- MissionEditor/IsoView.cpp | 1 + MissionEditor/Loading.cpp | 308 ++++++------------ MissionEditor/MapData.cpp | 4 + MissionEditor/inlines.h | 22 +- MissionEditorPackLib/MissionEditorPackLib.cpp | 42 +-- MissionEditorPackLib/MissionEditorPackLib.h | 5 +- 12 files changed, 162 insertions(+), 252 deletions(-) diff --git a/3rdParty/xcc/misc/cc_file.cpp b/3rdParty/xcc/misc/cc_file.cpp index cb20d31..ccf1481 100644 --- a/3rdParty/xcc/misc/cc_file.cpp +++ b/3rdParty/xcc/misc/cc_file.cpp @@ -257,7 +257,7 @@ int Ccc_file::read() return 0; } -int Ccc_file::read(void* data, int size) +int Ccc_file::read(void* data, int64_t size) { if (get_p() < 0 || get_p() + size > get_size()) return 1; diff --git a/3rdParty/xcc/misc/cc_file.h b/3rdParty/xcc/misc/cc_file.h index b60c7b5..ef7e9b1 100644 --- a/3rdParty/xcc/misc/cc_file.h +++ b/3rdParty/xcc/misc/cc_file.h @@ -114,7 +114,7 @@ public: void load(const Ccc_file& f); t_file_type get_file_type(bool fast = true); int read(); - int read(void* data, int size); + int read(void* data, int64_t size); int extract(const string& name); virtual void close(); Ccc_file(bool read_on_open); @@ -154,7 +154,7 @@ public: return m_data; } - int get_p() const + int64_t get_p() const { return m_p; } @@ -174,7 +174,7 @@ public: m_p = p; } - void skip(int p) + void skip(int64_t p) { m_p += p; } @@ -189,7 +189,7 @@ private: Cvirtual_binary m_data; Cfile32 m_f; bool m_is_open = false; - int m_p; + int64_t m_p; const bool m_read_on_open; size_t m_size; }; diff --git a/3rdParty/xcc/misc/cc_structures.h b/3rdParty/xcc/misc/cc_structures.h index fba04e5..9956db8 100644 --- a/3rdParty/xcc/misc/cc_structures.h +++ b/3rdParty/xcc/misc/cc_structures.h @@ -194,7 +194,7 @@ struct t_mix_index_entry { t_mix_index_entry() = default; - t_mix_index_entry(unsigned int id_, int offset_, int size_) + t_mix_index_entry(unsigned int id_, int offset_, unsigned __int32 size_) { id = id_; offset = offset_; @@ -203,7 +203,7 @@ struct t_mix_index_entry unsigned __int32 id; __int32 offset; - __int32 size; + unsigned __int32 size; }; struct t_mix_rg_header diff --git a/3rdParty/xcc/misc/mix_file.cpp b/3rdParty/xcc/misc/mix_file.cpp index 19535a4..689134f 100644 --- a/3rdParty/xcc/misc/mix_file.cpp +++ b/3rdParty/xcc/misc/mix_file.cpp @@ -318,7 +318,7 @@ string Cmix_file::get_name(int id) #endif } -int Cmix_file::get_id(t_game game, string name) +unsigned int Cmix_file::get_id(t_game game, string name) { boost::to_upper(name); std::replace(name.begin(), name.end(), '/', '\\'); diff --git a/3rdParty/xcc/misc/mix_file.h b/3rdParty/xcc/misc/mix_file.h index ab37c00..6797b02 100644 --- a/3rdParty/xcc/misc/mix_file.h +++ b/3rdParty/xcc/misc/mix_file.h @@ -26,7 +26,7 @@ class Cmix_file : public Ccc_file public: int post_open(); string get_name(int id); - static int get_id(t_game game, string name); + static unsigned int get_id(t_game game, string name); int get_index(unsigned int id) const; using Ccc_file::get_size; using Ccc_file::vdata; @@ -80,10 +80,14 @@ public: return m_index[get_index(id)].offset; } - int get_size(unsigned int id) const + size_t get_size(unsigned int id) const { - assert(get_index(id) != -1); - return m_index[get_index(id)].size; + auto const idx = get_index(id); + //assert(idx != -1); + if (idx >= 0) { + return m_index[idx].size; + } + return 0; } bool has_checksum() const @@ -101,7 +105,7 @@ public: return &m_index[0]; } private: - using t_id_index = map; + using t_id_index = map; static bool m_ft_support; diff --git a/3rdParty/xcc/misc/tmp_file.h b/3rdParty/xcc/misc/tmp_file.h index 53647e2..993e0dd 100644 --- a/3rdParty/xcc/misc/tmp_file.h +++ b/3rdParty/xcc/misc/tmp_file.h @@ -27,7 +27,7 @@ public: bool is_valid() const { const t_tmp_header& h = header(); - int size = get_size(); + auto const size = get_size(); return !(sizeof(t_tmp_header) > size || h.cx != 24 || h.cy != 24 || diff --git a/MissionEditor/IsoView.cpp b/MissionEditor/IsoView.cpp index d2b69d6..57fa652 100644 --- a/MissionEditor/IsoView.cpp +++ b/MissionEditor/IsoView.cpp @@ -5506,6 +5506,7 @@ void CIsoView::DrawMap() SetError("Loading graphics"); theApp.m_loading->LoadUnitGraphic(buildingId); ::Map->UpdateBuildingInfo(&buildingId); + pic = buildinginfo[id].pic[0]; } if (pic.pic == NULL) { diff --git a/MissionEditor/Loading.cpp b/MissionEditor/Loading.cpp index 8687481..1d00972 100644 --- a/MissionEditor/Loading.cpp +++ b/MissionEditor/Loading.cpp @@ -1233,12 +1233,12 @@ BOOL CLoading::LoadUnitGraphic(const CString& lpUnittype) CString filename; // filename of the image char theat = cur_theat; // standard theater char is t (Temperat). a is snow. - BOOL bAlwaysSetChar = FALSE; // second char is always theater, even if NewTheater not specified! + bool bAlwaysSetChar = FALSE; // second char is always theater, even if NewTheater not specified! WORD wStep = 1; // step is 1 for infantry, buildings, etc, and for shp vehicles it specifies the step rate between every direction WORD wStartWalkFrame = 0; // for examply cyborg reaper has another walk starting frame int iTurretOffset = 0; // used for centering y pos of turret (if existing) (for vehicles) - const BOOL bStructure = rules["BuildingTypes"].HasValue(lpUnittype); // is this a structure? - const BOOL bVehicle = rules["VehicleTypes"].HasValue(lpUnittype); // is this a structure? + const bool bStructure = rules["BuildingTypes"].HasValue(lpUnittype); // is this a structure? + const bool bVehicle = rules["VehicleTypes"].HasValue(lpUnittype); // is this a structure? auto const bPowerUp = !rules.GetString(lpUnittype, "PowersUpBuilding").IsEmpty(); @@ -1314,7 +1314,6 @@ BOOL CLoading::LoadUnitGraphic(const CString& lpUnittype) SHPHEADER specialanim3_h; BYTE* specialanim4 = NULL; SHPHEADER specialanim4_h; - BYTE** lpT = NULL; SHPHEADER* lpT_h = NULL; std::vector turretColors[8]; std::vector turretLighting[8]; @@ -1360,8 +1359,8 @@ BOOL CLoading::LoadUnitGraphic(const CString& lpUnittype) FSunPackLib::VoxelNormalClass vnc = FSunPackLib::VoxelNormalClass::Unknown; - if (rules.GetBool(image, "Turret")) { - turretanim_name = rules.GetString(image, "TurretAnim"); + if (rules.GetBool(lpUnittype, "Turret")) { + turretanim_name = rules.GetString(lpUnittype, "TurretAnim"); auto vxl_turretanim_filename = turretanim_name.IsEmpty() ? image + "tur.vxl" : turretanim_name + ".vxl"; auto vxl_barrelanim_filename = image + "barl.vxl"; auto const& imageID = art.GetString(turretanim_name, "Image"); @@ -1369,40 +1368,40 @@ BOOL CLoading::LoadUnitGraphic(const CString& lpUnittype) vxl_turretanim_filename = imageID + ".vxl"; } - if (bStructure && turretanim_name.GetLength() > 0 && !rules.GetBool(image, "TurretAnimIsVoxel")) { + if (bStructure && turretanim_name.GetLength() > 0 && !rules.GetBool(lpUnittype, "TurretAnimIsVoxel")) { turretanim_filename = turretanim_name + ".shp"; auto const& imageID = art.GetString(turretanim_name, "Image"); if (!imageID.IsEmpty()) { turretanim_filename = imageID + ".shp"; } - - if (artSection.GetBool("NewTheater")) { + turretanim_filename.SetAt(1, 'G'); + if (artSection.GetBool("NewTheater", true)) { auto tmp = turretanim_filename; tmp.SetAt(1, theat); - if (FSunPackLib::XCC_DoesFileExist(tmp, hShpMix)) + if (FSunPackLib::XCC_DoesFileExist(tmp, hShpMix)) { turretanim_filename = tmp; + } } - + turretanim_filename.MakeUpper(); FSunPackLib::SetCurrentSHP(turretanim_filename, hShpMix); FSunPackLib::XCC_GetSHPHeader(&head); - int iStartTurret = 0; - const WORD wAnimCount = 4; // anims between each "normal" direction, seems to be hardcoded + auto const turretFrameStart = art.GetInteger(turretanim_name, "LoopStart"); + auto const turretFrameCount = art.GetInteger(turretanim_name, "LoopEnd", 32); + const WORD wAnimCount = turretFrameCount / 8; // anims between each "normal" direction - int i; - - for (i = 0; i < 8; i++) { - if (iStartTurret + i * wAnimCount < head.c_images) { - FSunPackLib::XCC_GetSHPImageHeader(iStartTurret + i * wAnimCount, &turretinfo[i]); + for (auto i = 0; i < 8; i++) { + if (turretFrameStart + i * wAnimCount < head.c_images) { + FSunPackLib::XCC_GetSHPImageHeader(turretFrameStart + i * wAnimCount, &turretinfo[i]); FSunPackLib::XCC_GetSHPHeader(&turrets_h[i]); - FSunPackLib::LoadSHPImage(iStartTurret + i * wAnimCount, turretColors[i]); + FSunPackLib::LoadSHPImage(turretFrameStart + i * wAnimCount, turretColors[i]); turretLighting[i].clear(); } } } else if ( - (bStructure && turretanim_name.GetLength() > 0 && rules.GetBool(image, "TurretAnimIsVoxel")) + (bStructure && !turretanim_name.IsEmpty() && rules.GetBool(lpUnittype, "TurretAnimIsVoxel")) || (!bStructure && (FindFileInMix(vxl_turretanim_filename) || FindFileInMix(vxl_barrelanim_filename))) ) { turretanim_filename = vxl_turretanim_filename; @@ -1545,17 +1544,16 @@ BOOL CLoading::LoadUnitGraphic(const CString& lpUnittype) if (bSuccess) { FSunPackLib::XCC_GetSHPHeader(&head); - int i; int maxPics = head.c_images; - if (maxPics > 8) { - maxPics = 8; // we only need 8 pictures for every direction! - } - if (bStructure && !bPowerUp && !rules.GetBool(image, "Turret")) { + if (bStructure && !bPowerUp) { maxPics = 1; } - if (bVoxelTurret) { + if (rules.GetBool(lpUnittype, "Turret")) { maxPics = 8; } + if (maxPics > 8) { + maxPics = 8; // we only need 8 pictures for every direction! + } if (!bStructure && rules.GetBool(image, "Turret")) { int iStartTurret = wStartWalkFrame + 8 * wStep; @@ -1572,32 +1570,23 @@ BOOL CLoading::LoadUnitGraphic(const CString& lpUnittype) // create an array of pointers to directdraw surfaces - lpT = new(BYTE * [maxPics]); + auto lpT = new(BYTE * [maxPics]); ::memset(lpT, 0, sizeof(BYTE) * maxPics); std::vector> lighting(maxPics); std::vector shp_image_headers(maxPics); - if (bVoxelTurret && bStructure) { - for (i = 0; i < maxPics; i++) { - FSunPackLib::LoadSHPImage(0, 1, &lpT[i]); - FSunPackLib::XCC_GetSHPImageHeader(0, &shp_image_headers[i]); - } - } else if (wStep == 1 && (rules.GetString(lpUnittype, "PowersUpBuilding").IsEmpty() || !rules.GetBool(lpUnittype, "Turret"))) { - // standard case... - FSunPackLib::LoadSHPImage(wStartWalkFrame, maxPics, lpT); - for (int i = 0; i < maxPics; ++i) { - FSunPackLib::XCC_GetSHPImageHeader(wStartWalkFrame + i, &shp_image_headers[i]); - } + if (lpUnittype == "CAWBNKR1") { + printf(""); + } - } else if (!rules.GetString(lpUnittype, "PowersUpBuilding").IsEmpty() && rules.GetBool(lpUnittype, "Turret")) { - // a "real" turret (vulcan cannon, etc...) - for (i = 0; i < maxPics; i++) { - FSunPackLib::LoadSHPImage(i * 4, 1, &lpT[i]); - FSunPackLib::XCC_GetSHPImageHeader(i * 4, &shp_image_headers[i]); + if (bStructure) { + for (auto i = 0; i < maxPics; i++) { + FSunPackLib::XCC_GetSHPImageHeader(0, &shp_image_headers[i]); + FSunPackLib::LoadSHPImage(0, 1, &lpT[i]); } - } else { + } else {// vehicle, infantry // walk frames used - for (i = 0; i < maxPics; i++) { + for (auto i = 0; i < maxPics; i++) { const int dir = bVehicle ? ((i + 1) % 8) : i; const int pic_in_file = dir * wStep + wStartWalkFrame; FSunPackLib::LoadSHPImage(pic_in_file, 1, &lpT[i]); @@ -1605,20 +1594,12 @@ BOOL CLoading::LoadUnitGraphic(const CString& lpUnittype) } } - for (i = 0; i < maxPics; i++) { - int pic_in_file = i; - if (bStructure && bVoxelTurret) pic_in_file = 0; - SHPIMAGEHEADER imghead = shp_image_headers[i]; - //FSunPackLib::XCC_GetSHPImageHeader(pic_in_file, &imghead); - + // this block handles one-direction only building frame + if (bStructure) { + SHPIMAGEHEADER imghead = shp_image_headers[0]; + auto blitDst = lpT[0]; if (bib != NULL) { - DDBLTFX fx; - - ::memset(&fx, 0, sizeof(DDBLTFX)); - fx.dwSize = sizeof(DDBLTFX); - - //lpT[i]->Blt(NULL, bib, NULL, DDBLT_KEYSRC | DDBLT_WAIT , &fx); - Blit_Pal(lpT[i], 0, 0, head.cx, head.cy, bib, bib_h.cx, bib_h.cy); + Blit_Pal(blitDst, 0, 0, head.cx, head.cy, bib, bib_h.cx, bib_h.cy); imghead.cx = head.cx - imghead.x; // update size of main graphic imghead.cy = head.cy - imghead.y; @@ -1626,144 +1607,73 @@ BOOL CLoading::LoadUnitGraphic(const CString& lpUnittype) } if (activeanim != NULL) { - DDBLTFX fx; - - ::memset(&fx, 0, sizeof(DDBLTFX)); - fx.dwSize = sizeof(DDBLTFX); - - //lpT[i]->Blt(NULL, activeanim, NULL, DDBLT_KEYSRC | DDBLT_WAIT , &fx); - Blit_Pal(lpT[i], 0, 0, head.cx, head.cy, activeanim, activeanim_h.cx, activeanim_h.cy); + Blit_Pal(blitDst, 0, 0, head.cx, head.cy, activeanim, activeanim_h.cx, activeanim_h.cy); } if (idleanim != NULL) { - DDBLTFX fx; - - ::memset(&fx, 0, sizeof(DDBLTFX)); - fx.dwSize = sizeof(DDBLTFX); - - //lpT[i]->Blt(NULL, idleanim, NULL, DDBLT_KEYSRC | DDBLT_WAIT , &fx); - Blit_Pal(lpT[i], 0, 0, head.cx, head.cy, idleanim, idleanim_h.cx, idleanim_h.cy); + Blit_Pal(blitDst, 0, 0, head.cx, head.cy, idleanim, idleanim_h.cx, idleanim_h.cy); } if (activeanim2 != NULL) { - DDBLTFX fx; - - ::memset(&fx, 0, sizeof(DDBLTFX)); - fx.dwSize = sizeof(DDBLTFX); - - //lpT[i]->Blt(NULL, activeanim2, NULL, DDBLT_KEYSRC | DDBLT_WAIT , &fx); - Blit_Pal(lpT[i], 0, 0, head.cx, head.cy, activeanim2, activeanim2_h.cx, activeanim2_h.cy); + Blit_Pal(blitDst, 0, 0, head.cx, head.cy, activeanim2, activeanim2_h.cx, activeanim2_h.cy); } if (activeanim3 != NULL) { - DDBLTFX fx; - - ::memset(&fx, 0, sizeof(DDBLTFX)); - fx.dwSize = sizeof(DDBLTFX); - - //lpT[i]->Blt(NULL, activeanim3, NULL, DDBLT_KEYSRC | DDBLT_WAIT , &fx); - Blit_Pal(lpT[i], 0, 0, head.cx, head.cy, activeanim3, activeanim3_h.cx, activeanim3_h.cy); + Blit_Pal(blitDst, 0, 0, head.cx, head.cy, activeanim3, activeanim3_h.cx, activeanim3_h.cy); } if (superanim1 != NULL) { - DDBLTFX fx; - - ::memset(&fx, 0, sizeof(DDBLTFX)); - fx.dwSize = sizeof(DDBLTFX); - - //lpT[i]->Blt(NULL, superanim1, NULL, DDBLT_KEYSRC | DDBLT_WAIT , &fx); - Blit_Pal(lpT[i], 0, superanim_1_zadjust, head.cx, head.cy, superanim1, superanim1_h.cx, superanim1_h.cy); - - + Blit_Pal(blitDst, 0, superanim_1_zadjust, head.cx, head.cy, superanim1, superanim1_h.cx, superanim1_h.cy); } if (superanim2 != NULL) { - DDBLTFX fx; - - ::memset(&fx, 0, sizeof(DDBLTFX)); - fx.dwSize = sizeof(DDBLTFX); - - //lpT[i]->Blt(NULL, superanim2, NULL, DDBLT_KEYSRC | DDBLT_WAIT , &fx); - Blit_Pal(lpT[i], 0, superanim_2_zadjust, head.cx, head.cy, superanim2, superanim2_h.cx, superanim2_h.cy); - - + Blit_Pal(blitDst, 0, superanim_2_zadjust, head.cx, head.cy, superanim2, superanim2_h.cx, superanim2_h.cy); } if (superanim3 != NULL) { - DDBLTFX fx; - - ::memset(&fx, 0, sizeof(DDBLTFX)); - fx.dwSize = sizeof(DDBLTFX); - - //lpT[i]->Blt(NULL, superanim3, NULL, DDBLT_KEYSRC | DDBLT_WAIT , &fx); - Blit_Pal(lpT[i], 0, superanim_3_zadjust, head.cx, head.cy, superanim3, superanim3_h.cx, superanim3_h.cy); - - + Blit_Pal(blitDst, 0, superanim_3_zadjust, head.cx, head.cy, superanim3, superanim3_h.cx, superanim3_h.cy); } - if (superanim4 != NULL && strcmp(lpUnittype, "YAGNTC") != NULL) { - DDBLTFX fx; - - ::memset(&fx, 0, sizeof(DDBLTFX)); - fx.dwSize = sizeof(DDBLTFX); - - //lpT[i]->Blt(NULL, superanim4, NULL, DDBLT_KEYSRC | DDBLT_WAIT , &fx); - Blit_Pal(lpT[i], 0, superanim_4_zadjust, head.cx, head.cy, superanim4, superanim4_h.cx, superanim4_h.cy); + Blit_Pal(blitDst, 0, superanim_4_zadjust, head.cx, head.cy, superanim4, superanim4_h.cx, superanim4_h.cy); } - if (specialanim1 != NULL) { - DDBLTFX fx; - - ::memset(&fx, 0, sizeof(DDBLTFX)); - fx.dwSize = sizeof(DDBLTFX); - - //lpT[i]->Blt(NULL, specialanim1, NULL, DDBLT_KEYSRC | DDBLT_WAIT , &fx); - Blit_Pal(lpT[i], 0, 0, head.cx, head.cy, specialanim1, specialanim1_h.cx, specialanim1_h.cy); - - + Blit_Pal(blitDst, 0, 0, head.cx, head.cy, specialanim1, specialanim1_h.cx, specialanim1_h.cy); } - if (specialanim2 != NULL) { - DDBLTFX fx; - - ::memset(&fx, 0, sizeof(DDBLTFX)); - fx.dwSize = sizeof(DDBLTFX); - - //lpT[i]->Blt(NULL, specialanim2, NULL, DDBLT_KEYSRC | DDBLT_WAIT , &fx); - Blit_Pal(lpT[i], 0, 0, head.cx, head.cy, specialanim2, specialanim2_h.cx, specialanim2_h.cy); - + Blit_Pal(blitDst, 0, 0, head.cx, head.cy, specialanim2, specialanim2_h.cx, specialanim2_h.cy); } - if (specialanim3 != NULL) { - DDBLTFX fx; - - ::memset(&fx, 0, sizeof(DDBLTFX)); - fx.dwSize = sizeof(DDBLTFX); - - //lpT[i]->Blt(NULL, specialanim3, NULL, DDBLT_KEYSRC | DDBLT_WAIT , &fx); - Blit_Pal(lpT[i], 0, 0, head.cx, head.cy, specialanim3, specialanim3_h.cx, specialanim3_h.cy); - - + Blit_Pal(blitDst, 0, 0, head.cx, head.cy, specialanim3, specialanim3_h.cx, specialanim3_h.cy); } if (specialanim4 != NULL) { - DDBLTFX fx; - - ::memset(&fx, 0, sizeof(DDBLTFX)); - fx.dwSize = sizeof(DDBLTFX); - - //lpT[i]->Blt(NULL, specialanim4, NULL, DDBLT_KEYSRC | DDBLT_WAIT , &fx); - Blit_Pal(lpT[i], 0, 0, head.cx, head.cy, specialanim4, specialanim4_h.cx, specialanim4_h.cy); + Blit_Pal(blitDst, 0, 0, head.cx, head.cy, specialanim4, specialanim4_h.cx, specialanim4_h.cy); } + } + + for (auto i = 0; i < maxPics; i++) { + SHPIMAGEHEADER* imghead = &shp_image_headers[i]; + if (bStructure) { + imghead = &shp_image_headers[0]; + if (!lpT[i]) { + auto const dataLen = imghead->cx * imghead->cy; + auto data = new(BYTE[dataLen]); + memcpy(data, lpT[0], dataLen); + lpT[i] = data; + } + } + //FSunPackLib::XCC_GetSHPImageHeader(pic_in_file, &imghead); + + if (!vxlBarrelLighting[i].empty() || !turretLighting[i].empty()) lighting[i].resize(head.cx * head.cy, 46); // value needs to lead to 1.0 lighting @@ -1823,24 +1733,26 @@ BOOL CLoading::LoadUnitGraphic(const CString& lpUnittype) ddsd.dwWidth = turrets_h[i].cx; ddsd.dwHeight = turrets_h[i].cy; - int XMover, YMover; - char c[50]; - itoa(i, c, 10); -#ifdef RA2_MODE - XMover = g_data.GetInteger("BuildingVoxelTurretsRA2", lpUnittype + "X"); - YMover = g_data.GetInteger("BuildingVoxelTurretsRA2", lpUnittype + "Y"); - XMover += g_data.GetInteger("BuildingVoxelTurretsRA2", lpUnittype + "X" + c); - YMover += g_data.GetInteger("BuildingVoxelTurretsRA2", lpUnittype + "Y" + c); -#else - XMover = g_data.GetInteger("BuildingVoxelTurrets", lpUnittype + "X"); - YMover = g_data.GetInteger("BuildingVoxelTurrets", lpUnittype + "Y"); -#endif + int XMover = 0; + int YMover = 0; RECT srcRect, destRect; if (bVoxelTurret) { - int mx = head.cx / 2 + rules.GetInteger(image, "TurretAnimX") - turretinfo[i].x; - int my = head.cy / 2 + rules.GetInteger(image, "TurretAnimY") - turretinfo[i].y; + int mx = head.cx / 2 + rules.GetInteger(lpUnittype, "TurretAnimX") - turretinfo[i].x; + int my = head.cy / 2 + rules.GetInteger(lpUnittype, "TurretAnimY") - turretinfo[i].y; + + char c[50]; + itoa(i, c, 10); +#ifdef RA2_MODE + XMover = g_data.GetInteger("BuildingVoxelTurretsRA2", lpUnittype + "X"); + YMover = g_data.GetInteger("BuildingVoxelTurretsRA2", lpUnittype + "Y"); + XMover += g_data.GetInteger("BuildingVoxelTurretsRA2", lpUnittype + "X" + c); + YMover += g_data.GetInteger("BuildingVoxelTurretsRA2", lpUnittype + "Y" + c); +#else + XMover = g_data.GetInteger("BuildingVoxelTurrets", lpUnittype + "X"); + YMover = g_data.GetInteger("BuildingVoxelTurrets", lpUnittype + "Y"); +#endif srcRect.top = 0; srcRect.left = 0; @@ -1851,13 +1763,9 @@ BOOL CLoading::LoadUnitGraphic(const CString& lpUnittype) destRect.right = destRect.left + ddsd.dwWidth;; destRect.bottom = destRect.top + ddsd.dwHeight; - } else // !bVoxelTurret - { - - int mx = rules.GetInteger(image, "TurretAnimX"); - int my = rules.GetInteger(image, "TurretAnimY");//+rules.GetInteger(image, "barrelAnimZAdjust"); - - + } else {// !bVoxelTurret + int mx = rules.GetInteger(lpUnittype, "TurretAnimX"); + int my = rules.GetInteger(lpUnittype, "TurretAnimY");//+rules.GetInteger(image, "barrelAnimZAdjust"); srcRect.top = 0; srcRect.left = 0; @@ -1921,7 +1829,7 @@ BOOL CLoading::LoadUnitGraphic(const CString& lpUnittype) } - if (!bPowerUp && i != 0 && (imghead.unknown == 0 && !g_data.GetBool("Debug", "IgnoreSHPImageHeadUnused")) && bStructure) { + if (!bPowerUp && i != 0 && (imghead->unknown == 0 && !g_data.GetBool("Debug", "IgnoreSHPImageHeadUnused")) && bStructure) { if (lpT[i]) delete[] lpT[i]; lpT[i] = NULL; } else { @@ -1948,10 +1856,10 @@ BOOL CLoading::LoadUnitGraphic(const CString& lpUnittype) if (hPalette == m_hPalUnitTemp || hPalette == m_hPalUnitUrb || hPalette == m_hPalUnitSnow || hPalette == m_hPalUnitDes || hPalette == m_hPalUnitLun || hPalette == m_hPalUnitUbn) p.pal = iPalUnit; if (hPalette == m_hPalLib) p.pal = iPalLib; - p.x = imghead.x; - p.y = imghead.y; - p.wHeight = imghead.cy; - p.wWidth = imghead.cx; + p.x = imghead->x; + p.y = imghead->y; + p.wHeight = imghead->cy; + p.wWidth = imghead->cx; p.wMaxWidth = head.cx; p.wMaxHeight = head.cy; p.bType = PICDATA_TYPE_SHP; @@ -3643,7 +3551,7 @@ void CLoading::LoadOverlayGraphic(const CString& lpOvrlName_, int iOvrlNum) FSunPackLib::SetTSPaletteEntry(hPalette, 0x10 + i, &rgbNew, &rgbOld[i]); } - } + } #endif FSunPackLib::LoadSHPImage(0, maxPics, lpT); @@ -3703,10 +3611,10 @@ void CLoading::LoadOverlayGraphic(const CString& lpOvrlName_, int iOvrlNum) delete[] lpT; - } - } +} + int i; for (i = 0; i < 0xFF; i++) { char ic[50]; @@ -4435,21 +4343,21 @@ void CLoading::FreeAll() #endif i->second.pic = NULL; - } catch (...) { - CString err; - err = "Access violation while trying to release surface "; - char c[6]; - itoa(e, c, 10); - err += c; + } catch (...) { + CString err; + err = "Access violation while trying to release surface "; + char c[6]; + itoa(e, c, 10); + err += c; - err += "\n"; - OutputDebugString(err); - continue; + err += "\n"; + OutputDebugString(err); + continue; + } + + i++; } - i++; - } - try { @@ -4469,7 +4377,7 @@ void CLoading::FreeAll() } catch (...) { errstream << "Exception while freeing DirectDraw" << endl; } -} + } void CLoading::PostNcDestroy() { @@ -4738,7 +4646,7 @@ void CLoading::LoadStrings() //CCStrings[*rules.GetSectionName(i)].SetString=rul CCStrings[*rules.GetSectionName(i)].SetString((LPSTR)(LPCSTR)rules.GetSection(i)->values["Name"]); } - } +} #endif diff --git a/MissionEditor/MapData.cpp b/MissionEditor/MapData.cpp index 4ccab1c..b3bfb32 100644 --- a/MissionEditor/MapData.cpp +++ b/MissionEditor/MapData.cpp @@ -3493,6 +3493,10 @@ void CMapData::UpdateBuildingInfo(const CString* lpUnitType) buildinginfo[n].bUrban = TRUE; } + if (type == "NALASR") { + printf(""); + } + buildinginfo[n].pic_count = 8; for (auto k = 0; k < 8; k++) { lpPicFile = GetUnitPictureFilename(type, k); diff --git a/MissionEditor/inlines.h b/MissionEditor/inlines.h index 960aa89..8a3ba42 100644 --- a/MissionEditor/inlines.h +++ b/MissionEditor/inlines.h @@ -52,28 +52,20 @@ inline CString GetUnitPictureFilename(LPCTSTR lpUnitName, DWORD dwPicIndex) { CIniFile& ini = Map->GetIniFile(); - CString UnitName = lpUnitName; + auto artname = rules.GetStringOr(lpUnitName, "Image", lpUnitName); + artname = ini.GetStringOr(lpUnitName, "Image", artname); - UnitName = ini.GetString(lpUnitName, "Image"); - if (UnitName.IsEmpty()) { - UnitName = rules.GetString(lpUnitName, "Image"); - } - - CString artname = UnitName; - if (UnitName.IsEmpty()) { - artname = lpUnitName; - } - auto const shapeName = art.GetString(UnitName, "Image"); + auto const& shapeName = art.GetString(artname, "Image"); if (!shapeName.IsEmpty()) { - if (!g_data.GetBool("IgnoreArtImage", UnitName)) { + if (!g_data.GetBool("IgnoreArtImage", artname)) { artname = shapeName; } } - CString filename = UnitName; + CString filename = artname; - if (art.GetBool(UnitName, "NewTheater") && !art.GetBool(UnitName, "DemandLoad")) { + if (art.GetBool(artname, "NewTheater") && !art.GetBool(artname, "DemandLoad")) { filename.SetAt(1, 'T'); } @@ -81,7 +73,7 @@ inline CString GetUnitPictureFilename(LPCTSTR lpUnitName, DWORD dwPicIndex) _itoa_s(dwPicIndex, n, 10); - if (pics.find(artname + n) != pics.end()) { + if (pics.find((artname + n)) != pics.end()) { filename = artname; // yes, found filename += n; } else if (pics.find(artname + ".bmp") != pics.end()) // since June, 15th (Matze): Only use BMP if no SHP/VXL exists diff --git a/MissionEditorPackLib/MissionEditorPackLib.cpp b/MissionEditorPackLib/MissionEditorPackLib.cpp index 67b1149..115dc25 100644 --- a/MissionEditorPackLib/MissionEditorPackLib.cpp +++ b/MissionEditorPackLib/MissionEditorPackLib.cpp @@ -558,26 +558,30 @@ namespace FSunPackLib return TRUE; }; - BOOL SetCurrentSHP(LPCSTR szSHP, HMIXFILE hOwner) + bool SetCurrentSHP(LPCSTR szSHP, HMIXFILE hOwner) { - if (cur_shp.is_open()) cur_shp.close(); + if (cur_shp.is_open()) { + cur_shp.close(); + } if (hOwner == NULL) { if (open_read(cur_shp, szSHP) != 0) { - return FALSE; + return false; } } else { - int id = mixfiles[hOwner - 1].get_id(mixfiles[hOwner - 1].get_game(), szSHP); - int size = mixfiles[hOwner - 1].get_size(id); - if (size == 0) + auto const id = mixfiles[hOwner - 1].get_id(mixfiles[hOwner - 1].get_game(), szSHP); + auto const size = mixfiles[hOwner - 1].get_size(id); + if (size == 0) { OutputDebugString("NULL size"); + return false; + } BYTE* b = new(BYTE[size]); mixfiles[hOwner - 1].seek(mixfiles[hOwner - 1].get_offset(id)); mixfiles[hOwner - 1].read(b, size); cur_shp.load(Cvirtual_binary(b, size)); } - return TRUE; + return true; }; BOOL XCC_GetTMPTileInfo(int iTile, POINT* lpPos, int* lpWidth, int* lpHeight, BYTE* lpDirection, BYTE* lpTileHeight, BYTE* lpTileType, RGBTRIPLE* lpRgbLeft, RGBTRIPLE* lpRgbRight) @@ -876,7 +880,7 @@ namespace FSunPackLib } - BOOL LoadSHPImage(int iImageIndex, int iCount, BYTE** lpPics) + BOOL LoadSHPImage(int startIndex, int wantedNum, BYTE** lpPics) { t_shp_ts_image_header imghead; BYTE* image = NULL; @@ -889,26 +893,22 @@ namespace FSunPackLib return FALSE; } - - - - int pic; std::vector decode_image_buffer; - for (pic = 0; pic < iCount; pic++) { - if (cur_shp.get_image_header(iImageIndex + pic)) { - imghead = *(cur_shp.get_image_header(iImageIndex + pic)); + for (auto frameIdx = 0; frameIdx < wantedNum; frameIdx++) { + if (cur_shp.get_image_header(startIndex + frameIdx)) { + imghead = *(cur_shp.get_image_header(startIndex + frameIdx)); // if(imghead.offset!=0) { - if (cur_shp.is_compressed(iImageIndex + pic)) { + if (cur_shp.is_compressed(startIndex + frameIdx)) { decode_image_buffer.resize(imghead.cx * imghead.cy); image = decode_image_buffer.data(); - decode3(cur_shp.get_image(iImageIndex + pic), image, imghead.cx, imghead.cy); + decode3(cur_shp.get_image(startIndex + frameIdx), image, imghead.cx, imghead.cy); } else - image = (unsigned char*)cur_shp.get_image(iImageIndex + pic); + image = (unsigned char*)cur_shp.get_image(startIndex + frameIdx); - lpPics[pic] = new(BYTE[head.cx * head.cy]); + lpPics[frameIdx] = new(BYTE[head.cx * head.cy]); int i, e; for (i = 0; i < head.cx; i++) { @@ -920,9 +920,9 @@ namespace FSunPackLib dwRead = (i - imghead.x) + (e - imghead.y) * imghead.cx; if (dwRead != 0xFFFFFFFF) { - lpPics[pic][dwWrite] = image[dwRead]; + lpPics[frameIdx][dwWrite] = image[dwRead]; } else - lpPics[pic][dwWrite] = 0; + lpPics[frameIdx][dwWrite] = 0; } diff --git a/MissionEditorPackLib/MissionEditorPackLib.h b/MissionEditorPackLib/MissionEditorPackLib.h index ef73036..aa83ccc 100644 --- a/MissionEditorPackLib/MissionEditorPackLib.h +++ b/MissionEditorPackLib/MissionEditorPackLib.h @@ -181,7 +181,7 @@ namespace FSunPackLib BOOL SetCurrentTMP(LPCSTR szTMP, HMIXFILE hOwner); - BOOL SetCurrentSHP(LPCSTR szSHP, HMIXFILE hOwner); + bool SetCurrentSHP(LPCSTR szSHP, HMIXFILE hOwner); BOOL XCC_GetTMPTileInfo(int iTile, POINT* lpPos, int* lpWidth, int* lpHeight, BYTE* lpDirection, BYTE* lpTileHeight, BYTE* lpTileType, RGBTRIPLE* lpRgbLeft, RGBTRIPLE* lpRgbRight); @@ -195,7 +195,8 @@ namespace FSunPackLib BOOL LoadTMPImage(int iStart, int iCount, BYTE** lpTileArray); BOOL LoadSHPImageInSurface(IDirectDraw4* pdd, HTSPALETTE hPalette, int iImageIndex, int iCount, LPDIRECTDRAWSURFACE4* pdds); - BOOL LoadSHPImage(int iImageIndex, int iCount, BYTE** lpPics); + // load 'wantedNum' frames at 'startIndex' + BOOL LoadSHPImage(int startIndex, int wantedNum, BYTE** lpPics); BOOL LoadSHPImage(int iImageIndex, std::vector& pic); HTSPALETTE LoadTSPalette(LPCSTR szPalette, HMIXFILE hPaletteOwner); From fb64321a280288803ec75771e2f396a619886cd2 Mon Sep 17 00:00:00 2001 From: Zero Fanker Date: Sat, 11 May 2024 22:48:53 -0400 Subject: [PATCH 02/13] split out class "IniMegaFile" . --- MissionEditor/IniMega.h | 33 +++++++++++++++++++++++++++++++++ MissionEditor/ViewObjects.cpp | 15 +-------------- MissionEditor/ViewObjects.h | 18 ------------------ 3 files changed, 34 insertions(+), 32 deletions(-) create mode 100644 MissionEditor/IniMega.h diff --git a/MissionEditor/IniMega.h b/MissionEditor/IniMega.h new file mode 100644 index 0000000..b29ccd4 --- /dev/null +++ b/MissionEditor/IniMega.h @@ -0,0 +1,33 @@ +#pragma once + +#include +#include "INIMeta.h" +#include "variables.h" + +extern CIniFile rules; + +class IniMegaFile +{ + friend class IniFileGroup; +public: + static IniFileGroup GetRules(); + + static bool IsNullOrEmpty(const CString& value) { return isNullOrEmpty(value); } + +private: + static bool isNullOrEmpty(const CString& value); +}; + + +IniFileGroup IniMegaFile::GetRules() +{ + IniFileGroup m_group; + m_group.Append(rules); + m_group.Append(Map->GetIniFile()); + return m_group; +} + +bool IniMegaFile::isNullOrEmpty(const CString& value) +{ + return !value.GetLength() || value == "none" || value == ""; +} \ No newline at end of file diff --git a/MissionEditor/ViewObjects.cpp b/MissionEditor/ViewObjects.cpp index 35318e4..b617afe 100644 --- a/MissionEditor/ViewObjects.cpp +++ b/MissionEditor/ViewObjects.cpp @@ -33,7 +33,7 @@ #include "rtpdlg.h" #include "TubeTool.h" #include "StringHelper.h" -#include "INIMeta.h" +#include "IniMega.h" #ifdef _DEBUG #define new DEBUG_NEW @@ -514,19 +514,6 @@ __inline HTREEITEM TV_InsertItemW(HWND hWnd, WCHAR* lpString, int len, HTREEITEM return res; } -IniFileGroup IniMegaFile::GetRules() -{ - IniFileGroup m_group; - m_group.Append(rules); - m_group.Append(Map->GetIniFile()); - return m_group; -} - -bool IniMegaFile::isNullOrEmpty(const CString& value) -{ - return !value.GetLength() || value == "none" || value == ""; -} - const IgnoreSet CollectIgnoreSet() { IgnoreSet ret; diff --git a/MissionEditor/ViewObjects.h b/MissionEditor/ViewObjects.h index 833f2e1..80c5d75 100644 --- a/MissionEditor/ViewObjects.h +++ b/MissionEditor/ViewObjects.h @@ -32,15 +32,11 @@ #define MAKE_MASK(refVal) 1 << static_cast(refVal) class TreeViewBuilder; -class CViewObjects; -class IniFileGroup; using IgnoreSet = std::unordered_set; static const IgnoreSet CollectIgnoreSet(); -extern CIniFile rules; - class TreeRoot { friend class TreeViewBuilder; friend class CViewObjects; @@ -225,20 +221,6 @@ private: void HandleBrushSize(int iTile); }; -class IniMegaFile -{ - friend class IniFileGroup; -public: - static IniFileGroup GetRules(); - - static bool IsNullOrEmpty(const CString& value) { return isNullOrEmpty(value); } - -private: - static bool isNullOrEmpty(const CString& value); - - -}; - ///////////////////////////////////////////////////////////////////////////// //{{AFX_INSERT_LOCATION}} From 981059c2b461f023db1f54a76729f71ec7c83db5 Mon Sep 17 00:00:00 2001 From: Zero Fanker Date: Mon, 13 May 2024 21:37:30 -0400 Subject: [PATCH 03/13] split out palette management, preparing for custom palette support . --- MissionEditor/Loading.cpp | 721 +++--------------- MissionEditor/Loading.h | 35 +- MissionEditor/Palettes.cpp | 349 +++++++++ MissionEditor/Palettes.h | 89 +++ MissionEditorPackLib/MissionEditorPackLib.cpp | 95 ++- MissionEditorPackLib/MissionEditorPackLib.h | 11 +- 6 files changed, 645 insertions(+), 655 deletions(-) create mode 100644 MissionEditor/Palettes.cpp create mode 100644 MissionEditor/Palettes.h diff --git a/MissionEditor/Loading.cpp b/MissionEditor/Loading.cpp index 1d00972..c61b5da 100644 --- a/MissionEditor/Loading.cpp +++ b/MissionEditor/Loading.cpp @@ -1029,60 +1029,6 @@ const Vec3f lightDirection = Vec3f(1.0f, 0.0f, -1.0f).normalize(); #endif -HTSPALETTE CLoading::GetIsoPalette(char theat) -{ - HTSPALETTE isoPalette = m_hPalIsoTemp; - switch (theat) { - case 'T': - case 'G': - isoPalette = m_hPalIsoTemp; - break; - case 'A': - isoPalette = m_hPalIsoSnow; - break; - case 'U': - isoPalette = m_hPalIsoUrb; - break; - case 'N': - isoPalette = m_hPalIsoUbn; - break; - case 'D': - isoPalette = m_hPalIsoDes; - break; - case 'L': - isoPalette = m_hPalIsoLun; - break; - } - return isoPalette; -} - -HTSPALETTE CLoading::GetUnitPalette(char theat) -{ - HTSPALETTE isoPalette = m_hPalUnitTemp; - switch (theat) { - case 'T': - case 'G': - isoPalette = m_hPalUnitTemp; - break; - case 'A': - isoPalette = m_hPalUnitSnow; - break; - case 'U': - isoPalette = m_hPalUnitUrb; - break; - case 'N': - isoPalette = m_hPalUnitUbn; - break; - case 'D': - isoPalette = m_hPalUnitDes; - break; - case 'L': - isoPalette = m_hPalUnitLun; - break; - } - return isoPalette; -} - CString theatToSuffix(char theat) { if (theat == 'T') return ".tem"; @@ -1126,20 +1072,20 @@ std::optional CLoading::FindUnitShp(const CString& image, char pr const auto& unitPalettePrefixes = g_data["ForceUnitPalettePrefix"]; if (unitPalettePrefixes.end() != std::find_if(unitPalettePrefixes.begin(), unitPalettePrefixes.end(), [&image](const auto& pair) {return image.Find(pair.second) == 0; })) { - forcedPalette = GetUnitPalette(preferred_theat); + forcedPalette = m_palettes.GetUnitPalette(preferred_theat); } const auto& isoPalettePrefixes = g_data["ForceIsoPalettePrefix"]; if (isoPalettePrefixes.end() != std::find_if(isoPalettePrefixes.begin(), isoPalettePrefixes.end(), [&image](const auto& pair) {return image.Find(pair.second) == 0; })) { - forcedPalette = GetIsoPalette(preferred_theat); + forcedPalette = m_palettes.GetIsoPalette(preferred_theat); } const bool isTheater = artSection.GetBool("Theater"); const bool isNewTheater = artSection.GetBool("NewTheater"); const bool terrainPalette = artSection.GetBool("TerrainPalette"); - auto unitOrIsoPalette = terrainPalette ? GetIsoPalette(preferred_theat) : GetUnitPalette(preferred_theat); + auto unitOrIsoPalette = terrainPalette ? m_palettes.GetIsoPalette(preferred_theat) : m_palettes.GetUnitPalette(preferred_theat); HMIXFILE curMixFile = 0; CString curFilename = image + ".shp"; @@ -1154,7 +1100,7 @@ std::optional CLoading::FindUnitShp(const CString& image, char pr curFilename.MakeLower(); curMixFile = FindFileInMix(curFilename, &curMixTheater); if (curMixFile) - return FindShpResult(curMixFile, curMixTheater, curFilename, toTheaterChar(suffixToTheat(curSuffix)), forcedPalette ? forcedPalette : GetIsoPalette(suffixToTheat(curSuffix))); + return FindShpResult(curMixFile, curMixTheater, curFilename, toTheaterChar(suffixToTheat(curSuffix)), forcedPalette ? forcedPalette : m_palettes.GetIsoPalette(suffixToTheat(curSuffix))); } } // Phase 1: if NewTheater is enabled and first character indicates support, try with real theater, then in order of kTheatersToTry @@ -1203,7 +1149,7 @@ std::optional CLoading::FindUnitShp(const CString& image, char pr curFilename.MakeLower(); curMixFile = FindFileInMix(curFilename, &curMixTheater); if (curMixFile) - return FindShpResult(curMixFile, curMixTheater, curFilename, toTheaterChar(suffixToTheat(curSuffix)), forcedPalette ? forcedPalette : GetIsoPalette(suffixToTheat(curSuffix))); + return FindShpResult(curMixFile, curMixTheater, curFilename, toTheaterChar(suffixToTheat(curSuffix)), forcedPalette ? forcedPalette : m_palettes.GetIsoPalette(suffixToTheat(curSuffix))); } // Phase 6: try with theater in 2nd char even if first char does not indicate support curFilename = image + ".shp"; @@ -1211,7 +1157,7 @@ std::optional CLoading::FindUnitShp(const CString& image, char pr curFilename.SetAt(1, curTheater); curMixFile = FindFileInMix(curFilename, &curMixTheater); if (curMixFile) - return FindShpResult(curMixFile, curMixTheater, curFilename, toTheaterChar(curTheater), forcedPalette ? forcedPalette : GetIsoPalette(curTheater)); + return FindShpResult(curMixFile, curMixTheater, curFilename, toTheaterChar(curTheater), forcedPalette ? forcedPalette : m_palettes.GetIsoPalette(curTheater)); } return std::nullopt; @@ -2770,117 +2716,16 @@ HMIXFILE CLoading::FindFileInMix(LPCTSTR lpFilename, TheaterChar* pTheaterChar) void CLoading::InitPalettes() { errstream << "InitPalettes() called\n"; - if (!FSunPackLib::XCC_ExtractFile("isotem.pal", u8AppDataPath + "\\TmpPalette.pal", m_hCache)) - errstream << "IsoTem.pal failed\n"; - m_hPalIsoTemp = FSunPackLib::LoadTSPalette(u8AppDataPath + "\\TmpPalette.pal", NULL); - deleteFile(u8AppDataPath + "\\TmpPalette.pal"); - - if (!FSunPackLib::XCC_ExtractFile("isosno.pal", u8AppDataPath + "\\TmpPalette.pal", m_hCache)) - errstream << "IsoSno.pal failed\n"; - m_hPalIsoSnow = FSunPackLib::LoadTSPalette(u8AppDataPath + "\\TmpPalette.pal", NULL); - deleteFile(u8AppDataPath + "\\TmpPalette.pal"); - - if (!FSunPackLib::XCC_ExtractFile("isourb.pal", u8AppDataPath + "\\TmpPalette.pal", m_hCache)) - errstream << "IsoUrb.pal failed\n"; - m_hPalIsoUrb = FSunPackLib::LoadTSPalette(u8AppDataPath + "\\TmpPalette.pal", NULL); - deleteFile(u8AppDataPath + "\\TmpPalette.pal"); - - HMIXFILE m_hCache2 = m_hExpand[100].hECache; - if (!FSunPackLib::XCC_ExtractFile("isolun.pal", u8AppDataPath + "\\TmpPalette.pal", m_hCache2)) - errstream << "IsoLun.pal failed\n"; - m_hPalIsoLun = FSunPackLib::LoadTSPalette(u8AppDataPath + "\\TmpPalette.pal", NULL); - deleteFile(u8AppDataPath + "\\TmpPalette.pal"); - - if (!FSunPackLib::XCC_ExtractFile("isodes.pal", u8AppDataPath + "\\TmpPalette.pal", m_hCache2)) - errstream << "IsoDes.pal failed\n"; - m_hPalIsoDes = FSunPackLib::LoadTSPalette(u8AppDataPath + "\\TmpPalette.pal", NULL); - deleteFile(u8AppDataPath + "\\TmpPalette.pal"); - - if (!FSunPackLib::XCC_ExtractFile("isoubn.pal", u8AppDataPath + "\\TmpPalette.pal", m_hCache2)) - errstream << "IsoUbn.pal failed\n"; - m_hPalIsoUbn = FSunPackLib::LoadTSPalette(u8AppDataPath + "\\TmpPalette.pal", NULL); - deleteFile(u8AppDataPath + "\\TmpPalette.pal"); - - - if (!FSunPackLib::XCC_ExtractFile("unittem.pal", u8AppDataPath + "\\TmpPalette.pal", m_hCache)) - errstream << "UnitTem.pal failed"; - m_hPalUnitTemp = FSunPackLib::LoadTSPalette(u8AppDataPath + "\\TmpPalette.pal", NULL); - deleteFile(u8AppDataPath + "\\TmpPalette.pal"); - - if (!FSunPackLib::XCC_ExtractFile("unitsno.pal", u8AppDataPath + "\\TmpPalette.pal", m_hCache)) - errstream << "UnitSno.pal failed\n"; - m_hPalUnitSnow = FSunPackLib::LoadTSPalette(u8AppDataPath + "\\TmpPalette.pal", NULL); - deleteFile(u8AppDataPath + "\\TmpPalette.pal"); - - if (!FSunPackLib::XCC_ExtractFile("uniturb.pal", u8AppDataPath + "\\TmpPalette.pal", m_hCache)) - errstream << "UnitUrb.pal failed\n"; - m_hPalUnitUrb = FSunPackLib::LoadTSPalette(u8AppDataPath + "\\TmpPalette.pal", NULL); - deleteFile(u8AppDataPath + "\\TmpPalette.pal"); - - - if (!FSunPackLib::XCC_ExtractFile("unitlun.pal", u8AppDataPath + "\\TmpPalette.pal", m_hCache2)) - errstream << "UnitLun.pal failed\n"; - m_hPalUnitLun = FSunPackLib::LoadTSPalette(u8AppDataPath + "\\TmpPalette.pal", NULL); - deleteFile(u8AppDataPath + "\\TmpPalette.pal"); - - if (!FSunPackLib::XCC_ExtractFile("unitdes.pal", u8AppDataPath + "\\TmpPalette.pal", m_hCache2)) - errstream << "UnitDes.pal failed\n"; - m_hPalUnitDes = FSunPackLib::LoadTSPalette(u8AppDataPath + "\\TmpPalette.pal", NULL); - deleteFile(u8AppDataPath + "\\TmpPalette.pal"); - - if (!FSunPackLib::XCC_ExtractFile("unitubn.pal", u8AppDataPath + "\\TmpPalette.pal", m_hCache2)) - errstream << "UnitUbn.pal failed\n"; - m_hPalUnitUbn = FSunPackLib::LoadTSPalette(u8AppDataPath + "\\TmpPalette.pal", NULL); - deleteFile(u8AppDataPath + "\\TmpPalette.pal"); - - - if (!FSunPackLib::XCC_ExtractFile("snow.pal", u8AppDataPath + "\\TmpPalette.pal", m_hCache)) - errstream << "Snow.pal failed\n"; - m_hPalSnow = FSunPackLib::LoadTSPalette(u8AppDataPath + "\\TmpPalette.pal", NULL); - deleteFile(u8AppDataPath + "\\TmpPalette.pal"); - - if (!FSunPackLib::XCC_ExtractFile("temperat.pal", u8AppDataPath + "\\TmpPalette.pal", m_hCache)) - errstream << "Temperat.pal failed\n"; - m_hPalTemp = FSunPackLib::LoadTSPalette(u8AppDataPath + "\\TmpPalette.pal", NULL); - deleteFile(u8AppDataPath + "\\TmpPalette.pal"); - - if (!FSunPackLib::XCC_ExtractFile("urban.pal", u8AppDataPath + "\\TmpPalette.pal", m_hCache)) - errstream << "Urban.pal failed\n"; - m_hPalUrb = FSunPackLib::LoadTSPalette(u8AppDataPath + "\\TmpPalette.pal", NULL); - deleteFile(u8AppDataPath + "\\TmpPalette.pal"); - - - if (!FSunPackLib::XCC_ExtractFile("lunar.pal", u8AppDataPath + "\\TmpPalette.pal", m_hCache2)) - errstream << "lunar.pal failed\n"; - m_hPalLun = FSunPackLib::LoadTSPalette(u8AppDataPath + "\\TmpPalette.pal", NULL); - deleteFile(u8AppDataPath + "\\TmpPalette.pal"); - - if (!FSunPackLib::XCC_ExtractFile("desert.pal", u8AppDataPath + "\\TmpPalette.pal", m_hCache2)) - errstream << "desert.pal failed\n"; - m_hPalDes = FSunPackLib::LoadTSPalette(u8AppDataPath + "\\TmpPalette.pal", NULL); - deleteFile(u8AppDataPath + "\\TmpPalette.pal"); - - if (!FSunPackLib::XCC_ExtractFile("urbann.pal", u8AppDataPath + "\\TmpPalette.pal", m_hCache2)) - errstream << "urbann.pal failed\n"; - m_hPalUbn = FSunPackLib::LoadTSPalette(u8AppDataPath + "\\TmpPalette.pal", NULL); - deleteFile(u8AppDataPath + "\\TmpPalette.pal"); - - - if (!FSunPackLib::XCC_ExtractFile("_ID2124019542", u8AppDataPath + "\\TmpPalette.pal", m_hCache)) - errstream << "lib.pal failed\n"; - m_hPalLib = FSunPackLib::LoadTSPalette(u8AppDataPath + "\\TmpPalette.pal", NULL); - deleteFile(u8AppDataPath + "\\TmpPalette.pal"); - + + m_palettes.Init(); errstream << "\n"; errstream.flush(); - - } void CLoading::InitTMPs(CProgressCtrl* prog) { - FetchPalettes(); + m_palettes.FetchPalettes(); MEMORYSTATUS ms; @@ -2991,17 +2836,33 @@ void CLoading::InitTMPs(CProgressCtrl* prog) if (tiles == &tiles_d) suffix = ".des"; filename += suffix; - HTSPALETTE hPalette = m_hPalIsoTemp; - if (tiles == &tiles_s) hPalette = m_hPalIsoSnow; - if (tiles == &tiles_u) hPalette = m_hPalIsoUrb; - if (tiles == &tiles_t) hPalette = m_hPalIsoTemp; - if (tiles == &tiles_un) hPalette = m_hPalIsoUbn; - if (tiles == &tiles_d) hPalette = m_hPalIsoDes; - if (tiles == &tiles_l) hPalette = m_hPalIsoLun; + HTSPALETTE hPalette = m_palettes.m_hPalIsoTemp; + if (tiles == &tiles_s) { + hPalette = m_palettes.m_hPalIsoSnow; } + if (tiles == &tiles_u) { + hPalette = m_palettes.m_hPalIsoUrb; } + if (tiles == &tiles_t) { + hPalette = m_palettes.m_hPalIsoTemp; + } + if (tiles == &tiles_un) { + hPalette = m_palettes.m_hPalIsoUbn; + } + if (tiles == &tiles_d) { + hPalette = m_palettes.m_hPalIsoDes; + } + if (tiles == &tiles_l) { + hPalette = m_palettes.m_hPalIsoLun; + } // MW add: use other... - if (FindFileInMix(filename) == NULL && tiles == &tiles_un) { filename = bas_f + ".urb"; hPalette = m_hPalIsoUrb; } - if (FindFileInMix(filename) == NULL) { filename = bas_f + ".tem"; hPalette = m_hPalIsoTemp; } + if (FindFileInMix(filename) == NULL && tiles == &tiles_un) { + filename = bas_f + ".urb"; + hPalette = m_palettes.m_hPalIsoUrb; + } + if (FindFileInMix(filename) == NULL) { + filename = bas_f + ".tem"; + hPalette = m_palettes.m_hPalIsoTemp; + } (*tiledata)[tilecount].bAllowTiberium = bTib; (*tiledata)[tilecount].bAllowToPlace = bPlace; @@ -3304,7 +3165,6 @@ void CLoading::LoadOverlayGraphic(const CString& lpOvrlName_, int iOvrlNum) last_succeeded_operation = 11; CString image; // the image used - CString filename; // filename of the image SHPHEADER head; char theat = cur_theat; BYTE** lpT = NULL; @@ -3312,41 +3172,41 @@ void CLoading::LoadOverlayGraphic(const CString& lpOvrlName_, int iOvrlNum) char OvrlID[50]; itoa(iOvrlNum, OvrlID, 10); - HTSPALETTE hPalette = m_hPalIsoTemp; + HTSPALETTE hPalette = m_palettes.m_hPalIsoTemp; if (cur_theat == 'T') { - hPalette = m_hPalIsoTemp; + hPalette = m_palettes.m_hPalIsoTemp; #ifdef RA2_MODE - hPalette = m_hPalIsoTemp; + hPalette = m_palettes.m_hPalIsoTemp; #endif } if (cur_theat == 'A') { - hPalette = m_hPalIsoSnow; + hPalette = m_palettes.m_hPalIsoSnow; #ifdef RA2_MODE - hPalette = m_hPalIsoSnow; + hPalette = m_palettes.m_hPalIsoSnow; #endif } - if (cur_theat == 'U' && m_hPalIsoUrb) { - hPalette = m_hPalIsoUrb; + if (cur_theat == 'U' && m_palettes.m_hPalIsoUrb) { + hPalette = m_palettes.m_hPalIsoUrb; #ifdef RA2_MODE - hPalette = m_hPalIsoUrb; + hPalette = m_palettes.m_hPalIsoUrb; #endif } - if (cur_theat == 'N' && m_hPalIsoUbn) { - hPalette = m_hPalIsoUbn; + if (cur_theat == 'N' && m_palettes.m_hPalIsoUbn) { + hPalette = m_palettes.m_hPalIsoUbn; #ifdef RA2_MODE - hPalette = m_hPalIsoUbn; + hPalette = m_palettes.m_hPalIsoUbn; #endif } - if (cur_theat == 'L' && m_hPalIsoLun) { - hPalette = m_hPalIsoLun; + if (cur_theat == 'L' && m_palettes.m_hPalIsoLun) { + hPalette = m_palettes.m_hPalIsoLun; #ifdef RA2_MODE - hPalette = m_hPalIsoLun; + hPalette = m_palettes.m_hPalIsoLun; #endif } - if (cur_theat == 'D' && m_hPalIsoDes) { - hPalette = m_hPalIsoDes; + if (cur_theat == 'D' && m_palettes.m_hPalIsoDes) { + hPalette = m_palettes.m_hPalIsoDes; #ifdef RA2_MODE - hPalette = m_hPalIsoDes; + hPalette = m_palettes.m_hPalIsoDes; #endif } @@ -3355,10 +3215,10 @@ void CLoading::LoadOverlayGraphic(const CString& lpOvrlName_, int iOvrlNum) const auto& unitPalettePrefixes = g_data["ForceOvrlUnitPalettePrefix"]; const CString sOvrlName(lpOvrlName_); if (unitPalettePrefixes.end() != std::find_if(unitPalettePrefixes.begin(), unitPalettePrefixes.end(), [&sOvrlName](const auto& pair) {return sOvrlName.Find(pair.second) == 0; })) { - forcedPalette = GetUnitPalette(cur_theat); + forcedPalette = m_palettes.GetUnitPalette(cur_theat); } if (isoPalettePrefixes.end() != std::find_if(isoPalettePrefixes.begin(), isoPalettePrefixes.end(), [&sOvrlName](const auto& pair) {return sOvrlName.Find(pair.second) == 0; })) { - forcedPalette = GetIsoPalette(cur_theat); + forcedPalette = m_palettes.GetIsoPalette(cur_theat); } HMIXFILE hMix; @@ -3386,20 +3246,7 @@ void CLoading::LoadOverlayGraphic(const CString& lpOvrlName_, int iOvrlNum) TruncSpace(image); - if (cur_theat == 'T') { - filename = image + ".tem"; - } else if (cur_theat == 'A') { - filename = image + ".sno"; - } else if (cur_theat == 'U') { - filename = image + ".urb"; - } else if (cur_theat == 'N') { - filename = image + ".ubn"; - } else if (cur_theat == 'L') { - filename = image + ".lun"; - } else if (cur_theat == 'D') { - filename = image + ".des"; - } - + CString filename = image + theatToSuffix(cur_theat); hMix = FindFileInMix(filename); @@ -3411,12 +3258,24 @@ void CLoading::LoadOverlayGraphic(const CString& lpOvrlName_, int iOvrlNum) filename.SetAt(1, theat); } - if (cur_theat == 'U' && m_hPalUnitUrb) hPalette = m_hPalUnitUrb; - if (cur_theat == 'T') hPalette = m_hPalUnitTemp; - if (cur_theat == 'A') hPalette = m_hPalUnitSnow; - if (cur_theat == 'N') hPalette = m_hPalUnitUbn; - if (cur_theat == 'L') hPalette = m_hPalUnitLun; - if (cur_theat == 'D') hPalette = m_hPalUnitDes; + if (cur_theat == 'U' && m_palettes.m_hPalUnitUrb) { + hPalette = m_palettes.m_hPalUnitUrb; + } + if (cur_theat == 'T') { + hPalette = m_palettes.m_hPalUnitTemp; + } + if (cur_theat == 'A') { + hPalette = m_palettes.m_hPalUnitSnow; + } + if (cur_theat == 'N') { + hPalette = m_palettes.m_hPalUnitUbn; + } + if (cur_theat == 'L') { + hPalette = m_palettes.m_hPalUnitLun; + } + if (cur_theat == 'D') { + hPalette = m_palettes.m_hPalUnitDes; + } hMix = FindFileInMix(filename); @@ -3449,47 +3308,59 @@ void CLoading::LoadOverlayGraphic(const CString& lpOvrlName_, int iOvrlNum) } if (cur_theat == 'T' || cur_theat == 'U') { - hPalette = m_hPalUnitTemp; + hPalette = m_palettes.m_hPalUnitTemp; } else - hPalette = m_hPalUnitSnow; + hPalette = m_palettes.m_hPalUnitSnow; } if (hMix == NULL) { filename = image + ".tem"; hMix = FindFileInMix(filename); - if (hMix) hPalette = m_hPalIsoTemp; + if (hMix) { + hPalette = m_palettes.m_hPalIsoTemp; + } } if (hMix == NULL) { filename = image + ".sno"; hMix = FindFileInMix(filename); - if (hMix) hPalette = m_hPalIsoSnow; + if (hMix) { + hPalette = m_palettes.m_hPalIsoSnow; + } } if (hMix == NULL) { filename = image + ".urb"; hMix = FindFileInMix(filename); - if (hMix && m_hPalIsoUrb) hPalette = m_hPalIsoUrb; + if (hMix && m_palettes.m_hPalIsoUrb) { + hPalette = m_palettes.m_hPalIsoUrb; + } } if (hMix == NULL) { filename = image + ".ubn"; hMix = FindFileInMix(filename); - if (hMix && m_hPalIsoUbn) hPalette = m_hPalIsoUbn; + if (hMix && m_palettes.m_hPalIsoUbn) { + hPalette = m_palettes.m_hPalIsoUbn; + } } if (hMix == NULL) { filename = image + ".lun"; hMix = FindFileInMix(filename); - if (hMix && m_hPalIsoLun) hPalette = m_hPalIsoLun; + if (hMix && m_palettes.m_hPalIsoLun) { + hPalette = m_palettes.m_hPalIsoLun; + } } if (hMix == NULL) { filename = image + ".des"; hMix = FindFileInMix(filename); - if (hMix && m_hPalIsoDes) hPalette = m_hPalIsoDes; + if (hMix && m_palettes.m_hPalIsoDes) { + hPalette = m_palettes.m_hPalIsoDes; + } } if (isveinhole == TRUE || isveins == TRUE || istiberium == TRUE) { - hPalette = m_hPalTemp; + hPalette = m_palettes.m_hPalTemp; #ifndef RA2_MODE - hPalette = m_hPalUnitTemp; + hPalette = m_palettes.m_hPalUnitTemp; #endif } @@ -3582,9 +3453,30 @@ void CLoading::LoadOverlayGraphic(const CString& lpOvrlName_, int iOvrlNum) PICDATA p; p.pic = lpT[i]; - if (hPalette == m_hPalIsoTemp || hPalette == m_hPalIsoUrb || hPalette == m_hPalIsoSnow || hPalette == m_hPalIsoDes || hPalette == m_hPalIsoLun || hPalette == m_hPalIsoUbn) p.pal = iPalIso; - if (hPalette == m_hPalTemp || hPalette == m_hPalUrb || hPalette == m_hPalSnow || hPalette == m_hPalDes || hPalette == m_hPalLun || hPalette == m_hPalUbn) p.pal = iPalTheater; - if (hPalette == m_hPalUnitTemp || hPalette == m_hPalUnitUrb || hPalette == m_hPalUnitSnow || hPalette == m_hPalUnitDes || hPalette == m_hPalUnitLun || hPalette == m_hPalUnitUbn) p.pal = iPalUnit; + if (hPalette == m_palettes.m_hPalIsoTemp + || hPalette == m_palettes.m_hPalIsoUrb + || hPalette == m_palettes.m_hPalIsoSnow + || hPalette == m_palettes.m_hPalIsoDes + || hPalette == m_palettes.m_hPalIsoLun + || hPalette == m_palettes.m_hPalIsoUbn) { + p.pal = iPalIso; + } + if (hPalette == m_palettes.m_hPalTemp + || hPalette == m_palettes.m_hPalUrb + || hPalette == m_palettes.m_hPalSnow + || hPalette == m_palettes.m_hPalDes + || hPalette == m_palettes.m_hPalLun + || hPalette == m_palettes.m_hPalUbn) { + p.pal = iPalTheater; + } + if (hPalette == m_palettes.m_hPalUnitTemp + || hPalette == m_palettes.m_hPalUnitUrb + || hPalette == m_palettes.m_hPalUnitSnow + || hPalette == m_palettes.m_hPalUnitDes + || hPalette == m_palettes.m_hPalUnitLun + || hPalette == m_palettes.m_hPalUnitUbn) { + p.pal = iPalUnit; + } p.vborder = new(VBORDER[head.cy]); int k; @@ -3624,257 +3516,6 @@ void CLoading::LoadOverlayGraphic(const CString& lpOvrlName_, int iOvrlNum) } -} - -#else // surfaces -void CLoading::LoadOverlayGraphic(LPCTSTR lpOvrlName_, int iOvrlNum) -{ - last_succeeded_operation = 11; - - CString image; // the image used - CString filename; // filename of the image - SHPHEADER head; - char theat = cur_theat; - LPDIRECTDRAWSURFACE4* lpT = NULL; - - char OvrlID[50]; - itoa(iOvrlNum, OvrlID, 10); - - HTSPALETTE hPalette; - if (cur_theat == 'T') { - hPalette = m_hPalIsoTemp; -#ifdef RA2_MODE - hPalette = m_hPalIsoTemp; -#endif - } - if (cur_theat == 'A') { - hPalette = m_hPalIsoSnow; -#ifdef RA2_MODE - hPalette = m_hPalIsoSnow; -#endif - } - if (cur_theat == 'U' && m_hPalIsoUrb) { - hPalette = m_hPalIsoUrb; -#ifdef RA2_MODE - hPalette = m_hPalIsoUrb; -#endif - } - - HMIXFILE hMix; - - CIsoView& v = *((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview; - - CString lpOvrlName = lpOvrlName_; - if (lpOvrlName.Find(' ') >= 0) lpOvrlName = lpOvrlName.Left(lpOvrlName.Find(' ')); - - CString isveinhole_t = rules.sections[lpOvrlName].values["IsVeinholeMonster"]; - CString istiberium_t = rules.sections[lpOvrlName].values["Tiberium"]; - CString isveins_t = rules.sections[lpOvrlName].values["IsVeins"]; - isveinhole_t.MakeLower(); - istiberium_t.MakeLower(); - isveins_t.MakeLower(); - BOOL isveinhole = FALSE, istiberium = FALSE, isveins = FALSE; - if (isTrue(isveinhole_t)) isveinhole = TRUE; - if (isTrue(istiberium_t)) istiberium = TRUE; - if (isTrue(isveins_t)) isveins = TRUE; - - - - - - image = lpOvrlName; - if (rules.sections[lpOvrlName].values.find("Image") != rules.sections[lpOvrlName].values.end()) - image = rules.sections[lpOvrlName].values["Image"]; - - TruncSpace(image); - - CString imagerules = image; - if (art.sections[image].values.find("Image") != art.sections[image].values.end()) - image = art.sections[image].values["Image"]; - - TruncSpace(image); - - if (cur_theat == 'T') filename = image + ".tem"; - if (cur_theat == 'A') filename = image + ".sno"; - if (cur_theat == 'U') filename = image + ".urb"; - - - hMix = FindFileInMix(filename); - - - if (hMix == NULL) { - filename = image + ".shp"; - if (isTrue(art.sections[image].values["NewTheater"])) - filename.SetAt(1, theat); - - if (cur_theat == 'U' && m_hPalUnitUrb) hPalette = m_hPalUnitUrb; - if (cur_theat == 'T') hPalette = m_hPalUnitTemp; - if (cur_theat == 'A') hPalette = m_hPalUnitSnow; - - hMix = FindFileInMix(filename); - - // errstream << (LPCSTR)filename << " " << hMix; - - if (hMix == NULL) { - filename.SetAt(1, 'T'); - hMix = FindFileInMix(filename); - } - if (hMix == NULL) { - filename.SetAt(1, 'A'); - hMix = FindFileInMix(filename); - } - if (hMix == NULL) { - filename.SetAt(1, 'U'); - hMix = FindFileInMix(filename); - } - - if (cur_theat == 'T' || cur_theat == 'U') { - hPalette = m_hPalUnitTemp; - } else - hPalette = m_hPalUnitSnow; - - } - - if (hMix == NULL) { - filename = image + ".tem"; - hMix = FindFileInMix(filename); - if (hMix) hPalette = m_hPalIsoTemp; - } - if (hMix == NULL) { - filename = image + ".sno"; - hMix = FindFileInMix(filename); - if (hMix) hPalette = m_hPalIsoSnow; - } - if (hMix == NULL) { - filename = image + ".urb"; - hMix = FindFileInMix(filename); - if (hMix && m_hPalIsoUrb) hPalette = m_hPalIsoUrb; - } - - if (isveinhole == TRUE || isveins == TRUE || istiberium == TRUE) { - hPalette = m_hPalTemp; -#ifndef RA2_MODE - hPalette = m_hPalUnitTemp; -#endif - } - - if (hMix != NULL) { - - FSunPackLib::SetCurrentSHP(filename, hMix); - { - - FSunPackLib::XCC_GetSHPHeader(&head); - - int i; - int maxPics = head.c_images; - if (maxPics > max_ovrl_img) maxPics = max_ovrl_img; // max may_ovrl_img pictures (memory usage!) - //errstream << ", loading " << maxPics << " of " << head.c_images << " pictures. "; - //errstream.flush(); - - - // create an array of pointers to directdraw surfaces - lpT = new(LPDIRECTDRAWSURFACE4[maxPics]); - memset(lpT, 0, sizeof(LPDIRECTDRAWSURFACE4) * maxPics); - - // if tiberium, change color - BOOL bIsBlueTib = FALSE; - BOOL bIsGreenTib = FALSE; - RGBTRIPLE rgbOld[16], rgbNew; -#ifndef RA2_MODE - if (istiberium) { - if (lpOvrlName[4] == '_') // other than green! - bIsBlueTib = TRUE; - else - bIsGreenTib = TRUE; - - - - int i; - for (i = 0; i < 16; i++) { - if (bIsGreenTib) { - rgbNew.rgbtBlue = 0; - if (i != 0) - rgbNew.rgbtGreen = 255 - i * 16 + 1; - else - rgbNew.rgbtGreen = 255; - rgbNew.rgbtRed = 0; - } else if (bIsBlueTib) { - if (i != 0) - rgbNew.rgbtBlue = 255 - i * 16 + 1; - else - rgbNew.rgbtBlue = 255; - rgbNew.rgbtGreen = 0; - rgbNew.rgbtRed = 0; - } - - FSunPackLib::SetTSPaletteEntry(hPalette, 0x10 + i, &rgbNew, &rgbOld[i]); - } - } -#endif - - FSunPackLib::LoadSHPImageInSurface(v.dd, hPalette, 0, maxPics, lpT); - -#ifndef RA2_MODE - if (istiberium) - for (i = 0; i < 16; i++) - FSunPackLib::SetTSPaletteEntry(hPalette, 0x10 + i, &rgbOld[i], NULL); -#endif - - for (i = 0; i < maxPics; i++) { - SHPIMAGEHEADER imghead; - FSunPackLib::XCC_GetSHPImageHeader(i, &imghead); - - if (imghead.unknown == 0) // is it a shadow or not used image? - if (lpT[i]) lpT[i]->Release(); - - if (imghead.unknown && lpT[i]) { - char ic[50]; - itoa(i, ic, 10); - - PICDATA p; - p.pic = lpT[i]; - p.x = imghead.x; - p.y = imghead.y; - - p.wHeight = imghead.cy; - p.wWidth = imghead.cx; - p.wMaxWidth = head.cx; - p.wMaxHeight = head.cy; - p.bType = PICDATA_TYPE_SHP; - - - - pics[(CString)"OVRL" + OvrlID + "_" + ic] = p; - } - } - - - delete[] lpT; - - //errstream << " --> Finished" << endl; - //errstream.flush(); - } - /*else - { - errstream << " failed"; - errstream.flush(); - }*/ - } - - else { - //errstream << "File not found: " << (LPCTSTR)filename << endl; - //errstream.flush(); - } - - int i; - for (i = 0; i < 0xFF; i++) { - char ic[50]; - itoa(i, ic, 10); - - pics[(CString)"OVRL" + OvrlID + "_" + ic].bTried = TRUE; - } - - } #endif @@ -4727,12 +4368,12 @@ void CLoading::PrepareUnitGraphic(LPCSTR lpUnittype) auto const bPowerUp = !rules.GetString(lpUnittype, "PowersUpBuilding").IsEmpty(); HTSPALETTE hPalette; - if (theat == 'T') hPalette = m_hPalIsoTemp; - if (theat == 'A') hPalette = m_hPalIsoSnow; - if (theat == 'U') hPalette = m_hPalIsoUrb; - if (theat == 'L') hPalette = m_hPalIsoLun; - if (theat == 'D') hPalette = m_hPalIsoDes; - if (theat == 'N') hPalette = m_hPalIsoUbn; + if (theat == 'T') hPalette = m_palettes.m_hPalIsoTemp; + if (theat == 'A') hPalette = m_palettes.m_hPalIsoSnow; + if (theat == 'U') hPalette = m_palettes.m_hPalIsoUrb; + if (theat == 'L') hPalette = m_palettes.m_hPalIsoLun; + if (theat == 'D') hPalette = m_palettes.m_hPalIsoDes; + if (theat == 'N') hPalette = m_palettes.m_hPalIsoUbn; CIsoView& v = *((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview; @@ -4978,7 +4619,7 @@ void CLoading::PrepareUnitGraphic(LPCSTR lpUnittype) auto limited_to_theater = artSection.GetBool("TerrainPalette") ? shp->mixfile_theater : TheaterChar::None; if (filename == "tibtre01.tem" || filename == "tibtre02.tem" || filename == "tibtre03.tem" || filename == "veinhole.tem") { - hPalette = m_hPalUnitTemp; + hPalette = m_palettes.m_hPalUnitTemp; } if (shp->mixfile > 0) { @@ -4986,7 +4627,7 @@ void CLoading::PrepareUnitGraphic(LPCSTR lpUnittype) BOOL bSuccess = FSunPackLib::SetCurrentSHP(filename, shp->mixfile); if (!bSuccess) { filename = image + ".sno"; - if (cur_theat == 'T' || cur_theat == 'U') hPalette = m_hPalIsoTemp; + if (cur_theat == 'T' || cur_theat == 'U') hPalette = m_palettes.m_hPalIsoTemp; HMIXFILE hShpMix = FindFileInMix(filename); bSuccess = FSunPackLib::SetCurrentSHP(filename, hShpMix); @@ -5030,112 +4671,4 @@ void CLoading::PrepareUnitGraphic(LPCSTR lpUnittype) } -} - -/* -Helper function that fetches the palette data from FsunPackLib -FSunPackLib doesn´t provide any special function to retrieve a color table entry, -so we have to build it ourself -Also builds color_conv -*/ -void CLoading::FetchPalettes() -{ - // SetTSPaletteEntry(HTSPALETTE hPalette, BYTE bIndex, RGBTRIPLE* rgb, RGBTRIPLE* orig); - // SetTSPaletteEntry can retrieve the current color table entry without modifying it! - - - // iso palette - HTSPALETTE hCur = 0; - if (Map->GetTheater() == THEATER0) hCur = m_hPalIsoTemp; - if (Map->GetTheater() == THEATER1) hCur = m_hPalIsoSnow; - if (Map->GetTheater() == THEATER2) hCur = m_hPalIsoUrb; - if (Map->GetTheater() == THEATER3) hCur = m_hPalIsoUbn; - if (Map->GetTheater() == THEATER4) hCur = m_hPalIsoLun; - if (Map->GetTheater() == THEATER5) hCur = m_hPalIsoDes; - - int i; - - for (i = 0; i < 256; i++) { - FSunPackLib::SetTSPaletteEntry(hCur, i, NULL /* don´t modify it!*/, &palIso[i] /*but retrieve it!*/); - } - - - // unit palette - if (Map->GetTheater() == THEATER0) hCur = m_hPalUnitTemp; - if (Map->GetTheater() == THEATER1) hCur = m_hPalUnitSnow; - if (Map->GetTheater() == THEATER2) hCur = m_hPalUnitUrb; - if (Map->GetTheater() == THEATER3) hCur = m_hPalUnitUbn; - if (Map->GetTheater() == THEATER4) hCur = m_hPalUnitLun; - if (Map->GetTheater() == THEATER5) hCur = m_hPalUnitDes; - - - for (i = 0; i < 256; i++) { - FSunPackLib::SetTSPaletteEntry(hCur, i, NULL /* don´t modify it!*/, &palUnit[i] /*but retrieve it!*/); - } - - - // theater palette - if (Map->GetTheater() == THEATER0) hCur = m_hPalTemp; - if (Map->GetTheater() == THEATER1) hCur = m_hPalSnow; - if (Map->GetTheater() == THEATER2) hCur = m_hPalUrb; - if (Map->GetTheater() == THEATER3) hCur = m_hPalUbn; - if (Map->GetTheater() == THEATER4) hCur = m_hPalLun; - if (Map->GetTheater() == THEATER5) hCur = m_hPalDes; - - - - for (i = 0; i < 256; i++) { - FSunPackLib::SetTSPaletteEntry(hCur, i, NULL /* don´t modify it!*/, &palTheater[i] /*but retrieve it!*/); - } - - - // lib palette - hCur = m_hPalLib; - - - for (i = 0; i < 256; i++) { - FSunPackLib::SetTSPaletteEntry(hCur, i, NULL /* don´t modify it!*/, &palLib[i] /*but retrieve it!*/); - } - - CreateConvTable(palIso, iPalIso); - CreateConvTable(palLib, iPalLib); - CreateConvTable(palUnit, iPalUnit); - CreateConvTable(palTheater, iPalTheater); - - CIsoView& v = *((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview; - - DDPIXELFORMAT pf; - memset(&pf, 0, sizeof(DDPIXELFORMAT)); - pf.dwSize = sizeof(DDPIXELFORMAT); - - v.lpds->GetPixelFormat(&pf); - v.pf = pf; - v.m_color_converter.reset(new FSunPackLib::ColorConverter(v.pf)); - - FSunPackLib::ColorConverter conf(pf); - - for (auto const& [name, col] : rules["Colors"]) { - COLORREF cref = v.GetColor("", col); - - color_conv[col] = conf.GetColor(GetRValue(cref), GetGValue(cref), GetBValue(cref)); - colorref_conv[cref] = color_conv[col]; - } -} - -void CLoading::CreateConvTable(RGBTRIPLE* pal, int* iPal) -{ - CIsoView& v = *((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview; - - DDPIXELFORMAT pf; - memset(&pf, 0, sizeof(DDPIXELFORMAT)); - pf.dwSize = sizeof(DDPIXELFORMAT); - - v.lpds->GetPixelFormat(&pf); - - FSunPackLib::ColorConverter conf(pf); - - int i; - for (i = 0; i < 256; i++) { - iPal[i] = conf.GetColor(pal[i].rgbtRed, pal[i].rgbtGreen, pal[i].rgbtBlue); - } -} +} \ No newline at end of file diff --git a/MissionEditor/Loading.h b/MissionEditor/Loading.h index 62b861b..929abb3 100644 --- a/MissionEditor/Loading.h +++ b/MissionEditor/Loading.h @@ -23,6 +23,7 @@ #include "FinalSunDlg.h" #include "MissionEditorPackLib.h" +#include "Palettes.h" #include #include @@ -90,8 +91,6 @@ class CLoading : public CDialog { // Construction public: - void CreateConvTable(RGBTRIPLE* pal, int* iPal); - void FetchPalettes(); void PrepareUnitGraphic(LPCSTR lpUnittype); void LoadStrings(); void FreeAll(); @@ -114,11 +113,17 @@ public: void LoadBuildingSubGraphic(const CString& subkey, const CIniFileSection& artSection, BOOL bAlwaysSetChar, char theat, HMIXFILE hShpMix, SHPHEADER& shp_h, BYTE*& shp); void LoadOverlayGraphic(const CString& lpOvrlName, int iOvrlNum); void InitVoxelNormalTables(); - HTSPALETTE GetIsoPalette(char theat); - HTSPALETTE GetUnitPalette(char theat); std::optional FindUnitShp(const CString& image, char preferred_theat, const CIniFileSection& artSection); char cur_theat; + HMIXFILE FindFileInMix(LPCTSTR lpFilename, TheaterChar* pTheaterChar = NULL); + + const HMIXFILE CacheMix() const { + return m_hCache; + } + const EXPANDMIX* ExpandMixes() const { + return m_hExpand; + } // Dialog data //{{AFX_DATA(CLoading) @@ -156,29 +161,9 @@ private: int m_pic_count; int m_bmp_count; BOOL LoadTile(LPCSTR lpFilename, HMIXFILE hOwner, HTSPALETTE hPalette, DWORD dwID, BOOL bReplacement); - HTSPALETTE m_hPalIsoTemp; - HTSPALETTE m_hPalIsoSnow; - HTSPALETTE m_hPalIsoUrb; - HTSPALETTE m_hPalUnitTemp; - HTSPALETTE m_hPalUnitSnow; - HTSPALETTE m_hPalUnitUrb; - HTSPALETTE m_hPalTemp; - HTSPALETTE m_hPalSnow; - HTSPALETTE m_hPalUrb; - HTSPALETTE m_hPalLib; - // YR pals: - HTSPALETTE m_hPalLun; - HTSPALETTE m_hPalDes; - HTSPALETTE m_hPalUbn; - HTSPALETTE m_hPalIsoLun; - HTSPALETTE m_hPalIsoDes; - HTSPALETTE m_hPalIsoUbn; - HTSPALETTE m_hPalUnitLun; - HTSPALETTE m_hPalUnitDes; - HTSPALETTE m_hPalUnitUbn; + Palettes m_palettes; - HMIXFILE FindFileInMix(LPCTSTR lpFilename, TheaterChar* pTheaterChar = NULL); HMIXFILE m_hLocal; HMIXFILE m_hSno; HMIXFILE m_hTem; diff --git a/MissionEditor/Palettes.cpp b/MissionEditor/Palettes.cpp new file mode 100644 index 0000000..3296083 --- /dev/null +++ b/MissionEditor/Palettes.cpp @@ -0,0 +1,349 @@ +#include "Palettes.h" +#include "variables.h" +#include "functions.h" + +void Palettes::Init() +{ + if (!FSunPackLib::XCC_ExtractFile("isotem.pal", u8AppDataPath + "\\TmpPalette.pal", loading.CacheMix())) + errstream << "IsoTem.pal failed\n"; + m_hPalIsoTemp = FSunPackLib::LoadTSPalette(u8AppDataPath + "\\TmpPalette.pal", NULL); + deleteFile(u8AppDataPath + "\\TmpPalette.pal"); + + if (!FSunPackLib::XCC_ExtractFile("isosno.pal", u8AppDataPath + "\\TmpPalette.pal", loading.CacheMix())) + errstream << "IsoSno.pal failed\n"; + m_hPalIsoSnow = FSunPackLib::LoadTSPalette(u8AppDataPath + "\\TmpPalette.pal", NULL); + deleteFile(u8AppDataPath + "\\TmpPalette.pal"); + + if (!FSunPackLib::XCC_ExtractFile("isourb.pal", u8AppDataPath + "\\TmpPalette.pal", loading.CacheMix())) + errstream << "IsoUrb.pal failed\n"; + m_hPalIsoUrb = FSunPackLib::LoadTSPalette(u8AppDataPath + "\\TmpPalette.pal", NULL); + deleteFile(u8AppDataPath + "\\TmpPalette.pal"); + + HMIXFILE m_hCache2 = loading.ExpandMixes()[100].hECache; + if (!FSunPackLib::XCC_ExtractFile("isolun.pal", u8AppDataPath + "\\TmpPalette.pal", m_hCache2)) + errstream << "IsoLun.pal failed\n"; + m_hPalIsoLun = FSunPackLib::LoadTSPalette(u8AppDataPath + "\\TmpPalette.pal", NULL); + deleteFile(u8AppDataPath + "\\TmpPalette.pal"); + + if (!FSunPackLib::XCC_ExtractFile("isodes.pal", u8AppDataPath + "\\TmpPalette.pal", m_hCache2)) + errstream << "IsoDes.pal failed\n"; + m_hPalIsoDes = FSunPackLib::LoadTSPalette(u8AppDataPath + "\\TmpPalette.pal", NULL); + deleteFile(u8AppDataPath + "\\TmpPalette.pal"); + + if (!FSunPackLib::XCC_ExtractFile("isoubn.pal", u8AppDataPath + "\\TmpPalette.pal", m_hCache2)) + errstream << "IsoUbn.pal failed\n"; + m_hPalIsoUbn = FSunPackLib::LoadTSPalette(u8AppDataPath + "\\TmpPalette.pal", NULL); + deleteFile(u8AppDataPath + "\\TmpPalette.pal"); + + + if (!FSunPackLib::XCC_ExtractFile("unittem.pal", u8AppDataPath + "\\TmpPalette.pal", loading.CacheMix())) + errstream << "UnitTem.pal failed"; + m_hPalUnitTemp = FSunPackLib::LoadTSPalette(u8AppDataPath + "\\TmpPalette.pal", NULL); + deleteFile(u8AppDataPath + "\\TmpPalette.pal"); + + if (!FSunPackLib::XCC_ExtractFile("unitsno.pal", u8AppDataPath + "\\TmpPalette.pal", loading.CacheMix())) + errstream << "UnitSno.pal failed\n"; + m_hPalUnitSnow = FSunPackLib::LoadTSPalette(u8AppDataPath + "\\TmpPalette.pal", NULL); + deleteFile(u8AppDataPath + "\\TmpPalette.pal"); + + if (!FSunPackLib::XCC_ExtractFile("uniturb.pal", u8AppDataPath + "\\TmpPalette.pal", loading.CacheMix())) + errstream << "UnitUrb.pal failed\n"; + m_hPalUnitUrb = FSunPackLib::LoadTSPalette(u8AppDataPath + "\\TmpPalette.pal", NULL); + deleteFile(u8AppDataPath + "\\TmpPalette.pal"); + + + if (!FSunPackLib::XCC_ExtractFile("unitlun.pal", u8AppDataPath + "\\TmpPalette.pal", m_hCache2)) + errstream << "UnitLun.pal failed\n"; + m_hPalUnitLun = FSunPackLib::LoadTSPalette(u8AppDataPath + "\\TmpPalette.pal", NULL); + deleteFile(u8AppDataPath + "\\TmpPalette.pal"); + + if (!FSunPackLib::XCC_ExtractFile("unitdes.pal", u8AppDataPath + "\\TmpPalette.pal", m_hCache2)) + errstream << "UnitDes.pal failed\n"; + m_hPalUnitDes = FSunPackLib::LoadTSPalette(u8AppDataPath + "\\TmpPalette.pal", NULL); + deleteFile(u8AppDataPath + "\\TmpPalette.pal"); + + if (!FSunPackLib::XCC_ExtractFile("unitubn.pal", u8AppDataPath + "\\TmpPalette.pal", m_hCache2)) + errstream << "UnitUbn.pal failed\n"; + m_hPalUnitUbn = FSunPackLib::LoadTSPalette(u8AppDataPath + "\\TmpPalette.pal", NULL); + deleteFile(u8AppDataPath + "\\TmpPalette.pal"); + + + if (!FSunPackLib::XCC_ExtractFile("snow.pal", u8AppDataPath + "\\TmpPalette.pal", loading.CacheMix())) + errstream << "Snow.pal failed\n"; + m_hPalSnow = FSunPackLib::LoadTSPalette(u8AppDataPath + "\\TmpPalette.pal", NULL); + deleteFile(u8AppDataPath + "\\TmpPalette.pal"); + + if (!FSunPackLib::XCC_ExtractFile("temperat.pal", u8AppDataPath + "\\TmpPalette.pal", loading.CacheMix())) + errstream << "Temperat.pal failed\n"; + m_hPalTemp = FSunPackLib::LoadTSPalette(u8AppDataPath + "\\TmpPalette.pal", NULL); + deleteFile(u8AppDataPath + "\\TmpPalette.pal"); + + if (!FSunPackLib::XCC_ExtractFile("urban.pal", u8AppDataPath + "\\TmpPalette.pal", loading.CacheMix())) + errstream << "Urban.pal failed\n"; + m_hPalUrb = FSunPackLib::LoadTSPalette(u8AppDataPath + "\\TmpPalette.pal", NULL); + deleteFile(u8AppDataPath + "\\TmpPalette.pal"); + + + if (!FSunPackLib::XCC_ExtractFile("lunar.pal", u8AppDataPath + "\\TmpPalette.pal", m_hCache2)) + errstream << "lunar.pal failed\n"; + m_hPalLun = FSunPackLib::LoadTSPalette(u8AppDataPath + "\\TmpPalette.pal", NULL); + deleteFile(u8AppDataPath + "\\TmpPalette.pal"); + + if (!FSunPackLib::XCC_ExtractFile("desert.pal", u8AppDataPath + "\\TmpPalette.pal", m_hCache2)) + errstream << "desert.pal failed\n"; + m_hPalDes = FSunPackLib::LoadTSPalette(u8AppDataPath + "\\TmpPalette.pal", NULL); + deleteFile(u8AppDataPath + "\\TmpPalette.pal"); + + if (!FSunPackLib::XCC_ExtractFile("urbann.pal", u8AppDataPath + "\\TmpPalette.pal", m_hCache2)) + errstream << "urbann.pal failed\n"; + m_hPalUbn = FSunPackLib::LoadTSPalette(u8AppDataPath + "\\TmpPalette.pal", NULL); + deleteFile(u8AppDataPath + "\\TmpPalette.pal"); + + + if (!FSunPackLib::XCC_ExtractFile("_ID2124019542", u8AppDataPath + "\\TmpPalette.pal", loading.CacheMix())) + errstream << "lib.pal failed\n"; + m_hPalLib = FSunPackLib::LoadTSPalette(u8AppDataPath + "\\TmpPalette.pal", NULL); + deleteFile(u8AppDataPath + "\\TmpPalette.pal"); + + LoadedPalettes["isotem.pal"] = new Palette(m_hPalIsoTemp); + LoadedPalettes["isosno.pal"] = new Palette(m_hPalIsoSnow); + LoadedPalettes["isourb.pal"] = new Palette(m_hPalIsoUrb); + LoadedPalettes["isoubn.pal"] = new Palette(m_hPalIsoUbn); + LoadedPalettes["isolun.pal"] = new Palette(m_hPalIsoLun); + LoadedPalettes["isodes.pal"] = new Palette(m_hPalIsoDes); + + LoadedPalettes["unittem.pal"] = new Palette(m_hPalUnitTemp); + LoadedPalettes["unitsno.pal"] = new Palette(m_hPalUnitSnow); + LoadedPalettes["uniturb.pal"] = new Palette(m_hPalUnitUrb); + LoadedPalettes["unitubn.pal"] = new Palette(m_hPalUnitUbn); + LoadedPalettes["unitlun.pal"] = new Palette(m_hPalUnitLun); + LoadedPalettes["unitdes.pal"] = new Palette(m_hPalUnitDes); + + LoadedPalettes["temperat.pal"] = new Palette(m_hPalTemp); + LoadedPalettes["snow.pal"] = new Palette(m_hPalSnow); + LoadedPalettes["urban.pal"] = new Palette(m_hPalUrb); + LoadedPalettes["urbann.pal"] = new Palette(m_hPalUbn); + LoadedPalettes["lunar.pal"] = new Palette(m_hPalLun); + LoadedPalettes["desert.pal"] = new Palette(m_hPalDes); + LoadedPalettes["lib.pal"] = new Palette(m_hPalLib); +} + + +HTSPALETTE Palettes::GetIsoPalette(char theat) +{ + HTSPALETTE isoPalette = m_hPalIsoTemp; + switch (theat) { + case 'T': + case 'G': + isoPalette = m_hPalIsoTemp; + break; + case 'A': + isoPalette = m_hPalIsoSnow; + break; + case 'U': + isoPalette = m_hPalIsoUrb; + break; + case 'N': + isoPalette = m_hPalIsoUbn; + break; + case 'D': + isoPalette = m_hPalIsoDes; + break; + case 'L': + isoPalette = m_hPalIsoLun; + break; + } + return isoPalette; +} + +HTSPALETTE Palettes::GetUnitPalette(char theat) +{ + HTSPALETTE isoPalette = m_hPalUnitTemp; + switch (theat) { + case 'T': + case 'G': + isoPalette = m_hPalUnitTemp; + break; + case 'A': + isoPalette = m_hPalUnitSnow; + break; + case 'U': + isoPalette = m_hPalUnitUrb; + break; + case 'N': + isoPalette = m_hPalUnitUbn; + break; + case 'D': + isoPalette = m_hPalUnitDes; + break; + case 'L': + isoPalette = m_hPalUnitLun; + break; + } + return isoPalette; +} + + +/* +Helper function that fetches the palette data from FsunPackLib +FSunPackLib doesn´t provide any special function to retrieve a color table entry, +so we have to build it ourself +Also builds color_conv +*/ +void Palettes::FetchPalettes() +{ + // SetTSPaletteEntry(HTSPALETTE hPalette, BYTE bIndex, RGBTRIPLE* rgb, RGBTRIPLE* orig); + // SetTSPaletteEntry can retrieve the current color table entry without modifying it! + + + // iso palette + HTSPALETTE hCur = 0; + if (Map->GetTheater() == THEATER0) hCur = m_hPalIsoTemp; + if (Map->GetTheater() == THEATER1) hCur = m_hPalIsoSnow; + if (Map->GetTheater() == THEATER2) hCur = m_hPalIsoUrb; + if (Map->GetTheater() == THEATER3) hCur = m_hPalIsoUbn; + if (Map->GetTheater() == THEATER4) hCur = m_hPalIsoLun; + if (Map->GetTheater() == THEATER5) hCur = m_hPalIsoDes; + + int i; + + for (i = 0; i < 256; i++) { + FSunPackLib::SetTSPaletteEntry(hCur, i, NULL /* don´t modify it!*/, &palIso[i] /*but retrieve it!*/); + } + + + // unit palette + if (Map->GetTheater() == THEATER0) hCur = m_hPalUnitTemp; + if (Map->GetTheater() == THEATER1) hCur = m_hPalUnitSnow; + if (Map->GetTheater() == THEATER2) hCur = m_hPalUnitUrb; + if (Map->GetTheater() == THEATER3) hCur = m_hPalUnitUbn; + if (Map->GetTheater() == THEATER4) hCur = m_hPalUnitLun; + if (Map->GetTheater() == THEATER5) hCur = m_hPalUnitDes; + + + for (i = 0; i < 256; i++) { + FSunPackLib::SetTSPaletteEntry(hCur, i, NULL /* don´t modify it!*/, &palUnit[i] /*but retrieve it!*/); + } + + + // theater palette + if (Map->GetTheater() == THEATER0) hCur = m_hPalTemp; + if (Map->GetTheater() == THEATER1) hCur = m_hPalSnow; + if (Map->GetTheater() == THEATER2) hCur = m_hPalUrb; + if (Map->GetTheater() == THEATER3) hCur = m_hPalUbn; + if (Map->GetTheater() == THEATER4) hCur = m_hPalLun; + if (Map->GetTheater() == THEATER5) hCur = m_hPalDes; + + + + for (i = 0; i < 256; i++) { + FSunPackLib::SetTSPaletteEntry(hCur, i, NULL /* don´t modify it!*/, &palTheater[i] /*but retrieve it!*/); + } + + + // lib palette + hCur = m_hPalLib; + + + for (i = 0; i < 256; i++) { + FSunPackLib::SetTSPaletteEntry(hCur, i, NULL /* don´t modify it!*/, &palLib[i] /*but retrieve it!*/); + } + + CreateConvTable(palIso, iPalIso); + CreateConvTable(palLib, iPalLib); + CreateConvTable(palUnit, iPalUnit); + CreateConvTable(palTheater, iPalTheater); + + CIsoView& v = *((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview; + + DDPIXELFORMAT pf; + memset(&pf, 0, sizeof(DDPIXELFORMAT)); + pf.dwSize = sizeof(DDPIXELFORMAT); + + v.lpds->GetPixelFormat(&pf); + v.pf = pf; + v.m_color_converter.reset(new FSunPackLib::ColorConverter(v.pf)); + + FSunPackLib::ColorConverter conf(pf); + + for (auto const& [name, col] : rules["Colors"]) { + COLORREF cref = v.GetColor("", col); + + color_conv[col] = conf.GetColor(GetRValue(cref), GetGValue(cref), GetBValue(cref)); + colorref_conv[cref] = color_conv[col]; + } +} + +void Palettes::CreateConvTable(RGBTRIPLE* pal, int* iPal) +{ + CIsoView& v = *((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview; + + DDPIXELFORMAT pf; + memset(&pf, 0, sizeof(DDPIXELFORMAT)); + pf.dwSize = sizeof(DDPIXELFORMAT); + + v.lpds->GetPixelFormat(&pf); + + FSunPackLib::ColorConverter conf(pf); + + int i; + for (i = 0; i < 256; i++) { + iPal[i] = conf.GetColor(pal[i].rgbtRed, pal[i].rgbtGreen, pal[i].rgbtBlue); + } +} + + +Palette* Palettes::LoadPalette(const CString& palName) +{ + if (LoadedPalettes.size() == 0) { + Palettes::Init(); + } + + auto it = LoadedPalettes.find(palName); + if (it != LoadedPalettes.end()) { + return it->second; + } + + BytePalette buffer; + HMIXFILE mixIdx = loading.FindFileInMix(palName); + + if (FSunPackLib::LoadTSPalette(reinterpret_cast(buffer.Data), palName, mixIdx)) { + auto pal = new Palette(buffer); + LoadedPalettes[palName] = pal; + return pal; + } + + return nullptr; +} + +void Palettes::Clear() +{ + for (auto& pair : LoadedPalettes) { + delete(pair.second); + } + LoadedPalettes.clear(); + RemappedPalettes.clear(); + Init(); +} + +Palette::Palette(const BytePalette& bytes) +{ + for (auto idx = 0; idx < 256; idx++) { + Data[idx].R = bytes.Data[idx].red; + Data[idx].G = bytes.Data[idx].green; + Data[idx].B = bytes.Data[idx].blue; + Data[idx].Zero = 0; + } +} + +Palette::Palette(HTSPALETTE indexer) +{ + for (auto idx = 0; idx < 256; idx++) { + RGBTRIPLE ret; + FSunPackLib::SetTSPaletteEntry(indexer, idx, NULL /* don´t modify it!*/, &ret /*but retrieve it!*/); + Data[idx].R = ret.rgbtRed; + Data[idx].G = ret.rgbtGreen; + Data[idx].B = ret.rgbtBlue; + Data[idx].Zero = 0; + } +} diff --git a/MissionEditor/Palettes.h b/MissionEditor/Palettes.h new file mode 100644 index 0000000..282aa1c --- /dev/null +++ b/MissionEditor/Palettes.h @@ -0,0 +1,89 @@ +#pragma once + +#include +#include +#include "MissionEditorPackLib.h" + +struct BGRStruct +{ + unsigned char B, G, R, Zero; + bool operator< (const BGRStruct& rhs) const { return *(int*)this < *(int*)&rhs; } + bool operator==(const BGRStruct& rhs) const { return *(int*)this == *(int*)&rhs; } +}; + +struct ColorStruct +{ + unsigned char red, green, blue; +}; + +class BytePalette +{ +public: + ColorStruct Data[256]; + + ColorStruct& operator[](int index) { return Data[index]; } +}; + +class Palette +{ +public: + Palette(const BytePalette& bytes); + Palette(HTSPALETTE raw); + + BGRStruct& operator[](int index) { return Data[index]; } + ColorStruct GetByteColor(int index) { + ColorStruct ret; + BGRStruct& tmp = Data[index]; + ret.red = tmp.R; + ret.green = tmp.G; + ret.blue = tmp.B; + return ret; + } +private: + BGRStruct Data[256]; +}; + +class Palettes +{ +public: + Palettes(CLoading& loading) : + loading(loading) + {} + + void Init(); + + HTSPALETTE GetIsoPalette(char theat); + HTSPALETTE GetUnitPalette(char theat); + void FetchPalettes(); + void CreateConvTable(RGBTRIPLE* pal, int* iPal); + + Palette* LoadPalette(const CString& palName); + void Clear(); + + HTSPALETTE m_hPalIsoTemp; + HTSPALETTE m_hPalIsoSnow; + HTSPALETTE m_hPalIsoUrb; + + HTSPALETTE m_hPalUnitTemp; + HTSPALETTE m_hPalUnitSnow; + HTSPALETTE m_hPalUnitUrb; + HTSPALETTE m_hPalTemp; + HTSPALETTE m_hPalSnow; + HTSPALETTE m_hPalUrb; + HTSPALETTE m_hPalLib; + // YR pals: + HTSPALETTE m_hPalLun; + HTSPALETTE m_hPalDes; + HTSPALETTE m_hPalUbn; + HTSPALETTE m_hPalIsoLun; + HTSPALETTE m_hPalIsoDes; + HTSPALETTE m_hPalIsoUbn; + HTSPALETTE m_hPalUnitLun; + HTSPALETTE m_hPalUnitDes; + HTSPALETTE m_hPalUnitUbn; + +private: + CLoading& loading; + std::map LoadedPalettes; + std::map> RemappedPalettes; +}; \ No newline at end of file diff --git a/MissionEditorPackLib/MissionEditorPackLib.cpp b/MissionEditorPackLib/MissionEditorPackLib.cpp index 115dc25..dfa18a0 100644 --- a/MissionEditorPackLib/MissionEditorPackLib.cpp +++ b/MissionEditorPackLib/MissionEditorPackLib.cpp @@ -25,6 +25,7 @@ struct IUnknown; #include #include +#include #include "mix_file.h" #include "cc_file.h" @@ -1934,46 +1935,78 @@ namespace FSunPackLib return TRUE; } + bool loadTSPaletteRaw(Cpal_file& pal, const std::string& szPalette) + { + return open_read(pal, szPalette) == 0; + } + bool loadTSPaletteFromMix(Cpal_file& pal, const std::string& szPalette, HMIXFILE hPaletteOwner) + { + if (szPalette[0] == '_' && szPalette[1] == 'I' && szPalette[2] == 'D') { + char id[256]; + strcpy_s(id, &szPalette[3]); + int iId = atoi(id); + return pal.open(iId, mixfiles[hPaletteOwner - 1]) == 0; + } + return pal.open(szPalette, mixfiles[hPaletteOwner - 1]) == 0; + } + + + std::optional loadTSPalette(const std::string& szPalette, HMIXFILE hPaletteOwner) + { + Cpal_file pal; + if (hPaletteOwner == NULL) { + if (!loadTSPaletteRaw(pal, szPalette)) { + return std::nullopt; + } + } else { + if (!loadTSPaletteFromMix(pal, szPalette, hPaletteOwner)) { + return std::nullopt; + } + } + if (!pal.is_open()) { + return std::nullopt; + } + return pal; + } + + bool LoadTSPalette(RGBTRIPLE* ret, const std::string& szPalette, HMIXFILE hPaletteOwner) + { + if (ret == nullptr) { + return false; + } + + auto&& palRet = loadTSPalette(szPalette, hPaletteOwner); + if (!palRet.has_value()) { + return false; + } + auto&& pal = palRet.value(); + auto const paldata = reinterpret_cast(pal.get_data()); + memcpy(ret, paldata, 768); + convert_palet_18_to_24(reinterpret_cast(ret)); + pal.close(); + return true; + } + + bool LoadTSPalette(RGBTRIPLE* ret, LPCSTR szPalette, HMIXFILE hPaletteOwner) + { + return LoadTSPalette(ret, std::string(szPalette), hPaletteOwner); + } HTSPALETTE LoadTSPalette(const std::string& szPalette, HMIXFILE hPaletteOwner) { - Cpal_file pal; - RGBTRIPLE* paldata; - - if (dwPalCount > 255) + if (dwPalCount > 255) { return NULL; - if (hPaletteOwner == NULL) { - if (open_read(pal, szPalette)) - return NULL; - } else { - if (szPalette[0] == '_' && szPalette[1] == 'I' && szPalette[2] == 'D') { - char id[256]; - strcpy_s(id, &szPalette[3]); - int iId = atoi(id); - if (pal.open(iId, mixfiles[hPaletteOwner - 1])) - return NULL; - } else { - if (pal.open(szPalette, mixfiles[hPaletteOwner - 1]) != 0) - return NULL; - } } - if (!pal.is_open()) + t_palet buffer; + if (!LoadTSPalette(reinterpret_cast(buffer), szPalette, hPaletteOwner)) { return NULL; - - dwPalCount++; - - - paldata = (RGBTRIPLE*)pal.get_data(); - //t_palet t_p; - memcpy(ts_palettes[dwPalCount - 1], paldata, 768); - bFirstConv[dwPalCount - 1] = TRUE; - convert_palet_18_to_24(ts_palettes[dwPalCount - 1]); - - pal.close(); + } + memcpy(ts_palettes[dwPalCount], buffer, 768); + bFirstConv[dwPalCount] = TRUE; + dwPalCount++;// HTSPALETTE is always internal `index+1` return dwPalCount; - } HTSPALETTE LoadTSPalette(LPCSTR szPalette, HMIXFILE hPaletteOwner) diff --git a/MissionEditorPackLib/MissionEditorPackLib.h b/MissionEditorPackLib/MissionEditorPackLib.h index aa83ccc..e724930 100644 --- a/MissionEditorPackLib/MissionEditorPackLib.h +++ b/MissionEditorPackLib/MissionEditorPackLib.h @@ -35,10 +35,10 @@ typedef DWORD HTSPALETTE; struct SHPHEADER { - __int16 zero; - __int16 cx; - __int16 cy; - __int16 c_images; + __int16 zero;// type + __int16 cx;// width + __int16 cy;// height + __int16 c_images;// count }; struct SHPIMAGEHEADER @@ -199,10 +199,11 @@ namespace FSunPackLib BOOL LoadSHPImage(int startIndex, int wantedNum, BYTE** lpPics); BOOL LoadSHPImage(int iImageIndex, std::vector& pic); + bool LoadTSPalette(RGBTRIPLE* ret, const std::string& szPalette, HMIXFILE hPaletteOwner = NULL); + bool LoadTSPalette(RGBTRIPLE* ret, LPCSTR szPalette, HMIXFILE hPaletteOwner = NULL); HTSPALETTE LoadTSPalette(LPCSTR szPalette, HMIXFILE hPaletteOwner); HTSPALETTE LoadTSPalette(const std::string& szPalette, HMIXFILE hPaletteOwner); - BOOL SetTSPaletteEntry(HTSPALETTE hPalette, BYTE bIndex, RGBTRIPLE* rgb, RGBTRIPLE* orig); From 800cd951b6e773872b7b73f63f1b040463910a9f Mon Sep 17 00:00:00 2001 From: Zero Fanker Date: Sat, 18 May 2024 21:19:01 -0400 Subject: [PATCH 04/13] generally transplanted FA2sp image handling logic, but still WIP TODO: Fix palette background issue. Fix voxel handling . --- MissionEditor/INIMeta.h | 9 + MissionEditor/IniMega.h | 4 +- MissionEditor/IsoView.cpp | 16 +- MissionEditor/Loading.cpp | 2046 ++++++++--------- MissionEditor/Loading.h | 43 +- MissionEditor/MapData.cpp | 8 +- MissionEditor/MissionEditor.vcxproj | 3 + MissionEditor/MissionEditor.vcxproj.filters | 9 + MissionEditor/Palettes.cpp | 1 + MissionEditor/Palettes.h | 4 + MissionEditor/Structs.h | 2 +- MissionEditor/ViewObjects.h | 2 + MissionEditor/inlines.h | 19 +- MissionEditor/variables.cpp | 3 +- MissionEditor/variables.h | 5 +- MissionEditorPackLib/MissionEditorPackLib.cpp | 20 +- MissionEditorPackLib/MissionEditorPackLib.h | 27 +- 17 files changed, 1058 insertions(+), 1163 deletions(-) diff --git a/MissionEditor/INIMeta.h b/MissionEditor/INIMeta.h index deffb31..57528b5 100644 --- a/MissionEditor/INIMeta.h +++ b/MissionEditor/INIMeta.h @@ -27,6 +27,15 @@ public: CString GetStringOr(const CString& section, const CString& key, const CString& def) const; IniSectionGroup GetSection(const CString& section) const; + bool GetBool(const CString& pSection, const CString& pKey, bool def = false) const + { + return INIHelper::StringToBool(GetString(pSection, pKey), def); + } + int GetInteger(const CString& pSection, const CString& pKey, int def = 0) const + { + return INIHelper::StringToInteger(GetString(pSection, pKey), def); + } + auto Size() const { return m_group.size(); } void Append(const CIniFile& INI); diff --git a/MissionEditor/IniMega.h b/MissionEditor/IniMega.h index b29ccd4..447fcf8 100644 --- a/MissionEditor/IniMega.h +++ b/MissionEditor/IniMega.h @@ -19,7 +19,7 @@ private: }; -IniFileGroup IniMegaFile::GetRules() +inline IniFileGroup IniMegaFile::GetRules() { IniFileGroup m_group; m_group.Append(rules); @@ -27,7 +27,7 @@ IniFileGroup IniMegaFile::GetRules() return m_group; } -bool IniMegaFile::isNullOrEmpty(const CString& value) +inline bool IniMegaFile::isNullOrEmpty(const CString& value) { return !value.GetLength() || value == "none" || value == ""; } \ No newline at end of file diff --git a/MissionEditor/IsoView.cpp b/MissionEditor/IsoView.cpp index 57fa652..eed8806 100644 --- a/MissionEditor/IsoView.cpp +++ b/MissionEditor/IsoView.cpp @@ -547,7 +547,7 @@ inline void CalculateHouseColorPalette(int house_pal[houseColorRelMax + 1], cons /* There is no need for newpal */ -__forceinline void BlitPic(void* dst, int x, int y, int dleft, int dtop, int dpitch, int dright, int dbottom, PICDATA& pd, int* color = NULL, int* newPal = NULL)//BYTE* src, int swidth, int sheight) +__forceinline void BlitPic(void* dst, int x, int y, int dleft, int dtop, int dpitch, int dright, int dbottom, PICDATA& pd, int* color = NULL, const int* newPal = NULL)//BYTE* src, int swidth, int sheight) { ASSERT(pd.bType != PICDATA_TYPE_BMP); @@ -650,7 +650,7 @@ __forceinline void BlitPic(void* dst, int x, int y, int dleft, int dtop, int dpi } } -__forceinline void BlitPicHalfTransp(void* dst, int x, int y, int dleft, int dtop, int dpitch, int dright, int dbottom, PICDATA& pd, int* color = NULL, int* newPal = NULL)//BYTE* src, int swidth, int sheight) +__forceinline void BlitPicHalfTransp(void* dst, int x, int y, int dleft, int dtop, int dpitch, int dright, int dbottom, PICDATA& pd, int* color = NULL, const int* newPal = NULL)//BYTE* src, int swidth, int sheight) { ASSERT(pd.bType != PICDATA_TYPE_BMP); @@ -5372,7 +5372,7 @@ void CIsoView::DrawMap() int w = 1, h = 1; PICDATA pic; - if (id > -1 && id < 0x0F00) { + if (id > -1 && id < buildingInfoCapacity) { w = buildinginfo[id].w; h = buildinginfo[id].h; int dir = objp.direction / 32; @@ -5402,7 +5402,9 @@ void CIsoView::DrawMap() ::Map->UpdateBuildingInfo(&objp.type); int dir = (7 - objp.direction / 32) % 8; pic = buildinginfo[id].pic[dir]; - if (pic.pic == NULL) pic = buildinginfo[id].pic[0]; + if (pic.pic == NULL) { + pic = buildinginfo[id].pic[0]; + } } if (pic.pic == NULL) { #ifndef NOSURFACES @@ -5480,7 +5482,7 @@ void CIsoView::DrawMap() int id = m.node.type; int w = 1, h = 1; PICDATA pic; - if (id > -1 && id < 0x0F00) { + if (id > -1 && id < buildingInfoCapacity) { w = buildinginfo[id].w; h = buildinginfo[id].h; pic = buildinginfo[id].pic[0]; @@ -5694,7 +5696,7 @@ void CIsoView::DrawMap() int id = m.terraintype; int w = 1, h = 1; PICDATA pic; - if (id > -1 && id < 0x0F00) { + if (id > -1 && id < buildingInfoCapacity) { w = treeinfo[id].w; h = treeinfo[id].h; pic = treeinfo[id].pic; @@ -5745,7 +5747,7 @@ void CIsoView::DrawMap() int id = m.smudgetype; PICDATA pic; - if (id > -1 && id < 0x0F00) { + if (id > -1 && id < buildingInfoCapacity) { pic = smudgeinfo[id].pic; } diff --git a/MissionEditor/Loading.cpp b/MissionEditor/Loading.cpp index c61b5da..050800b 100644 --- a/MissionEditor/Loading.cpp +++ b/MissionEditor/Loading.cpp @@ -39,6 +39,7 @@ #include #include "VoxelNormals.h" #include +#include "IniMega.h" #ifdef _DEBUG #define new DEBUG_NEW @@ -46,12 +47,21 @@ static char THIS_FILE[] = __FILE__; #endif +struct DrawRect +{ + int X{}; + int Y{}; + int Width{}; + int Height{}; +}; + ///////////////////////////////////////////////////////////////////////////// // Dialogfeld CLoading -CLoading::CLoading(CWnd* pParent /*=NULL*/) - : CDialog(CLoading::IDD, pParent) +CLoading::CLoading(CWnd* pParent /*=NULL*/) : + CDialog(CLoading::IDD, pParent), + m_palettes(*this) { //{{AFX_DATA_INIT(CLoading) //}}AFX_DATA_INIT @@ -476,7 +486,194 @@ void CLoading::Load() } +void SetTheaterLetter(CString& basename, char TheaterIdentifier) +{ + if (TheaterIdentifier != 0 && basename.GetLength() >= 2) { + char c0 = basename[0]; + char c1 = basename[1] & ~0x20; // evil hack to uppercase, copied from Ares + if (isalpha(static_cast(c0))) { + if (c1 == 'A' || c1 == 'T') { + basename.SetAt(1, TheaterIdentifier); + } + } + } +} +void SetGenericTheaterLetter(CString& name) +{ + name.SetAt(1, 'G'); +} + +bool CLoading::LoadSingleFrameShape(const CString& name, int nFrame, int deltaX, int deltaY) +{ + CString file = name + ".SHP"; + SetTheaterLetter(file, this->cur_theat); + + + auto nMix = FindFileInMix(file); + //check whether there can be a valid file + do { + if (FSunPackLib::XCC_DoesFileExist(file, nMix)) { + break; + } + SetGenericTheaterLetter(file); + nMix = FindFileInMix(file); + if (FSunPackLib::XCC_DoesFileExist(file, nMix)) { + break; + } + file = name + ".SHP"; + nMix = FindFileInMix(file); + if (FSunPackLib::XCC_DoesFileExist(file, nMix)) { + break; + } + return false; + } while (0); + + SHPHEADER header; + unsigned char* pBuffer = nullptr; + + if (!FSunPackLib::SetCurrentSHP(file, nMix)) { + return false; + } + if (!FSunPackLib::XCC_GetSHPHeader(&header)) { + return false; + } + if (!FSunPackLib::LoadSHPImage(nFrame, 1, &pBuffer)) { + return false; + } + + UnionSHP_Add(pBuffer, header.cx, header.cy, deltaX, deltaY); + + return true; +}; + +void CLoading::UnionSHP_Add(unsigned char* pBuffer, int Width, int Height, int DeltaX, int DeltaY, bool UseTemp) +{ + UnionSHP_Data[UseTemp].push_back(SHPUnionData{ pBuffer,Width,Height,DeltaX,DeltaY }); +} + + +void CLoading::UnionSHP_GetAndClear(unsigned char*& pOutBuffer, int* OutWidth, int* OutHeight, bool UseTemp) +{ + // never calls it when UnionSHP_Data is empty + + if (UnionSHP_Data[UseTemp].size() == 1) { + pOutBuffer = UnionSHP_Data[UseTemp][0].pBuffer; + *OutWidth = UnionSHP_Data[UseTemp][0].Width; + *OutHeight = UnionSHP_Data[UseTemp][0].Height; + UnionSHP_Data[UseTemp].clear(); + return; + } + + // For each shp, we make their center at the same point, this will give us proper result. + int W = 0, H = 0; + + for (auto& data : UnionSHP_Data[UseTemp]) { + if (W < data.Width + 2 * abs(data.DeltaX)) { + W = data.Width + 2 * abs(data.DeltaX); + } + if (H < data.Height + 2 * abs(data.DeltaY)) { + H = data.Height + 2 * abs(data.DeltaY); + } + } + + // just make it work like unsigned char[W][H]; + pOutBuffer = new(unsigned char[W * H]); + *OutWidth = W; + *OutHeight = H; + + int ImageCenterX = W / 2; + int ImageCenterY = H / 2; + + // Image[X][Y] <=> pOutBuffer[Y * W + X]; + for (auto& data : UnionSHP_Data[UseTemp]) { + int nStartX = ImageCenterX - data.Width / 2 + data.DeltaX; + int nStartY = ImageCenterY - data.Height / 2 + data.DeltaY; + + for (int j = 0; j < data.Height; ++j) + for (int i = 0; i < data.Width; ++i) + if (auto nPalIdx = data.pBuffer[j * data.Width + i]) + pOutBuffer[(nStartY + j) * W + nStartX + i] = nPalIdx; + + delete[](data.pBuffer); + } + + UnionSHP_Data[UseTemp].clear(); +} + + +void CLoading::VXL_Add(const unsigned char* pCache, int X, int Y, int Width, int Height) +{ + for (int j = 0; j < Height; ++j) + for (int i = 0; i < Width; ++i) + if (auto ch = pCache[j * Width + i]) + VXL_Data[(j + Y) * 0x100 + X + i] = ch; +} + +void CLoading::VXL_GetAndClear(unsigned char*& pBuffer, int* OutWidth, int* OutHeight) +{ + /* TODO : Save memory + int validFirstX = 0x100 - 1; + int validFirstY = 0x100 - 1; + int validLastX = 0; + int validLastY = 0; + + for (int j = 0; j < 0x100; ++j) + { + for (int i = 0; i < 0x100; ++i) + { + unsigned char ch = VXL_Data[j * 0x100 + i]; + if (ch != 0) + { + if (i < validFirstX) + validFirstX = i; + if (j < validFirstY) + validFirstY = j; + if (i > validLastX) + validLastX = i; + if (j > validLastY) + validLastY = j; + } + } + } + */ + pBuffer = new unsigned char[0x10000]; + memcpy_s(pBuffer, 0x10000, VXL_Data, 0x10000); + memset(VXL_Data, 0, 0x10000); +} + +bool IsImageLoaded(const CString& ID) { + auto const it = pics.find(ID); + if (it == pics.end()) { + return false; + } + return it->second.pic != nullptr; +} + +void GetFullPaletteName(CString& PaletteName, char theater) +{ + switch (theater) { + case 'A': + PaletteName += "sno.pal"; + return; + case 'U': + PaletteName += "urb.pal"; + return; + case 'N': + PaletteName += "ubn.pal"; + return; + case 'D': + PaletteName += "des.pal"; + return; + case 'L': + PaletteName += "lun.pal"; + return; + case 'T': + default: + PaletteName += "tem.pal"; + return; + } +} // // InitPics loads all graphics except terrain graphics! @@ -1168,916 +1365,713 @@ int lepton_to_screen_y(int leptons) return leptons * f_y / 256; } -BOOL CLoading::LoadUnitGraphic(const CString& lpUnittype) +CLoading::ObjectType CLoading::GetItemType(const CString& ID) { - errstream << "Loading: " << lpUnittype << endl; + if (ObjectTypes.size() == 0) { + auto load = [this](const CString& typeListName, ObjectType e) { + auto const& rules = IniMegaFile::GetRules(); + auto const& items = rules.GetSection(typeListName); + for (auto it = items.begin(); it != items.end(); ++it) { + auto const& [_, id] = *it; + ObjectTypes.insert({ id, e }); + } + }; + + load("InfantryTypes", ObjectType::Infantry); + load("VehicleTypes", ObjectType::Vehicle); + load("AircraftTypes", ObjectType::Aircraft); + load("BuildingTypes", ObjectType::Building); + load("SmudgeTypes", ObjectType::Smudge); + load("TerrainTypes", ObjectType::Terrain); + } + + auto itr = ObjectTypes.find(ID); + if (itr != ObjectTypes.end()) + return itr->second; + return ObjectType::Unknown; +} + +BOOL CLoading::LoadUnitGraphic(const CString& ID) +{ + errstream << "Loading: " << ID << endl; errstream.flush(); last_succeeded_operation = 10; - CString _rules_image; // the image used - CString filename; // filename of the image char theat = cur_theat; // standard theater char is t (Temperat). a is snow. - bool bAlwaysSetChar = FALSE; // second char is always theater, even if NewTheater not specified! - WORD wStep = 1; // step is 1 for infantry, buildings, etc, and for shp vehicles it specifies the step rate between every direction - WORD wStartWalkFrame = 0; // for examply cyborg reaper has another walk starting frame - int iTurretOffset = 0; // used for centering y pos of turret (if existing) (for vehicles) - const bool bStructure = rules["BuildingTypes"].HasValue(lpUnittype); // is this a structure? - const bool bVehicle = rules["VehicleTypes"].HasValue(lpUnittype); // is this a structure? - auto const bPowerUp = !rules.GetString(lpUnittype, "PowersUpBuilding").IsEmpty(); - - - CIsoView& v = *((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview; - - _rules_image = lpUnittype; - _rules_image = rules.GetStringOr(lpUnittype, "Image", _rules_image); - - CString _art_image = _rules_image; - auto const& imageID = art.GetString(_rules_image, "Image"); - if (!imageID.IsEmpty()) { - if (!g_data.GetBool("IgnoreArtImage", _rules_image)) { - _art_image = imageID; - } + auto eItemType = GetItemType(ID); + switch (eItemType) { + case ObjectType::Infantry: + this->LoadInfantry(ID); + break; + case ObjectType::Terrain: + case ObjectType::Smudge: + this->LoadTerrainOrSmudge(ID); + break; + case ObjectType::Vehicle: + case ObjectType::Aircraft: + this->LoadVehicleOrAircraft(ID); + break; + case ObjectType::Building: + this->LoadBuilding(ID); + break; + case CLoading::ObjectType::Unknown: + default: + break; } - const CString& image = _art_image; - const auto& rulesSection = rules[lpUnittype]; - const auto& artSection = art[image]; - - // is it a shp graphic? - if (!artSection.GetBool("Voxel")) { - try { - - auto shp = FindUnitShp(image, cur_theat, artSection); - if (!shp) { - errstream << "Building SHP in theater " << cur_theat << " not found: " << image << endl; - errstream.flush(); - missingimages[lpUnittype] = TRUE; - return FALSE; - } - - filename = shp->filename; - HTSPALETTE hPalette = shp->palette; - const auto hShpMix = shp->mixfile; - theat = static_cast(shp->theat); - auto limited_to_theater = artSection.GetBool("TerrainPalette") ? shp->mixfile_theater : TheaterChar::None; - - - SHPHEADER head; - int superanim_1_zadjust = 0; - int superanim_2_zadjust = 0; - int superanim_3_zadjust = 0; - int superanim_4_zadjust = 0; - - CString turretanim_name; - CString turretanim_filename; - CString barrelanim_filename; - BYTE* bib = NULL; - SHPHEADER bib_h; - BYTE* activeanim = NULL; - SHPHEADER activeanim_h; - BYTE* idleanim = NULL; - SHPHEADER idleanim_h; - BYTE* activeanim2 = NULL; - SHPHEADER activeanim2_h; - BYTE* activeanim3 = NULL; - SHPHEADER activeanim3_h; - BYTE* superanim1 = NULL; - SHPHEADER superanim1_h; - BYTE* superanim2 = NULL; - SHPHEADER superanim2_h; - BYTE* superanim3 = NULL; - SHPHEADER superanim3_h; - BYTE* superanim4 = NULL; - SHPHEADER superanim4_h; - BYTE* specialanim1 = NULL; - SHPHEADER specialanim1_h; - BYTE* specialanim2 = NULL; - SHPHEADER specialanim2_h; - BYTE* specialanim3 = NULL; - SHPHEADER specialanim3_h; - BYTE* specialanim4 = NULL; - SHPHEADER specialanim4_h; - SHPHEADER* lpT_h = NULL; - std::vector turretColors[8]; - std::vector turretLighting[8]; - std::vector vxlBarrelColors[8]; - std::vector vxlBarrelLighting[8]; - SHPHEADER turrets_h[8]; - SHPIMAGEHEADER turretinfo[8]; - SHPHEADER barrels_h[8]; - SHPIMAGEHEADER barrelinfo[8]; - - - if (hShpMix > 0) { - - std::string shp_mixfile; - if (FSunPackLib::XCC_GetMixName(hShpMix, shp_mixfile)) { - errstream << (LPCTSTR)filename << " found "; - errstream << " in " << shp_mixfile << endl; - errstream.flush(); - } - //hShpMix=20; - - LoadBuildingSubGraphic("BibShape", artSection, bAlwaysSetChar, theat, hShpMix, bib_h, bib); - - LoadBuildingSubGraphic("ActiveAnim", artSection, bAlwaysSetChar, theat, hShpMix, activeanim_h, activeanim); - LoadBuildingSubGraphic("IdleAnim", artSection, bAlwaysSetChar, theat, hShpMix, idleanim_h, idleanim); - LoadBuildingSubGraphic("ActiveAnim2", artSection, bAlwaysSetChar, theat, hShpMix, activeanim2_h, activeanim2); - LoadBuildingSubGraphic("ActiveAnim3", artSection, bAlwaysSetChar, theat, hShpMix, activeanim3_h, activeanim3); - if (!g_data.GetBool("IgnoreSuperAnim1", image)) - LoadBuildingSubGraphic("SuperAnim", artSection, bAlwaysSetChar, theat, hShpMix, superanim1_h, superanim1); - if (!g_data.GetBool("IgnoreSuperAnim2", image)) - LoadBuildingSubGraphic("SuperAnimTwo", artSection, bAlwaysSetChar, theat, hShpMix, superanim2_h, superanim2); - if (!g_data.GetBool("IgnoreSuperAnim3", image)) - LoadBuildingSubGraphic("SuperAnimThree", artSection, bAlwaysSetChar, theat, hShpMix, superanim3_h, superanim3); - if (!g_data.GetBool("IgnoreSuperAnim4", image)) - LoadBuildingSubGraphic("SuperAnimFour", artSection, bAlwaysSetChar, theat, hShpMix, superanim4_h, superanim4); - LoadBuildingSubGraphic("SpecialAnim", artSection, bAlwaysSetChar, theat, hShpMix, specialanim1_h, specialanim1); - LoadBuildingSubGraphic("SpecialAnimTwo", artSection, bAlwaysSetChar, theat, hShpMix, specialanim2_h, specialanim2); - LoadBuildingSubGraphic("SpecialAnimThree", artSection, bAlwaysSetChar, theat, hShpMix, specialanim3_h, specialanim3); - LoadBuildingSubGraphic("SpecialAnimFour", artSection, bAlwaysSetChar, theat, hShpMix, specialanim4_h, specialanim4); - - BOOL bVoxelTurret = FALSE; - BOOL bVoxelBarrel = FALSE; - - FSunPackLib::VoxelNormalClass vnc = FSunPackLib::VoxelNormalClass::Unknown; - - if (rules.GetBool(lpUnittype, "Turret")) { - turretanim_name = rules.GetString(lpUnittype, "TurretAnim"); - auto vxl_turretanim_filename = turretanim_name.IsEmpty() ? image + "tur.vxl" : turretanim_name + ".vxl"; - auto vxl_barrelanim_filename = image + "barl.vxl"; - auto const& imageID = art.GetString(turretanim_name, "Image"); - if (!imageID.IsEmpty()) { - vxl_turretanim_filename = imageID + ".vxl"; - } - - if (bStructure && turretanim_name.GetLength() > 0 && !rules.GetBool(lpUnittype, "TurretAnimIsVoxel")) { - turretanim_filename = turretanim_name + ".shp"; - auto const& imageID = art.GetString(turretanim_name, "Image"); - if (!imageID.IsEmpty()) { - turretanim_filename = imageID + ".shp"; - } - turretanim_filename.SetAt(1, 'G'); - if (artSection.GetBool("NewTheater", true)) { - auto tmp = turretanim_filename; - tmp.SetAt(1, theat); - if (FSunPackLib::XCC_DoesFileExist(tmp, hShpMix)) { - turretanim_filename = tmp; - } - } - - turretanim_filename.MakeUpper(); - FSunPackLib::SetCurrentSHP(turretanim_filename, hShpMix); - FSunPackLib::XCC_GetSHPHeader(&head); - - auto const turretFrameStart = art.GetInteger(turretanim_name, "LoopStart"); - auto const turretFrameCount = art.GetInteger(turretanim_name, "LoopEnd", 32); - const WORD wAnimCount = turretFrameCount / 8; // anims between each "normal" direction - - for (auto i = 0; i < 8; i++) { - if (turretFrameStart + i * wAnimCount < head.c_images) { - FSunPackLib::XCC_GetSHPImageHeader(turretFrameStart + i * wAnimCount, &turretinfo[i]); - FSunPackLib::XCC_GetSHPHeader(&turrets_h[i]); - FSunPackLib::LoadSHPImage(turretFrameStart + i * wAnimCount, turretColors[i]); - turretLighting[i].clear(); - } - - } - } else if ( - (bStructure && !turretanim_name.IsEmpty() && rules.GetBool(lpUnittype, "TurretAnimIsVoxel")) - || (!bStructure && (FindFileInMix(vxl_turretanim_filename) || FindFileInMix(vxl_barrelanim_filename))) - ) { - turretanim_filename = vxl_turretanim_filename; - barrelanim_filename = vxl_barrelanim_filename; - - HMIXFILE hVXL = FindFileInMix(vxl_turretanim_filename); - HMIXFILE hBarl = FindFileInMix(vxl_barrelanim_filename); - - iTurretOffset = artSection.GetInteger("TurretOffset", iTurretOffset); - Vec3f turretModelOffset(iTurretOffset / 6.0f, 0.0f, 0.0f); - - - if (hVXL) { - bVoxelTurret = TRUE; - - if ( - FSunPackLib::SetCurrentVXL(turretanim_filename, hVXL) - ) { - // we assume the voxel normal class is always the same for the combined voxels - FSunPackLib::GetVXLSectionInfo(0, vnc); - - int i; - - for (i = 0; i < 8; i++) { - float r_x, r_y, r_z; - - - const int dir = bVehicle ? ((i + 1) % 8) : i; - r_x = 300; - r_y = 0; - r_z = 45 * dir + 90; - - // convert - const double pi = 3.141592654; - const Vec3f rotation(r_x / 180.0f * pi, r_y / 180.0f * pi, r_z / 180.0f * pi); - - - RECT r; - int center_x, center_y; - if (! - FSunPackLib::LoadVXLImage(*m_voxelNormalTables, lightDirection, rotation, turretModelOffset, turretColors[i], turretLighting[i], ¢er_x, ¢er_y, 0, 0, 0, 0, 0, &r) - ) { - - } else { - turrets_h[i].cx = r.right - r.left; - turrets_h[i].cy = r.bottom - r.top; - - turretinfo[i].x = center_x; - turretinfo[i].y = center_y; - turretinfo[i].cx = r.right - r.left; - turretinfo[i].cy = r.bottom - r.top; - - } - - } - } - } - if (hBarl) { - bVoxelBarrel = TRUE; - - if ( - FSunPackLib::SetCurrentVXL(barrelanim_filename, hBarl) - ) { - // we assume the voxel normal class is always the same for the combined voxels - FSunPackLib::GetVXLSectionInfo(0, vnc); - - int i; - - for (i = 0; i < 8; i++) { - float r_x, r_y, r_z; - - - const int dir = bVehicle ? ((i + 1) % 8) : i; - r_x = 300; - r_y = 0; - r_z = 45 * dir + 90; - - // convert - const double pi = 3.141592654; - const Vec3f rotation(r_x / 180.0f * pi, r_y / 180.0f * pi, r_z / 180.0f * pi); - - - RECT r; - int center_x, center_y; - if (! - FSunPackLib::LoadVXLImage( - *m_voxelNormalTables, - lightDirection, - rotation, - turretModelOffset, - vxlBarrelColors[i], - vxlBarrelLighting[i], - ¢er_x, - ¢er_y, - rules.GetInteger(image, "TurretAnimZAdjust"), - 0, 0, 0, 0, &r) - ) { - - } else { - barrels_h[i].cx = r.right - r.left; - barrels_h[i].cy = r.bottom - r.top; - - barrelinfo[i].x = center_x; - barrelinfo[i].y = center_y; - barrelinfo[i].cx = r.right - r.left; - barrelinfo[i].cy = r.bottom - r.top; - - } - - } - } - } - } - } - - - wStep = art.GetInteger(image, "WalkFrames", wStep); - wStartWalkFrame = art.GetInteger(image, "StartWalkFrame", wStartWalkFrame); - - if (art.GetString(image, "Palette") == "lib") { - hPalette = m_hPalLib; - } - - BOOL bSuccess = FSunPackLib::SetCurrentSHP(filename, hShpMix); - if ( - !bSuccess - ) { - filename = image + ".sno"; - if (cur_theat == 'T' || cur_theat == 'U' /* || cur_theat=='N' ? */) { - hPalette = m_hPalIsoTemp; - } - HMIXFILE hShpMix = FindFileInMix(filename); - bSuccess = FSunPackLib::SetCurrentSHP(filename, hShpMix); - - if (!bSuccess) { - missingimages[lpUnittype] = TRUE; - } - } - - if (bSuccess) { - - FSunPackLib::XCC_GetSHPHeader(&head); - int maxPics = head.c_images; - if (bStructure && !bPowerUp) { - maxPics = 1; - } - if (rules.GetBool(lpUnittype, "Turret")) { - maxPics = 8; - } - if (maxPics > 8) { - maxPics = 8; // we only need 8 pictures for every direction! - } - - if (!bStructure && rules.GetBool(image, "Turret")) { - int iStartTurret = wStartWalkFrame + 8 * wStep; - const WORD wAnimCount = 4; // anims between each "normal" direction, seems to be hardcoded - for (auto i = 0; i < 8; i++) { - if (iStartTurret + i * wAnimCount < head.c_images) { - FSunPackLib::XCC_GetSHPImageHeader(iStartTurret + i * wAnimCount, &turretinfo[i]); - FSunPackLib::XCC_GetSHPHeader(&turrets_h[i]); - FSunPackLib::LoadSHPImage(iStartTurret + i * wAnimCount, turretColors[i]); - } - } - } - - - - // create an array of pointers to directdraw surfaces - auto lpT = new(BYTE * [maxPics]); - ::memset(lpT, 0, sizeof(BYTE) * maxPics); - std::vector> lighting(maxPics); - std::vector shp_image_headers(maxPics); - - if (lpUnittype == "CAWBNKR1") { - printf(""); - } - - if (bStructure) { - for (auto i = 0; i < maxPics; i++) { - FSunPackLib::XCC_GetSHPImageHeader(0, &shp_image_headers[i]); - FSunPackLib::LoadSHPImage(0, 1, &lpT[i]); - } - } else {// vehicle, infantry - // walk frames used - for (auto i = 0; i < maxPics; i++) { - const int dir = bVehicle ? ((i + 1) % 8) : i; - const int pic_in_file = dir * wStep + wStartWalkFrame; - FSunPackLib::LoadSHPImage(pic_in_file, 1, &lpT[i]); - FSunPackLib::XCC_GetSHPImageHeader(pic_in_file, &shp_image_headers[i]); - } - } - - // this block handles one-direction only building frame - if (bStructure) { - SHPIMAGEHEADER imghead = shp_image_headers[0]; - auto blitDst = lpT[0]; - if (bib != NULL) { - Blit_Pal(blitDst, 0, 0, head.cx, head.cy, bib, bib_h.cx, bib_h.cy); - - imghead.cx = head.cx - imghead.x; // update size of main graphic - imghead.cy = head.cy - imghead.y; - - } - - if (activeanim != NULL) { - Blit_Pal(blitDst, 0, 0, head.cx, head.cy, activeanim, activeanim_h.cx, activeanim_h.cy); - - - } - - if (idleanim != NULL) { - Blit_Pal(blitDst, 0, 0, head.cx, head.cy, idleanim, idleanim_h.cx, idleanim_h.cy); - - - } - - if (activeanim2 != NULL) { - Blit_Pal(blitDst, 0, 0, head.cx, head.cy, activeanim2, activeanim2_h.cx, activeanim2_h.cy); - - } - - if (activeanim3 != NULL) { - Blit_Pal(blitDst, 0, 0, head.cx, head.cy, activeanim3, activeanim3_h.cx, activeanim3_h.cy); - - } - - if (superanim1 != NULL) { - Blit_Pal(blitDst, 0, superanim_1_zadjust, head.cx, head.cy, superanim1, superanim1_h.cx, superanim1_h.cy); - } - - if (superanim2 != NULL) { - Blit_Pal(blitDst, 0, superanim_2_zadjust, head.cx, head.cy, superanim2, superanim2_h.cx, superanim2_h.cy); - } - - if (superanim3 != NULL) { - Blit_Pal(blitDst, 0, superanim_3_zadjust, head.cx, head.cy, superanim3, superanim3_h.cx, superanim3_h.cy); - } - if (superanim4 != NULL && strcmp(lpUnittype, "YAGNTC") != NULL) { - Blit_Pal(blitDst, 0, superanim_4_zadjust, head.cx, head.cy, superanim4, superanim4_h.cx, superanim4_h.cy); - - - } - if (specialanim1 != NULL) { - Blit_Pal(blitDst, 0, 0, head.cx, head.cy, specialanim1, specialanim1_h.cx, specialanim1_h.cy); - } - if (specialanim2 != NULL) { - Blit_Pal(blitDst, 0, 0, head.cx, head.cy, specialanim2, specialanim2_h.cx, specialanim2_h.cy); - } - if (specialanim3 != NULL) { - Blit_Pal(blitDst, 0, 0, head.cx, head.cy, specialanim3, specialanim3_h.cx, specialanim3_h.cy); - } - - if (specialanim4 != NULL) { - Blit_Pal(blitDst, 0, 0, head.cx, head.cy, specialanim4, specialanim4_h.cx, specialanim4_h.cy); - - } - } - - for (auto i = 0; i < maxPics; i++) { - SHPIMAGEHEADER* imghead = &shp_image_headers[i]; - if (bStructure) { - imghead = &shp_image_headers[0]; - if (!lpT[i]) { - auto const dataLen = imghead->cx * imghead->cy; - auto data = new(BYTE[dataLen]); - memcpy(data, lpT[0], dataLen); - lpT[i] = data; - } - } - //FSunPackLib::XCC_GetSHPImageHeader(pic_in_file, &imghead); - - - - if (!vxlBarrelLighting[i].empty() || !turretLighting[i].empty()) - lighting[i].resize(head.cx * head.cy, 46); // value needs to lead to 1.0 lighting - - // barrels hidden behind turret: - if (!vxlBarrelColors[i].empty() && (i == 1 || i == 0 || i == 7)) { - DDSURFACEDESC2 ddsd; - ::memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); - ddsd.dwSize = sizeof(DDSURFACEDESC2); - ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT; - ddsd.dwWidth = barrels_h[i].cx; - ddsd.dwHeight = barrels_h[i].cy; - - int XMover, YMover; - char c[50]; - itoa(i, c, 10); -#ifdef RA2_MODE - XMover = g_data.GetInteger("BuildingVoxelBarrelsRA2", lpUnittype + "X"); - YMover = g_data.GetInteger("BuildingVoxelBarrelsRA2", lpUnittype + "Y"); - XMover += g_data.GetInteger("BuildingVoxelBarrelsRA2", lpUnittype + "X" + c); - YMover += g_data.GetInteger("BuildingVoxelBarrelsRA2", lpUnittype + "Y" + c); -#else - XMover = atoi(g_data.GetInteger("BuildingVoxelBarrels"].lpUnittype + "X"); - YMover = atoi(g_data.GetInteger("BuildingVoxelBarrels"].lpUnittype + "Y"); -#endif - - RECT srcRect, destRect; - - int mx = head.cx / 2 + rules.GetInteger(image, "TurretAnimX") - barrelinfo[i].x; - int my = head.cy / 2 + rules.GetInteger(image, "TurretAnimY") - barrelinfo[i].y; - - srcRect.top = 0; - srcRect.left = 0; - srcRect.right = ddsd.dwWidth; - srcRect.bottom = ddsd.dwHeight; - destRect.top = YMover + my; - destRect.left = XMover + mx; - destRect.right = destRect.left + ddsd.dwWidth; - destRect.bottom = destRect.top + ddsd.dwHeight; - - - errstream << "vxl barrel: " << i << " size: " << ddsd.dwWidth << " " << ddsd.dwHeight << " at " << destRect.left << " " << destRect.top << endl; - errstream.flush(); - Blit_PalD(lpT[i], destRect, vxlBarrelColors[i].data(), srcRect, ddsd.dwWidth, head.cx, ddsd.dwHeight, head.cy); - Blit_PalD(lighting[i].data(), destRect, vxlBarrelLighting[i].data(), srcRect, ddsd.dwWidth, head.cx, ddsd.dwHeight, head.cy, vxlBarrelColors[i].data()); - - } - - - if (!turretColors[i].empty()) { - DDSURFACEDESC2 ddsd; - ::memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); - ddsd.dwSize = sizeof(DDSURFACEDESC2); - ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT; - //turrets[i]->GetSurfaceDesc(&ddsd); - // replace DX code: - ddsd.dwWidth = turrets_h[i].cx; - ddsd.dwHeight = turrets_h[i].cy; - - int XMover = 0; - int YMover = 0; - - RECT srcRect, destRect; - - if (bVoxelTurret) { - int mx = head.cx / 2 + rules.GetInteger(lpUnittype, "TurretAnimX") - turretinfo[i].x; - int my = head.cy / 2 + rules.GetInteger(lpUnittype, "TurretAnimY") - turretinfo[i].y; - - char c[50]; - itoa(i, c, 10); -#ifdef RA2_MODE - XMover = g_data.GetInteger("BuildingVoxelTurretsRA2", lpUnittype + "X"); - YMover = g_data.GetInteger("BuildingVoxelTurretsRA2", lpUnittype + "Y"); - XMover += g_data.GetInteger("BuildingVoxelTurretsRA2", lpUnittype + "X" + c); - YMover += g_data.GetInteger("BuildingVoxelTurretsRA2", lpUnittype + "Y" + c); -#else - XMover = g_data.GetInteger("BuildingVoxelTurrets", lpUnittype + "X"); - YMover = g_data.GetInteger("BuildingVoxelTurrets", lpUnittype + "Y"); -#endif - - srcRect.top = 0; - srcRect.left = 0; - srcRect.right = ddsd.dwWidth; - srcRect.bottom = ddsd.dwHeight; - destRect.top = YMover + my; - destRect.left = XMover + mx; - destRect.right = destRect.left + ddsd.dwWidth;; - destRect.bottom = destRect.top + ddsd.dwHeight; - - } else {// !bVoxelTurret - int mx = rules.GetInteger(lpUnittype, "TurretAnimX"); - int my = rules.GetInteger(lpUnittype, "TurretAnimY");//+rules.GetInteger(image, "barrelAnimZAdjust"); - - srcRect.top = 0; - srcRect.left = 0; - srcRect.right = turrets_h[i].cx; - srcRect.bottom = turrets_h[i].cy; - destRect.top = YMover + my; - destRect.left = XMover + mx; - destRect.right = destRect.left + srcRect.right; - destRect.bottom = destRect.top + srcRect.bottom; - } - - errstream << "vxl turret: " << i << " size: " << ddsd.dwWidth << " " << ddsd.dwHeight << " at " << destRect.left << " " << destRect.top << endl; - errstream.flush(); - Blit_PalD(lpT[i], destRect, turretColors[i].data(), srcRect, ddsd.dwWidth, head.cx, ddsd.dwHeight, head.cy); - Blit_PalD(lighting[i].data(), destRect, turretLighting[i].data(), srcRect, ddsd.dwWidth, head.cx, ddsd.dwHeight, head.cy, turretColors[i].data()); - - } - - // barrels in front of turret - if (!vxlBarrelColors[i].empty() && i != 1 && i != 0 && i != 7) { - DDSURFACEDESC2 ddsd; - ::memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); - ddsd.dwSize = sizeof(DDSURFACEDESC2); - ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT; - ddsd.dwWidth = barrels_h[i].cx; - ddsd.dwHeight = barrels_h[i].cy; - - int XMover, YMover; - char c[50]; - itoa(i, c, 10); -#ifdef RA2_MODE - XMover = g_data.GetInteger("BuildingVoxelBarrelsRA2", lpUnittype + "X"); - YMover = g_data.GetInteger("BuildingVoxelBarrelsRA2", lpUnittype + "Y"); - XMover += g_data.GetInteger("BuildingVoxelBarrelsRA2", lpUnittype + (CString)"X" + c); - YMover += g_data.GetInteger("BuildingVoxelBarrelsRA2", lpUnittype + (CString)"Y" + c); -#else - XMover = g_data.GetInteger("BuildingVoxelBarrels", lpUnittype + "X"); - YMover = g_data.GetInteger("BuildingVoxelBarrels", lpUnittype + "Y"); -#endif - - RECT srcRect, destRect; - - int mx = head.cx / 2 + rules.GetInteger(image, "TurretAnimX") - barrelinfo[i].x; - int my = head.cy / 2 + rules.GetInteger(image, "TurretAnimY") - barrelinfo[i].y; - - srcRect.top = 0; - srcRect.left = 0; - srcRect.right = ddsd.dwWidth; - srcRect.bottom = ddsd.dwHeight; - destRect.top = YMover + my; - destRect.left = XMover + mx; - destRect.right = destRect.left + ddsd.dwWidth; - destRect.bottom = destRect.top + ddsd.dwHeight; - - - errstream << "vxl barrel: " << i << " size: " << ddsd.dwWidth << " " << ddsd.dwHeight << " at " << destRect.left << " " << destRect.top << endl; - errstream.flush(); - Blit_PalD(lpT[i], destRect, vxlBarrelColors[i].data(), srcRect, ddsd.dwWidth, head.cx, ddsd.dwHeight, head.cy); - Blit_PalD(lighting[i].data(), destRect, vxlBarrelLighting[i].data(), srcRect, ddsd.dwWidth, head.cx, ddsd.dwHeight, head.cy, vxlBarrelColors[i].data()); - - - } - - if (!bPowerUp && i != 0 && (imghead->unknown == 0 && !g_data.GetBool("Debug", "IgnoreSHPImageHeadUnused")) && bStructure) { - if (lpT[i]) delete[] lpT[i]; - lpT[i] = NULL; - } else { - char ic[50]; - itoa(i, ic, 10); - - PICDATA p; - p.pic = lpT[i]; - if (std::find_if(lighting[i].begin(), lighting[i].end(), [](const BYTE b) { return b != 255; }) != lighting[i].end()) - p.lighting = std::shared_ptr>(new std::vector(std::move(lighting[i]))); - else - lighting[i].clear(); - p.vborder = new(VBORDER[head.cy]); - int k; - for (k = 0; k < head.cy; k++) { - int l, r; - GetDrawBorder(lpT[i], head.cx, k, l, r, 0); - p.vborder[k].left = l; - p.vborder[k].right = r; - } - - if (hPalette == m_hPalIsoTemp || hPalette == m_hPalIsoUrb || hPalette == m_hPalIsoSnow || hPalette == m_hPalIsoUbn || hPalette == m_hPalIsoDes || hPalette == m_hPalIsoLun) p.pal = iPalIso; - if (hPalette == m_hPalTemp || hPalette == m_hPalUrb || hPalette == m_hPalSnow || hPalette == m_hPalUbn || hPalette == m_hPalLun || hPalette == m_hPalDes) p.pal = iPalTheater; - if (hPalette == m_hPalUnitTemp || hPalette == m_hPalUnitUrb || hPalette == m_hPalUnitSnow || hPalette == m_hPalUnitDes || hPalette == m_hPalUnitLun || hPalette == m_hPalUnitUbn) p.pal = iPalUnit; - if (hPalette == m_hPalLib) p.pal = iPalLib; - - p.x = imghead->x; - p.y = imghead->y; - p.wHeight = imghead->cy; - p.wWidth = imghead->cx; - p.wMaxWidth = head.cx; - p.wMaxHeight = head.cy; - p.bType = PICDATA_TYPE_SHP; - p.bTerrain = limited_to_theater; - - pics[image + ic] = p; - - //errstream << " --> finished as " << (LPCSTR)(image+ic) << endl; - //errstream.flush(); - } - - - } - - delete[] lpT; - - - if (bib) delete[] bib; - if (activeanim) delete[] activeanim; - if (idleanim) delete[] idleanim; - if (activeanim2) delete[] activeanim2; - if (activeanim3) delete[] activeanim3; - if (superanim1) delete[] superanim1; - if (superanim2) delete[] superanim2; - if (superanim3) delete[] superanim3; - if (superanim4) delete[] superanim4; - if (specialanim1) delete[] specialanim1; - if (specialanim2) delete[] specialanim2; - if (specialanim3) delete[] specialanim3; - if (specialanim4) delete[] specialanim4; - - //for(i=0;i<8;i++) - // if(turrets[i]) delete[] turrets[i]; - - } - - //errstream << " --> Finished" << endl; - //errstream.flush(); - } - - else { - errstream << "File in theater " << cur_theat << " not found: " << (LPCTSTR)filename << endl; - errstream.flush(); - - missingimages[lpUnittype] = TRUE; - } - - } catch (...) { - errstream << " exception " << endl; - errstream.flush(); - } - - - } else { - filename = image + ".vxl"; - - HMIXFILE hMix = FindFileInMix(filename); - if (hMix == FALSE) { - missingimages[lpUnittype] = TRUE; - return FALSE; - } - - int XMover, YMover; -#ifdef RA2_MODE - XMover = g_data.GetInteger("VehicleVoxelTurretsRA2", lpUnittype + "X"); - YMover = g_data.GetInteger("VehicleVoxelTurretsRA2", lpUnittype + "Y"); -#else - XMover = g_data.GetInteger("VehicleVoxelTurrets", lpUnittype + "X"); - YMover = g_data.GetInteger("VehicleVoxelTurrets", lpUnittype + "Y"); -#endif - - iTurretOffset = art.GetInteger(image, "TurretOffset", iTurretOffset); - - int i; - - for (i = 0; i < 8; i++) { - float r_x, r_y, r_z; - - - r_x = 300; - r_y = 0; - r_z = 45 * i + 90; - - //r_x = 0; - //r_y = 0; - //r_z = 0; - - // convert - const double pi = 3.141592654; - Vec3f rotation(r_x / 180.0f * pi, r_y / 180.0f * pi, r_z / 180.0f * pi); - Vec3f turretModelOffset(iTurretOffset / 6.0f, 0.0f, 0.0f); - - - std::vector colors; - std::shared_ptr> pLighting(new std::vector); - auto& lighting = *pLighting; - std::vector turretColors; - std::vector turretNormals; - std::vector barrelColors; - std::vector barrelNormals; - RECT lprT; - RECT lprB; - int turret_x, turret_y, turret_x_zmax, turret_y_zmax, barrel_x, barrel_y; - - if (rules.GetBool(lpUnittype, "Turret")) { - if (FSunPackLib::SetCurrentVXL(image + "tur.vxl", hMix)) { - FSunPackLib::LoadVXLImage(*m_voxelNormalTables, lightDirection, rotation, turretModelOffset, turretColors, turretNormals, &turret_x, &turret_y, 0, &turret_x_zmax, &turret_y_zmax, -1, -1, &lprT); - } - if (FSunPackLib::SetCurrentVXL(image + "barl.vxl", hMix)) { - FSunPackLib::LoadVXLImage(*m_voxelNormalTables, lightDirection, rotation, turretModelOffset, barrelColors, barrelNormals, &barrel_x, &barrel_y, 0, NULL, NULL, 0, 0, &lprB); - } - } - - - if (!FSunPackLib::SetCurrentVXL(filename, hMix)) { - return FALSE; - } - - - - int xcenter, ycenter, xcenter_zmax, ycenter_zmax; - - RECT r; - - if (! - FSunPackLib::LoadVXLImage(*m_voxelNormalTables, lightDirection, rotation, Vec3f(), colors, lighting, &xcenter, &ycenter, 0, &xcenter_zmax, &ycenter_zmax, -1, -1, &r) - ) { - return FALSE; - } - - FSunPackLib::VoxelNormalClass vnc = FSunPackLib::VoxelNormalClass::Unknown; - FSunPackLib::GetVXLSectionInfo(0, vnc); // we assume the normal class for all voxels sections and turrets or barrels is the same - - DDSURFACEDESC2 ddsd; - ::memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); - ddsd.dwSize = sizeof(DDSURFACEDESC2); - ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT; - ddsd.dwWidth = r.right - r.left; - ddsd.dwHeight = r.bottom - r.top; - - //lpT->GetSurfaceDesc(&ddsd); - - // turret - if (turretColors.size()) { - DDSURFACEDESC2 ddsdT; - ::memset(&ddsdT, 0, sizeof(DDSURFACEDESC2)); - ddsdT.dwSize = sizeof(DDSURFACEDESC2); - ddsdT.dwFlags = DDSD_WIDTH | DDSD_HEIGHT; - ddsdT.dwWidth = lprT.right - lprT.left; - ddsdT.dwHeight = lprT.bottom - lprT.top; - //lpTurret->GetSurfaceDesc(&ddsdT); - - DDBLTFX fx; - ::memset(&fx, 0, sizeof(DDBLTFX)); - fx.dwSize = sizeof(DDBLTFX); - - - RECT srcRect, destRect; - srcRect.left = 0; - srcRect.right = ddsdT.dwWidth; - destRect.left = xcenter - turret_x + XMover; - destRect.right = destRect.left + ddsdT.dwWidth; - srcRect.top = 0; - srcRect.bottom = ddsdT.dwHeight; - destRect.top = ycenter - turret_y + YMover; - destRect.bottom = destRect.top + ddsdT.dwHeight; - - errstream << destRect.left << " " << destRect.top << endl; - errstream.flush(); - - Blit_PalD(colors.data(), destRect, turretColors.data(), srcRect, ddsdT.dwWidth, ddsd.dwWidth, ddsdT.dwHeight, ddsd.dwHeight); - Blit_PalD(lighting.data(), destRect, turretNormals.data(), srcRect, ddsdT.dwWidth, ddsd.dwWidth, ddsdT.dwHeight, ddsd.dwHeight, turretColors.data()); - //AssertNormals(turretColors, turretNormals); - - } - - // barrel - if (barrelColors.size()) { - DDSURFACEDESC2 ddsdB; - ::memset(&ddsdB, 0, sizeof(DDSURFACEDESC2)); - ddsdB.dwSize = sizeof(DDSURFACEDESC2); - ddsdB.dwFlags = DDSD_WIDTH | DDSD_HEIGHT; - ddsdB.dwWidth = lprB.right - lprB.left; - ddsdB.dwHeight = lprB.bottom - lprB.top; - //lpBarrel->GetSurfaceDesc(&ddsdB); - - DDSURFACEDESC2 ddsdT; - ::memset(&ddsdT, 0, sizeof(DDSURFACEDESC2)); - ddsdT.dwSize = sizeof(DDSURFACEDESC2); - ddsdT.dwFlags = DDSD_WIDTH | DDSD_HEIGHT; - - if (turretColors.size()) { - ddsdT.dwWidth = lprT.right - lprT.left; - ddsdT.dwHeight = lprT.bottom - lprT.top; - //lpTurret->GetSurfaceDesc(&ddsdT); - } - - - DDBLTFX fx; - ::memset(&fx, 0, sizeof(DDBLTFX)); - fx.dwSize = sizeof(DDBLTFX); - - RECT srcRect, destRect; - srcRect.left = 0; - srcRect.right = ddsdB.dwWidth; - destRect.left = xcenter - barrel_x + XMover; - destRect.right = destRect.left + ddsdB.dwWidth; - srcRect.top = 0; - srcRect.bottom = ddsdB.dwHeight; - destRect.top = ycenter - barrel_y + YMover; - destRect.bottom = destRect.top + ddsdB.dwHeight; - - Blit_PalD(colors.data(), destRect, barrelColors.data(), srcRect, ddsdB.dwWidth, ddsd.dwWidth, ddsdB.dwHeight, ddsd.dwHeight); - Blit_PalD(lighting.data(), destRect, barrelNormals.data(), srcRect, ddsdB.dwWidth, ddsd.dwWidth, ddsdB.dwHeight, ddsd.dwHeight, barrelColors.data()); - //AssertNormals(vxlBarrelColors, barrelNormals); - - } - - // all VXL, so every non-transparent area should have a normal - //AssertNormals(colors, lighting); - - char ic[50]; - itoa(7 - i, ic, 10); - - errstream << ddsd.dwWidth << " " << ddsd.dwHeight << "\n"; - PICDATA p; - p.pic = new(BYTE[colors.size()]); - ::memcpy(p.pic, colors.data(), colors.size()); - p.lighting = pLighting; - p.normalClass = vnc; - - p.vborder = new(VBORDER[ddsd.dwHeight]); - int k; - for (k = 0; k < ddsd.dwHeight; k++) { - int l, r; - GetDrawBorder(colors.data(), ddsd.dwWidth, k, l, r, 0); - p.vborder[k].left = l; - p.vborder[k].right = r; - } - - //if(hPalette==m_hPalIsoTemp || hPalette==m_hPalIsoUrb || hPalette==m_hPalIsoSnow) p.pal=iPalIso; - //if(hPalette==m_hPalTemp || hPalette==m_hPalUrb || hPalette==m_hPalSnow) p.pal=iPalTheater; - //if(hPalette==m_hPalUnitTemp || hPalette==m_hPalUnitUrb || hPalette==m_hPalUnitSnow) p.pal=iPalUnit; - //if(hPalette==m_hPalLib) p.pal=iPalLib; - p.pal = iPalUnit; - - p.x = -xcenter; - p.y = -ycenter; - p.wHeight = ddsd.dwHeight; - p.wWidth = ddsd.dwWidth; - p.wMaxWidth = ddsd.dwWidth; - p.wMaxHeight = ddsd.dwHeight; - p.bType = PICDATA_TYPE_VXL; - p.bTerrain = TheaterChar::None; - - pics[image + ic] = p; - - errstream << "vxl saved as " << (LPCSTR)image << (LPCSTR)ic << endl; - errstream.flush(); - - //delete[] lpT; - - } - - - - } - - - return FALSE; } + + + +CString CLoading::GetTerrainOrSmudgeFileID(const CString& ID) +{ + CString ArtID = GetArtID(ID); + CString ImageID = art.GetStringOr(ArtID, "Image", ArtID); + + return ImageID; +} + +CString CLoading::GetBuildingFileID(const CString& ID) +{ + CString ArtID = GetArtID(ID); + CString ImageID = art.GetStringOr(ArtID, "Image", ArtID); + + CString backupID = ImageID; + SetTheaterLetter(ImageID, cur_theat); + + CString validator = ImageID + ".SHP"; + int nMix = this->FindFileInMix(validator); + if (!FSunPackLib::XCC_DoesFileExist(validator, nMix)) { + SetGenericTheaterLetter(ImageID); + validator = ImageID + ".SHP"; + nMix = this->FindFileInMix(validator); + if (!FSunPackLib::XCC_DoesFileExist(validator, nMix)) { + ImageID = backupID; + } + } + return ImageID; +} + +CString CLoading::GetInfantryFileID(const CString& ID) +{ + CString ArtID = GetArtID(ID); + + CString ImageID = art.GetStringOr(ArtID, "Image", ArtID); + auto const& rules = IniMegaFile::GetRules(); + + if (rules.GetBool(ID, "AlternateTheaterArt")) { + ImageID += this->cur_theat; + } else if (rules.GetBool(ID, "AlternateArcticArt")) { + if (this->cur_theat == 'A') { + ImageID += 'A'; + } + } + if (!art.TryGetSection(ImageID)) { + ImageID = ArtID; + } + return ImageID; +} + +CString CLoading::GetArtID(const CString& ID) +{ + auto const& rules = IniMegaFile::GetRules(); + return rules.GetStringOr(ID, "Image", ID); +} + +CString CLoading::GetVehicleOrAircraftFileID(const CString& ID) +{ + CString ArtID = GetArtID(ID); + + CString ImageID = art.GetStringOr(ArtID, "Image", ArtID); + + return ImageID; +} + +void CLoading::LoadBuilding(const CString& ID) +{ + CString ArtID = GetArtID(ID); + CString ImageID = GetBuildingFileID(ID); + + auto const& rules = IniMegaFile::GetRules(); + auto const& ppPowerUpBld = rules.GetString(ID, "PowersUpBuilding"); + // Early load + if (!ppPowerUpBld.IsEmpty()) { + CString SrcBldName = GetBuildingFileID(*ppPowerUpBld) + "0"; + if (!IsImageLoaded(SrcBldName)) + LoadBuilding(*ppPowerUpBld); + } + + auto loadAnimFrame = [this, &ArtID, &ID](const CString& key, const CString& controlKey) { + auto const imageID = art.GetStringOr(ArtID, key, ArtID); + if (!imageID.IsEmpty()) { + if (!g_data.GetBool(controlKey, ID)) { + int nStartFrame = art.GetInteger(imageID, "LoopStart"); + LoadSingleFrameShape(art.GetStringOr(imageID, "Image", imageID), nStartFrame); + } + } + }; + + int nBldStartFrame = art.GetInteger(ArtID, "LoopStart", 0); + + if (!this->LoadSingleFrameShape(ImageID, nBldStartFrame)) { + return; + } + + loadAnimFrame("IdleAnim", "IgnoreIdleAnim"); + loadAnimFrame("ActiveAnim", "IgnoreActiveAnim1"); + loadAnimFrame("ActiveAnimTwo", "IgnoreActiveAnim2"); + loadAnimFrame("ActiveAnimThree", "IgnoreActiveAnim3"); + loadAnimFrame("ActiveAnimFour", "IgnoreActiveAnim4"); + loadAnimFrame("SuperAnim", "IgnoreSuperAnim1"); + loadAnimFrame("SuperAnimTwo", "IgnoreSuperAnim2"); + loadAnimFrame("SuperAnimThree", "IgnoreSuperAnim3"); + loadAnimFrame("SuperAnimFour", "IgnoreSuperAnim4"); + auto bibImageName = art.GetString(ArtID, "BibShape"); + if (bibImageName.GetLength()) { + LoadSingleFrameShape(art.GetStringOr(bibImageName, "Image", bibImageName)); + } + + CString PaletteName = art.GetStringOr(ArtID, "Palette", "unit"); + if (art.GetBool(ArtID, "TerrainPalette")) { + PaletteName = "iso"; + } + GetFullPaletteName(PaletteName, cur_theat); + + CString DictName; + + unsigned char* pBuffer; + int width, height; + UnionSHP_GetAndClear(pBuffer, &width, &height); + + if (ID == "NAWEAP2") { + printf(""); + } + + // No turret + if (!rules.GetBool(ID, "Turret")) { + DictName.Format("%s%d", ID, 0); + SetImageData(pBuffer, DictName, width, height, m_palettes.LoadPalette(PaletteName)); + return; + } + // Has turret + if (rules.GetBool(ID, "TurretAnimIsVoxel")) { + int turzadjust = rules.GetInteger(ID, "TurretAnimZAdjust"); // no idea why apply it but it worked + + CString TurName = rules.GetStringOr(ID, "TurretAnim", ID + "tur"); + CString BarlName = ID + "barl"; + + + //if (!DrawStuff::is_vpl_loaded()) { + // DrawStuff::load_vpl("voxels.vpl"); + //} + + unsigned char* pTurImages[8]{ nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr }; + unsigned char* pBarlImages[8]{ nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr }; + DrawRect turrect[8] = { 0 }; + int barlrect[8][4] = { 0 }; + + + CString VXLName = BarlName + ".vxl"; + CString HVAName = BarlName + ".hva"; + + HMIXFILE hBarl = FindFileInMix(BarlName); + if (hBarl && FSunPackLib::SetCurrentVXL(VXLName, hBarl)) { + auto vnc = FSunPackLib::VoxelNormalClass::Unknown; + std::vector vxlColors[8]; + std::vector vxlLighting[8]; + // we assume the voxel normal class is always the same for the combined voxels + FSunPackLib::GetVXLSectionInfo(0, vnc); + for (int i = 0; i < 8; ++i) { + float r_x, r_y, r_z; + const int dir = i; + r_x = 300; + r_y = 0; + r_z = 45 * dir + 90; + + // convert + const double pi = 3.141592654; + const Vec3f rotation(r_x / 180.0f * pi, r_y / 180.0f * pi, r_z / 180.0f * pi); + RECT r; + int center_x, center_y; + if (!FSunPackLib::LoadVXLImage( + *m_voxelNormalTables, + lightDirection, + rotation, + 0, + vxlColors[i], + vxlLighting[i], + ¢er_x, ¢er_y, + 0, nullptr, nullptr, 0, 0, &r)) { + break; + } + + auto const x = center_x; + auto const y = center_y; + auto const width = r.right - r.left; + auto const height = r.bottom - r.top; + + VXL_Add(vxlColors[i].data(), x, y, width, height); + VXL_Add(vxlLighting[i].data(), x, y, width, height); + VXL_GetAndClear(pTurImages[i], nullptr, nullptr); + turrect[i] = { x, y, width, height }; + } + } + + + VXLName = TurName + ".vxl"; + HVAName = TurName + ".hva"; + + HMIXFILE hVXL = FindFileInMix(VXLName); + + //if (DrawStuff::load_vxl(VXLName) && DrawStuff::load_hva(HVAName)) { + // for (int i = 0; i < 8; ++i) { + // // (13 - i) % 8 for facing fix + // bool result = DrawStuff::get_to_image((13 - i) % 8, pTurImages[i], + // turrect[i][0], turrect[i][1], turrect[i][2], turrect[i][3], pBarlImages[i] ? 0 : turzadjust); + // if (!result) { + // break; + // } + // } + //} + + for (int i = 0; i < 8; ++i) { + auto pTempBuf = new(unsigned char[width * height]); + memcpy_s(pTempBuf, width * height, pBuffer, width * height); + UnionSHP_Add(pTempBuf, width, height); + + int deltaX = rules.GetInteger(ID, "TurretAnimX", 0); + int deltaY = rules.GetInteger(ID, "TurretAnimY", 0); + + auto const& turretRect = turrect[i]; + auto const& barlRect = barlrect[i]; + + if (pTurImages[i]) { + CString pKey; + + pKey.Format("%sX%d", ID, (15 - i) % 8); + int turdeltaX = g_data.GetInteger("BuildingVoxelTurretsRA2", pKey); + pKey.Format("%sY%d", ID, (15 - i) % 8); + int turdeltaY = g_data.GetInteger("BuildingVoxelTurretsRA2", pKey); + + VXL_Add(pTurImages[i], turretRect.X + turdeltaX, turretRect.Y + turdeltaY, turretRect.Width, turretRect.Height); + delete[] pTurImages[i]; + + if (pBarlImages[i]) { + pKey.Format("%sX%d", ID, (15 - i) % 8); + int barldeltaX = g_data.GetInteger("BuildingVoxelBarrelsRA2", pKey); + pKey.Format("%sY%d", ID, (15 - i) % 8); + int barldeltaY = g_data.GetInteger("BuildingVoxelBarrelsRA2", pKey); + + VXL_Add(pBarlImages[i], barlRect[2] + barldeltaX, barlRect[3] + barldeltaY, barlRect[0], barlRect[1]); + delete[] pBarlImages[i]; + } + } + + int nW = 0x100, nH = 0x100; + VXL_GetAndClear(pTurImages[i], &nW, &nH); + + UnionSHP_Add(pTurImages[i], 0x100, 0x100, deltaX, deltaY); + + unsigned char* pImage; + int width1, height1; + + UnionSHP_GetAndClear(pImage, &width1, &height1); + DictName.Format("%s%d", ID, i); + SetImageData(pImage, DictName, width1, height1, m_palettes.LoadPalette(PaletteName)); + } + delete[](pBuffer); + return; + } + + //SHP anim + CString TurName = rules.GetStringOr(ID, "TurretAnim", ID + "tur"); + int nStartFrame = art.GetInteger(TurName, "LoopStart"); + int deltaX = rules.GetInteger(ID, "TurretAnimX", 0); + int deltaY = rules.GetInteger(ID, "TurretAnimY", 0); + auto const turImageName = art.GetStringOr(TurName, "Image", TurName); + auto const frameCount = art.GetInteger(TurName, "LoopEnd", 32); + auto const frameInterval = frameCount / 8; + + for (int seqIdx = 0; seqIdx < 8; ++seqIdx) { + auto pTempBuf = new(unsigned char[width * height]); + memcpy_s(pTempBuf, width * height, pBuffer, width * height); + UnionSHP_Add(pTempBuf, width, height); + LoadSingleFrameShape(turImageName, nStartFrame + seqIdx * frameInterval, deltaX, deltaY); + + unsigned char* pImage; + int width1, height1; + UnionSHP_GetAndClear(pImage, &width1, &height1); + + DictName.Format("%s%d", ID, seqIdx); + SetImageData(pImage, DictName, width1, height1, m_palettes.LoadPalette(PaletteName)); + } + delete(pBuffer); +} + +void CLoading::LoadInfantry(const CString& ID) +{ + CString ArtID = GetArtID(ID); + CString ImageID = GetInfantryFileID(ID); + + CString sequenceName = art.GetString(ImageID, "Sequence"); + CString frames = art.GetStringOr(sequenceName, "Guard", "0,1,1"); + int framesToRead[8]; + int frameStart, frameStep; + sscanf_s(frames, "%d,%d,%d", &frameStart, &framesToRead[0], &frameStep); + for (int i = 0; i < 8; ++i) { + framesToRead[i] = frameStart + i * frameStep; + } + + CString FileName = ImageID + ".shp"; + int nMix = this->FindFileInMix(FileName); + if (FSunPackLib::XCC_DoesFileExist(FileName, nMix)) { + SHPHEADER header; + unsigned char* FramesBuffers; + FSunPackLib::SetCurrentSHP(FileName, nMix); + FSunPackLib::XCC_GetSHPHeader(&header); + for (int i = 0; i < 8; ++i) { + FSunPackLib::LoadSHPImage(framesToRead[i], 1, &FramesBuffers); + CString DictName; + DictName.Format("%s%d", ImageID, i); + CString PaletteName = art.GetStringOr(ArtID, "Palette", "unit"); + GetFullPaletteName(PaletteName, cur_theat); + SetImageData(FramesBuffers, DictName, header.cx, header.cy, m_palettes.LoadPalette(PaletteName)); + } + } +} + +void CLoading::LoadTerrainOrSmudge(const CString& ID) +{ + CString ArtID = GetArtID(ID); + CString ImageID = GetTerrainOrSmudgeFileID(ID); + CString FileName = ImageID + theatToSuffix(this->cur_theat); + int nMix = this->FindFileInMix(FileName); + if (FSunPackLib::XCC_DoesFileExist(FileName, nMix)) { + SHPHEADER header; + unsigned char* FramesBuffers[1]; + FSunPackLib::SetCurrentSHP(FileName, nMix); + FSunPackLib::XCC_GetSHPHeader(&header); + FSunPackLib::LoadSHPImage(0, 1, &FramesBuffers[0]); + CString DictName; + DictName.Format("%s%d", ImageID, 0); + CString PaletteName; + + if (ID.GetLength() >= 6 && *(DWORD*)ID.operator LPCTSTR() == *(DWORD*)("TIBT")) { + PaletteName = "unitsno.pal"; + } else { + PaletteName = art.GetStringOr(ArtID, "Palette", "iso"); + GetFullPaletteName(PaletteName, cur_theat); + } + SetImageData(FramesBuffers[0], DictName, header.cx, header.cy, m_palettes.LoadPalette(PaletteName)); + } +} + +void CLoading::LoadVehicleOrAircraft(const CString& ID) +{ + CString ArtID = GetArtID(ID); + CString ImageID = GetVehicleOrAircraftFileID(ID); + auto const& rules = IniMegaFile::GetRules(); + bool bHasTurret = rules.GetBool(ID, "Turret"); + + + // As SHP + if (!art.GetBool(ArtID, "Voxel")) { + int framesToRead[8]; + int nStandingFrames = art.GetInteger(ArtID, "StandingFrames", 0); + if (nStandingFrames) { + int nStartStandFrame = art.GetInteger(ArtID, "StartStandFrame", 0); + for (int i = 0; i < 8; ++i) { + framesToRead[i] = nStartStandFrame + i * nStandingFrames; + } + } else { + int nStartWalkFrame = art.GetInteger(ArtID, "StartWalkFrame", 0); + int nWalkFrames = art.GetInteger(ArtID, "WalkFrames", 1); + for (int i = 0; i < 8; ++i) { + framesToRead[i] = nStartWalkFrame + i * nWalkFrames; + } + } + + CString FileName = ImageID + ".shp"; + int nMix = this->FindFileInMix(FileName); + if (FSunPackLib::XCC_DoesFileExist(FileName, nMix)) { + SHPHEADER header; + unsigned char* FramesBuffers[2]; + FSunPackLib::SetCurrentSHP(FileName, nMix); + FSunPackLib::XCC_GetSHPHeader(&header); + for (int i = 0; i < 8; ++i) { + FSunPackLib::LoadSHPImage(framesToRead[i], 1, &FramesBuffers[0]); + CString DictName; + DictName.Format("%s%d", ImageID, i); + CString PaletteName = art.GetStringOr(ArtID, "Palette", "unit"); + GetFullPaletteName(PaletteName, cur_theat); + + if (bHasTurret) { + int nStartWalkFrame = art.GetInteger(ArtID, "StartWalkFrame", 0); + int nWalkFrames = art.GetInteger(ArtID, "WalkFrames", 1); + int turretFramesToRead[8]; + + // fix from cmcc + turretFramesToRead[i] = nStartWalkFrame + 8 * nWalkFrames + 4 * ((i + 1) % 8); + + FSunPackLib::LoadSHPImage(turretFramesToRead[i], 1, &FramesBuffers[1]); + UnionSHP_Add(FramesBuffers[0], header.cx, header.cy); + UnionSHP_Add(FramesBuffers[1], header.cx, header.cy); + unsigned char* outBuffer; + int outW, outH; + UnionSHP_GetAndClear(outBuffer, &outW, &outH); + + SetImageData(outBuffer, DictName, outW, outH, m_palettes.LoadPalette(PaletteName)); + } else { + SetImageData(FramesBuffers[0], DictName, header.cx, header.cy, m_palettes.LoadPalette(PaletteName)); + } + } + } + return; + } + + // As VXL + CString FileName = ImageID + ".vxl"; + CString HVAName = ImageID + ".hva"; + + //if (!DrawStuff::is_vpl_loaded()) { + // DrawStuff::load_vpl("voxels.vpl"); + //} + + CString PaletteName = art.GetStringOr(ArtID, "Palette", "unit"); + GetFullPaletteName(PaletteName, cur_theat); + + unsigned char* pImage[8]{ nullptr,nullptr ,nullptr ,nullptr ,nullptr ,nullptr ,nullptr ,nullptr }; + unsigned char* pTurretImage[8]{ nullptr ,nullptr ,nullptr ,nullptr ,nullptr ,nullptr ,nullptr ,nullptr }; + unsigned char* pBarrelImage[8]{ nullptr ,nullptr ,nullptr ,nullptr ,nullptr ,nullptr ,nullptr ,nullptr }; + DrawRect rect[8]; + DrawRect turretrect[8]; + DrawRect barrelrect[8]; + + int nMix = this->FindFileInMix(FileName); + if (!nMix || !FSunPackLib::SetCurrentVXL(FileName, nMix)) { + return; + } + + std::vector vxlColors[8]; + std::vector vxlLighting[8]; + + //if (!DrawStuff::load_vxl(FileName)) { + // return; + //} + //if (!DrawStuff::load_hva(HVAName)) { + // return; + //} + for (int i = 0; i < 8; ++i) { + // (i+6) % 8 to fix the facing + //bool result = DrawStuff::get_to_image((i + 6) % 8, pImage[i], + // rect[i][0], rect[i][1], rect[i][2], rect[i][3]); + //if (!result) { + // return; + //} + + float r_x, r_y, r_z; + const int dir = i; + r_x = 300; + r_y = 0; + r_z = 45 * dir + 90; + + // convert + const double pi = 3.141592654; + const Vec3f rotation(r_x / 180.0f * pi, r_y / 180.0f * pi, r_z / 180.0f * pi); + RECT r; + int center_x, center_y; + if (!FSunPackLib::LoadVXLImage( + *m_voxelNormalTables, + lightDirection, + rotation, + 0, + vxlColors[i], + vxlLighting[i], + ¢er_x, ¢er_y, + 0, nullptr, nullptr, 0, 0, &r)) { + break; + } + + auto const x = center_x; + auto const y = center_y; + auto const width = r.right - r.left; + auto const height = r.bottom - r.top; + + VXL_Add(vxlColors[i].data(), x, y, width, height); + VXL_Add(vxlLighting[i].data(), x, y, width, height); + VXL_GetAndClear(pImage[i], nullptr, nullptr); + rect[i] = { x,y,width,height }; + } + + if (!bHasTurret) { + for (int i = 0; i < 8; ++i) { + CString DictName; + DictName.Format("%s%d", ImageID, i); + + unsigned char* outBuffer; + int outW = 0x100, outH = 0x100; + + VXL_Add(pImage[i], rect[i].X, rect[i].Y, rect[i].Width, rect[i].Height); + delete[] pImage[i]; + VXL_GetAndClear(outBuffer, &outW, &outH); + + SetImageData(outBuffer, DictName, outW, outH, m_palettes.LoadPalette(PaletteName)); + } + return; + } + + int F, L, H; + int s_count = sscanf_s(art.GetStringOr(ArtID, "TurretOffset", "0,0,0"), "%d,%d,%d", &F, &L, &H); + if (s_count == 0) { + F = L = H = 0; + } else if (s_count == 1) { + L = H = 0; + } else if (s_count == 2) { + H = 0; + } + + CString turFileName = ImageID + "tur.vxl"; + CString turHVAName = ImageID + "tur.hva"; + //if (DrawStuff::load_vxl(turFileName)) { + // return; + //} + //if (DrawStuff::load_hva(turHVAName)) { + // return; + //} + for (int i = 0; i < 8; ++i) { + // (i+6) % 8 to fix the facing + //bool result = DrawStuff::get_to_image((i + 6) % 8, pTurretImage[i], + // turretrect[i][0], turretrect[i][1], turretrect[i][2], turretrect[i][3], F, L, H); + + //if (!result) { + // break; + //} + } + + CString barlFileName = ImageID + "barl.vxl"; + CString barlHVAName = ImageID + "barl.hva"; + //if (!DrawStuff::load_vxl(barlFileName)) { + // return; + //} + //if (!DrawStuff::load_hva(barlHVAName)) { + // return; + //} + for (int i = 0; i < 8; ++i) { + // (i+6) % 8 to fix the facing + //bool result = DrawStuff::get_to_image((i + 6) % 8, pBarrelImage[i], + // barrelrect[i][0], barrelrect[i][1], barrelrect[i][2], barrelrect[i][3], F, L, H); + + //if (!result) { + // break; + //} + } + + for (int i = 0; i < 8; ++i) { + CString DictName; + DictName.Format("%s%d", ImageID, i); + + unsigned char* outBuffer; + int outW = 0x100, outH = 0x100; + + if (pImage[i]) { + VXL_Add(pImage[i], rect[i].X, rect[i].Y, rect[i].Width, rect[i].Height); + delete[] pImage[i]; + } + CString pKey; + if (pTurretImage[i]) { + pKey.Format("%sX%d", ID, i); + int turdeltaX = g_data.GetInteger("VehicleVoxelTurretsRA2", pKey); + pKey.Format("%sY%d", ID, i); + int turdeltaY = g_data.GetInteger("VehicleVoxelTurretsRA2", pKey); + VXL_Add(pTurretImage[i], turretrect[i].X + turdeltaX, turretrect[i].Y + turdeltaY, turretrect[i].Width, turretrect[i].Height); + delete[] pTurretImage[i]; + + if (pBarrelImage[i]) { + pKey.Format("%sX%d", ID, i); + int barldeltaX = g_data.GetInteger("VehicleVoxelBarrelsRA2", pKey); + pKey.Format("%sY%d", ID, i); + int barldeltaY = g_data.GetInteger("VehicleVoxelBarrelsRA2", pKey); + + VXL_Add(pBarrelImage[i], barrelrect[i].X + barldeltaX, barrelrect[i].Y + barldeltaY, barrelrect[i].Width, barrelrect[i].Height); + delete[] pBarrelImage[i]; + } + } + + VXL_GetAndClear(outBuffer, &outW, &outH); + + SetImageData(outBuffer, DictName, outW, outH, m_palettes.LoadPalette(PaletteName)); + } + + +} + +void CLoading::SetImageData(unsigned char* pBuffer, const CString& NameInDict, int FullWidth, int FullHeight, Palette* pPal) +{ + auto& data = pics[NameInDict]; + SetImageData(pBuffer, data, FullWidth, FullHeight, pPal); +} + +// TODO: do not do this here, but in the calling position of "LoadUnitGraphic" +void CLoading::SetImageData(unsigned char* pBuffer, PICDATA& pData, const int FullWidth, const int FullHeight, Palette* pPal) +{ + if (pData.pic) { + delete[](pData.pic); + } + if (pData.vborder) { + delete[](pData.vborder); + } + + // Get available area + int counter = 0; + int validFirstX = FullWidth - 1; + int validFirstY = FullHeight - 1; + int validLastX = 0; + int validLastY = 0; + for (int j = 0; j < FullHeight; ++j) { + for (int i = 0; i < FullWidth; ++i) { + unsigned char ch = pBuffer[counter++]; + if (ch != 0) { + if (i < validFirstX) + validFirstX = i; + if (j < validFirstY) + validFirstY = j; + if (i > validLastX) + validLastX = i; + if (j > validLastY) + validLastY = j; + } + } + } + + pData.x = validFirstX; + pData.y = validFirstY; + pData.wWidth = validLastX - validFirstX + 1; + pData.wHeight = validLastY - validFirstY + 1; + + pData.pic = pBuffer; + pData.wMaxHeight = FullHeight; + pData.wMaxWidth = FullWidth; + + pData.vborder = new(VBORDER[FullHeight]); + for (auto k = 0; k < FullHeight; k++) { + int l, r; + GetDrawBorder(pBuffer, FullWidth, k, l, r, 0); + pData.vborder[k].left = l; + pData.vborder[k].right = r; + } + + pData.bType = PICDATA_TYPE_SHP; + pData.bTried = false; + //auto limited_to_theater = artSection.GetBool("TerrainPalette") ? shp->mixfile_theater : TheaterChar::None; + auto limited_to_theater = TheaterChar::None; + pData.bTerrain = limited_to_theater; + pData.pal = pPal ? reinterpret_cast(pPal->GetData()) : iPalUnit; +} + void CLoading::LoadBuildingSubGraphic(const CString& subkey, const CIniFileSection& artSection, BOOL bAlwaysSetChar, char theat, HMIXFILE hShpMix, SHPHEADER& shp_h, BYTE*& shp) { CString subname = artSection.GetString(subkey); @@ -2716,7 +2710,7 @@ HMIXFILE CLoading::FindFileInMix(LPCTSTR lpFilename, TheaterChar* pTheaterChar) void CLoading::InitPalettes() { errstream << "InitPalettes() called\n"; - + m_palettes.Init(); errstream << "\n"; @@ -2838,9 +2832,11 @@ void CLoading::InitTMPs(CProgressCtrl* prog) filename += suffix; HTSPALETTE hPalette = m_palettes.m_hPalIsoTemp; if (tiles == &tiles_s) { - hPalette = m_palettes.m_hPalIsoSnow; } + hPalette = m_palettes.m_hPalIsoSnow; + } if (tiles == &tiles_u) { - hPalette = m_palettes.m_hPalIsoUrb; } + hPalette = m_palettes.m_hPalIsoUrb; + } if (tiles == &tiles_t) { hPalette = m_palettes.m_hPalIsoTemp; } @@ -2855,12 +2851,12 @@ void CLoading::InitTMPs(CProgressCtrl* prog) } // MW add: use other... - if (FindFileInMix(filename) == NULL && tiles == &tiles_un) { - filename = bas_f + ".urb"; + if (FindFileInMix(filename) == NULL && tiles == &tiles_un) { + filename = bas_f + ".urb"; hPalette = m_palettes.m_hPalIsoUrb; } - if (FindFileInMix(filename) == NULL) { - filename = bas_f + ".tem"; + if (FindFileInMix(filename) == NULL) { + filename = bas_f + ".tem"; hPalette = m_palettes.m_hPalIsoTemp; } @@ -3454,10 +3450,10 @@ void CLoading::LoadOverlayGraphic(const CString& lpOvrlName_, int iOvrlNum) p.pic = lpT[i]; if (hPalette == m_palettes.m_hPalIsoTemp - || hPalette == m_palettes.m_hPalIsoUrb - || hPalette == m_palettes.m_hPalIsoSnow - || hPalette == m_palettes.m_hPalIsoDes - || hPalette == m_palettes.m_hPalIsoLun + || hPalette == m_palettes.m_hPalIsoUrb + || hPalette == m_palettes.m_hPalIsoSnow + || hPalette == m_palettes.m_hPalIsoDes + || hPalette == m_palettes.m_hPalIsoLun || hPalette == m_palettes.m_hPalIsoUbn) { p.pal = iPalIso; } @@ -3470,10 +3466,10 @@ void CLoading::LoadOverlayGraphic(const CString& lpOvrlName_, int iOvrlNum) p.pal = iPalTheater; } if (hPalette == m_palettes.m_hPalUnitTemp - || hPalette == m_palettes.m_hPalUnitUrb - || hPalette == m_palettes.m_hPalUnitSnow - || hPalette == m_palettes.m_hPalUnitDes - || hPalette == m_palettes.m_hPalUnitLun + || hPalette == m_palettes.m_hPalUnitUrb + || hPalette == m_palettes.m_hPalUnitSnow + || hPalette == m_palettes.m_hPalUnitDes + || hPalette == m_palettes.m_hPalUnitLun || hPalette == m_palettes.m_hPalUnitUbn) { p.pal = iPalUnit; } @@ -3516,7 +3512,7 @@ void CLoading::LoadOverlayGraphic(const CString& lpOvrlName_, int iOvrlNum) } -} + } #endif void CLoading::OnDestroy() @@ -4349,7 +4345,7 @@ in the specific terrain) Added: MW March 20th 2001 */ -void CLoading::PrepareUnitGraphic(LPCSTR lpUnittype) +void CLoading::PrepareUnitGraphic(const CString& lpUnittype) { CString _rules_image; // the image used CString filename; // filename of the image @@ -4392,222 +4388,6 @@ void CLoading::PrepareUnitGraphic(LPCSTR lpUnittype) // is it a shp graphic? if (!artSection.GetBool("Voxel")) { try { - - /*filename = image + ".shp"; - - - BYTE bTerrain=0; - - - - BOOL isNewTerrain=FALSE; - if(isTrue(artSection.GetValueByName("NewTheater")))//&& isTrue(artSection.GetValueByName("TerrainPalette")))//(filename.GetAt(0)=='G' || filename.GetAt(0)=='N' || filename.GetAt(0)=='C') && filename.GetAt(1)=='A') - { - hPalette=m_hPalUnitTemp; - if(theat=='A') hPalette=m_hPalUnitSnow; - if(theat=='U') hPalette=m_hPalUnitUrb; - if(theat=='L') hPalette=m_hPalUnitLun; - if(theat=='D') hPalette=m_hPalUnitDes; - if(theat=='N') hPalette=m_hPalUnitUbn; - filename.SetAt(1, theat); - isNewTerrain=TRUE; - } - - - HMIXFILE hShpMix=FindFileInMix(filename, &bTerrain); - - BYTE bIgnoreTerrain=TRUE; - - if(hShpMix==NULL && isNewTerrain) - { - filename.SetAt(1, 'G'); - hShpMix=FindFileInMix(filename, &bTerrain); - if(hShpMix) theat='G'; - - } - - - if(hShpMix==NULL && isNewTerrain) - { - filename.SetAt(1, 'N'); - hShpMix=FindFileInMix(filename, &bTerrain); - if(hShpMix) theat='N'; - } - - if(hShpMix==NULL && isNewTerrain) - { - filename.SetAt(1, 'D'); - hShpMix=FindFileInMix(filename, &bTerrain); - if(hShpMix) theat='D'; - } - - if(hShpMix==NULL && isNewTerrain) - { - filename.SetAt(1, 'L'); - hShpMix=FindFileInMix(filename, &bTerrain); - if(hShpMix) theat='L'; - } - - if(hShpMix==NULL && isNewTerrain) - { - filename.SetAt(1, 'A'); - hShpMix=FindFileInMix(filename, &bTerrain); - if(hShpMix) theat='A'; - } - - if(hShpMix==NULL && isNewTerrain) - { - filename.SetAt(1, 'T'); - hShpMix=FindFileInMix(filename, &bTerrain); - if(hShpMix){ - theat='T'; - hPalette=m_hIsoTemp; - } - } - - - if(isTrue(artSection.GetValueByName("TerrainPalette"))) - { - bIgnoreTerrain=FALSE; - - if(cur_theat=='T') - hPalette=m_hPalIsoTemp; - else if(cur_theat=='A') - hPalette=m_hPalIsoSnow; - else if (cur_theat=='U') - hPalette=m_hPalIsoUrb; - else if(cur_theat=='L') - hPalette=m_hPalIsoLun; - else if(cur_theat=='D') - hPalette=m_hPalIsoDes; - else if(cur_theat=='N') - hPalette=m_hPalIsoUbn; - - - - } - - - - if(hShpMix==0) - { - filename=image; - filename+=".shp"; - hShpMix=FindFileInMix(filename, &bTerrain); - - - - if(hShpMix==NULL) - { - filename=image; - if(theat=='T') filename+=".tem"; - if(theat=='A') filename+=".sno"; - if(theat=='U') filename+=".urb"; - if(theat=='L') filename+=".lun"; - if(theat=='D') filename+=".des"; - if(theat=='N') filename+=".ubn"; - filename.MakeLower(); - hShpMix=FindFileInMix(filename, &bTerrain); - - if(hShpMix==NULL) - { - filename=image; - filename+=".tem"; - hShpMix=FindFileInMix(filename, &bTerrain); - if(hShpMix) - { - hPalette=m_hPalIsoTemp; - } - } - - if(hShpMix!=NULL) - { - - - - } - else - { - filename=image+".shp"; - - filename.SetAt(1, 'A'); - - hShpMix=FindFileInMix(filename); - - if(hShpMix!=NULL) - { - bAlwaysSetChar=TRUE; - } - else - { - filename.SetAt(1, 'A'); - hShpMix=FindFileInMix(filename); - - if(hShpMix!=NULL) - { - theat='A'; - bAlwaysSetChar=TRUE; - } - else - { - filename.SetAt(1, 'U'); - hShpMix=FindFileInMix(filename); - if(hShpMix) theat='U'; - else - { - filename.SetAt(1, 'L'); - hShpMix=FindFileInMix(filename); - if(hShpMix) theat='L'; - else - { - filename.SetAt(1, 'D'); - hShpMix=FindFileInMix(filename); - if(hShpMix) theat='D'; - else - { - filename.SetAt(1, 'N'); - hShpMix=FindFileInMix(filename); - if(hShpMix) theat='N'; - else - { - filename.SetAt(1, 'T'); - hShpMix=FindFileInMix(filename); - if(hShpMix) theat='T'; - } - } - } - } - } - } - } - } - else - { - theat='T'; - } - - } - else - { - - // now we need to find out the palette - - if(isTrue(artSection.GetValueByName("TerrainPalette"))) // it´s a file in isotemp.mix/isosno.mix - { - - } - else // it´s a file in temperat.mix/snow.mix - { - if(cur_theat=='T') hPalette=m_hPalUnitTemp; - if(cur_theat=='A') hPalette=m_hPalUnitSnow; - if(cur_theat=='U') hPalette=m_hPalUnitUrb; - if(cur_theat=='L') hPalette=m_hPalUnitLun; - if(cur_theat=='D') hPalette=m_hPalUnitDes; - if(cur_theat=='N') hPalette=m_hPalUnitUbn; - } - - }*/ - auto shp = FindUnitShp(image, cur_theat, artSection); if (!shp) { return; diff --git a/MissionEditor/Loading.h b/MissionEditor/Loading.h index 929abb3..c2137c0 100644 --- a/MissionEditor/Loading.h +++ b/MissionEditor/Loading.h @@ -91,7 +91,7 @@ class CLoading : public CDialog { // Construction public: - void PrepareUnitGraphic(LPCSTR lpUnittype); + void PrepareUnitGraphic(const CString& lpUnittype); void LoadStrings(); void FreeAll(); void FreeTileSet(); @@ -109,6 +109,18 @@ public: CLoading(CWnd* pParent = NULL); // Standardconstructor void InitPics(CProgressCtrl* prog = NULL); void Load(); + bool LoadSingleFrameShape(const CString& name, int nFrame = 0, int deltaX = 0, int deltaY = 0); + void LoadBuilding(const CString& ID); + void LoadInfantry(const CString& ID); + void LoadTerrainOrSmudge(const CString& ID); + void LoadVehicleOrAircraft(const CString& ID); + + void SetImageData(unsigned char* pBuffer, const CString& NameInDict, int FullWidth, int FullHeight, Palette* pPal); + void SetImageData(unsigned char* pBuffer, PICDATA& pData, const int FullWidth, const int FullHeight, Palette* pPal); + void UnionSHP_Add(unsigned char* pBuffer, int Width, int Height, int DeltaX = 0, int DeltaY = 0, bool UseTemp = false); + void UnionSHP_GetAndClear(unsigned char*& pOutBuffer, int* OutWidth, int* OutHeight, bool UseTemp = false); + void VXL_Add(const unsigned char* pCache, int X, int Y, int Width, int Height); + void VXL_GetAndClear(unsigned char*& pBuffer, int* OutWidth, int* OutHeight); BOOL LoadUnitGraphic(const CString& lpUnittype); void LoadBuildingSubGraphic(const CString& subkey, const CIniFileSection& artSection, BOOL bAlwaysSetChar, char theat, HMIXFILE hShpMix, SHPHEADER& shp_h, BYTE*& shp); void LoadOverlayGraphic(const CString& lpOvrlName, int iOvrlNum); @@ -125,6 +137,24 @@ public: return m_hExpand; } + enum class ObjectType + { + Unknown = -1, + Infantry = 0, + Vehicle = 1, + Aircraft = 2, + Building = 3, + Terrain = 4, + Smudge = 5 + }; + + ObjectType GetItemType(const CString& ID); + CString GetArtID(const CString& ID); + CString GetVehicleOrAircraftFileID(const CString& ID); + CString GetTerrainOrSmudgeFileID(const CString& ID); + CString GetBuildingFileID(const CString& ID); + CString GetInfantryFileID(const CString& ID); + // Dialog data //{{AFX_DATA(CLoading) enum { IDD = IDD_LOADING }; @@ -197,7 +227,18 @@ private: std::unique_ptr m_voxelNormalTables; + struct SHPUnionData + { + unsigned char* pBuffer; + int Width; + int Height; + int DeltaX; + int DeltaY; + }; + std::map ObjectTypes; + std::vector UnionSHP_Data[2]; + unsigned char VXL_Data[0x10000]; }; //{{AFX_INSERT_LOCATION}} diff --git a/MissionEditor/MapData.cpp b/MissionEditor/MapData.cpp index b3bfb32..dfd5fe8 100644 --- a/MissionEditor/MapData.cpp +++ b/MissionEditor/MapData.cpp @@ -3453,7 +3453,7 @@ void CMapData::UpdateBuildingInfo(const CString* lpUnitType) CIniFile& ini = GetIniFile(); if (!lpUnitType) { - memset(buildinginfo, 0, 0x0F00 * sizeof(BUILDING_INFO)); + memset(buildinginfo, 0, buildingInfoCapacity * sizeof(BUILDING_INFO)); for (auto const& [seq, id] : rules.GetSection("BuildingTypes")) { auto const& type = id; @@ -3464,7 +3464,7 @@ void CMapData::UpdateBuildingInfo(const CString* lpUnitType) int n = Map->GetUnitTypeID(type); - if (n >= 0 && n < 0x0F00) { + if (n >= 0 && n < buildingInfoCapacity) { buildinginfo[n].w = foundation.Width; buildinginfo[n].h = foundation.Height; @@ -3525,7 +3525,7 @@ void CMapData::UpdateBuildingInfo(const CString* lpUnitType) int n = Map->GetUnitTypeID(type); - if (n >= 0 && n < 0x0F00) { + if (n >= 0 && n < buildingInfoCapacity) { buildinginfo[n].w = foundation.Width; buildinginfo[n].h = foundation.Height; buildinginfo[n].bSnow = TRUE; @@ -3560,7 +3560,7 @@ void CMapData::UpdateBuildingInfo(const CString* lpUnitType) int n = Map->GetUnitTypeID(type); - if (n >= 0 && n < 0x0F00) { + if (n >= 0 && n < buildingInfoCapacity) { buildinginfo[n].w = foundation.Width; buildinginfo[n].h = foundation.Height; CString lpPicFile = GetUnitPictureFilename(type, 0); diff --git a/MissionEditor/MissionEditor.vcxproj b/MissionEditor/MissionEditor.vcxproj index 81bdb17..ab01a2f 100644 --- a/MissionEditor/MissionEditor.vcxproj +++ b/MissionEditor/MissionEditor.vcxproj @@ -522,6 +522,7 @@ + @@ -610,6 +611,7 @@ + @@ -650,6 +652,7 @@ + diff --git a/MissionEditor/MissionEditor.vcxproj.filters b/MissionEditor/MissionEditor.vcxproj.filters index 23f6af9..58193e5 100644 --- a/MissionEditor/MissionEditor.vcxproj.filters +++ b/MissionEditor/MissionEditor.vcxproj.filters @@ -285,6 +285,9 @@ Source Files + + Source Files + @@ -577,6 +580,12 @@ Header Files + + Header Files + + + Header Files + diff --git a/MissionEditor/Palettes.cpp b/MissionEditor/Palettes.cpp index 3296083..fbe1be6 100644 --- a/MissionEditor/Palettes.cpp +++ b/MissionEditor/Palettes.cpp @@ -1,3 +1,4 @@ +#include "stdafx.h" #include "Palettes.h" #include "variables.h" #include "functions.h" diff --git a/MissionEditor/Palettes.h b/MissionEditor/Palettes.h index 282aa1c..ac44dec 100644 --- a/MissionEditor/Palettes.h +++ b/MissionEditor/Palettes.h @@ -4,6 +4,8 @@ #include #include "MissionEditorPackLib.h" +class CLoading; + struct BGRStruct { unsigned char B, G, R, Zero; @@ -39,6 +41,8 @@ public: ret.blue = tmp.B; return ret; } + const BGRStruct* GetData() const { return Data; } + private: BGRStruct Data[256]; }; diff --git a/MissionEditor/Structs.h b/MissionEditor/Structs.h index f6a5a27..bdf15c0 100644 --- a/MissionEditor/Structs.h +++ b/MissionEditor/Structs.h @@ -118,7 +118,7 @@ struct PICDATA { #else void* pic = nullptr; // BYTE* to image, exception: if bType==PICDATA_TYPE_BMP then this is a LPDIRECTDRAWSURFACE! VBORDER* vborder = nullptr; - int* pal = nullptr; + const int* pal = nullptr; std::shared_ptr> lighting; std::shared_ptr> rawPic; std::shared_ptr> _vBorder; diff --git a/MissionEditor/ViewObjects.h b/MissionEditor/ViewObjects.h index 80c5d75..9b29d4e 100644 --- a/MissionEditor/ViewObjects.h +++ b/MissionEditor/ViewObjects.h @@ -37,6 +37,8 @@ using IgnoreSet = std::unordered_set; static const IgnoreSet CollectIgnoreSet(); +extern CIniFile rules; + class TreeRoot { friend class TreeViewBuilder; friend class CViewObjects; diff --git a/MissionEditor/inlines.h b/MissionEditor/inlines.h index 8a3ba42..9fbeee6 100644 --- a/MissionEditor/inlines.h +++ b/MissionEditor/inlines.h @@ -47,8 +47,10 @@ inline BOOL isFalse(CString expr) return FALSE; } + + // retrieve the picture filename of a unit (as it is saved in the pics map). The returned file may not exist in the pics map (you need to do a check!). -inline CString GetUnitPictureFilename(LPCTSTR lpUnitName, DWORD dwPicIndex) +inline CString GetUnitPictureFilename(const CString& lpUnitName, DWORD dwPicIndex) { CIniFile& ini = Map->GetIniFile(); @@ -71,17 +73,16 @@ inline CString GetUnitPictureFilename(LPCTSTR lpUnitName, DWORD dwPicIndex) char n[50]; _itoa_s(dwPicIndex, n, 10); - - - if (pics.find((artname + n)) != pics.end()) { - filename = artname; // yes, found + // store differently for each type even they shares same image, + // because they can have different components, e.g. turret image + if (pics.find((lpUnitName + n)) != pics.end()) { + filename = lpUnitName; // yes, found filename += n; - } else if (pics.find(artname + ".bmp") != pics.end()) // since June, 15th (Matze): Only use BMP if no SHP/VXL exists - { + } else if (pics.find(artname + ".bmp") != pics.end()) { // since June, 15th (Matze): Only use BMP if no SHP/VXL exists filename = (CString)artname + ".bmp"; - } else + } else { filename = ""; - + } return filename; } diff --git a/MissionEditor/variables.cpp b/MissionEditor/variables.cpp index d3685f5..7221d20 100644 --- a/MissionEditor/variables.cpp +++ b/MissionEditor/variables.cpp @@ -176,7 +176,8 @@ bool bAllowAccessBehindCliffs = false; // infos for buildings and trees (should be extended to infantry, units, and aircraft) // they are initialized in CIsoView, should be changed to CMapData -BUILDING_INFO buildinginfo[0x0F00]; + +BUILDING_INFO buildinginfo[buildingInfoCapacity]; TREE_INFO treeinfo[0x0F00]; #ifdef SMUDGE_SUPP SMUDGE_INFO smudgeinfo[0x0F00]; diff --git a/MissionEditor/variables.h b/MissionEditor/variables.h index 4bc6295..e5a32e0 100644 --- a/MissionEditor/variables.h +++ b/MissionEditor/variables.h @@ -104,7 +104,10 @@ extern vector rndterrainsrc; // infos for buildings and trees (should be extended to infantry, units, and aircraft) // they are initialized in CIsoView, should be changed to CMapData -extern BUILDING_INFO buildinginfo[0x0F00]; + +size_t constexpr buildingInfoCapacity = 0x0F000; + +extern BUILDING_INFO buildinginfo[buildingInfoCapacity]; extern TREE_INFO treeinfo[0x0F00]; #ifdef SMUDGE_SUPP extern SMUDGE_INFO smudgeinfo[0x0F00]; diff --git a/MissionEditorPackLib/MissionEditorPackLib.cpp b/MissionEditorPackLib/MissionEditorPackLib.cpp index dfa18a0..f4c0705 100644 --- a/MissionEditorPackLib/MissionEditorPackLib.cpp +++ b/MissionEditorPackLib/MissionEditorPackLib.cpp @@ -413,7 +413,7 @@ namespace FSunPackLib BOOL XCC_DoesFileExist(LPCSTR szFile, HMIXFILE hOwner) { - if (hOwner == 0) + if (hOwner == NULL) return FALSE; if (hOwner > dwMixFileCount) return FALSE; @@ -1819,8 +1819,22 @@ namespace FSunPackLib return TRUE; } - BOOL LoadVXLImage(const VoxelNormalTables& normalTables, Vec3f lightDirection, const Vec3f rotation, const Vec3f modelOffset, std::vector& image, std::vector& lighting, int* lpXCenter, int* lpYCenter, int ZAdjust, int* lpXCenterZMax, int* lpYCenterZMax, int i3dCenterX, int i3dCenterY, RECT* vxlrect) - { + BOOL LoadVXLImage( + const VoxelNormalTables& normalTables, + Vec3f lightDirection, + const Vec3f rotation, + const Vec3f modelOffset, + OUT std::vector& image, + OUT std::vector& lighting, + OUT OPTIONAL int* lpXCenter, + OUT OPTIONAL int* lpYCenter, + int ZAdjust, + OUT OPTIONAL int* lpXCenterZMax, + OUT OPTIONAL int* lpYCenterZMax, + int i3dCenterX, + int i3dCenterY, + OUT OPTIONAL RECT* vxlrect + ) { last_succeeded_operation = 1; int i; diff --git a/MissionEditorPackLib/MissionEditorPackLib.h b/MissionEditorPackLib/MissionEditorPackLib.h index e724930..842bde3 100644 --- a/MissionEditorPackLib/MissionEditorPackLib.h +++ b/MissionEditorPackLib/MissionEditorPackLib.h @@ -28,6 +28,18 @@ #include #include "Vec3.h" +#ifndef IN +#define IN +#endif + +#ifndef OUT +#define OUT +#endif + +#ifndef OPTIONAL +#define OPTIONAL +#endif + class VoxelNormalTables; typedef DWORD HMIXFILE; @@ -217,7 +229,20 @@ namespace FSunPackLib BOOL LoadVXLImageInSurface(const VoxelNormalTables& normalTables, Vec3f lightDirection, IDirectDraw4* pdd, int iStart, int iCount, Vec3f rotation, Vec3f modelOffset, LPDIRECTDRAWSURFACE4* pdds, HTSPALETTE hPalette, int* lpXCenter = NULL, int* lpYCenter = NULL, int ZAdjust = 0, int* lpXCenterZMax = NULL, int* lpYCenterZMax = NULL, int i3dCenterX = -1, int i3dCenterY = -1); // modelOffset is applied before VXL/HVA translates and scales and before model-to-world rotation - BOOL LoadVXLImage(const VoxelNormalTables& normalTables, Vec3f lightDirection, Vec3f rotation, Vec3f modelOffset, std::vector& image, std::vector& lighting, int* lpXCenter = NULL, int* lpYCenter = NULL, int ZAdjust = 0, int* lpXCenterZMax = NULL, int* lpYCenterZMax = NULL, int i3dCenterX = -1, int i3dCenterY = -1, RECT* vxlrect = NULL); + BOOL LoadVXLImage(const VoxelNormalTables& normalTables, + Vec3f lightDirection, + Vec3f rotation, + Vec3f modelOffset, + OUT std::vector& image, + OUT std::vector& lighting, + OUT OPTIONAL int* lpXCenter = NULL, + OUT OPTIONAL int* lpYCenter = NULL, + int ZAdjust = 0, + OUT OPTIONAL int* lpXCenterZMax = NULL, + OUT OPTIONAL int* lpYCenterZMax = NULL, + int i3dCenterX = -1, + int i3dCenterY = -1, + OUT OPTIONAL RECT* vxlrect = NULL); BOOL WriteMixFile(LPCTSTR lpMixFile, LPCSTR* lpFiles, DWORD dwFileCount, Game game); From f1b969219a5b8742db86b68a7a216a4aac7d5ae9 Mon Sep 17 00:00:00 2001 From: Zero Fanker Date: Sun, 19 May 2024 11:19:13 -0400 Subject: [PATCH 05/13] Format adjustment . --- MissionEditor/INIMeta.cpp | 2 +- MissionEditor/IsoView.cpp | 19 ++++++++++++++----- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/MissionEditor/INIMeta.cpp b/MissionEditor/INIMeta.cpp index cdfdf0e..fcce812 100644 --- a/MissionEditor/INIMeta.cpp +++ b/MissionEditor/INIMeta.cpp @@ -13,7 +13,7 @@ const CIniFile* IniFileGroup::Nth(int idx) const return m_group.at(idx); } -const CString& IniFileGroup::GetString(const CString & section, const CString & key) const +const CString& IniFileGroup::GetString(const CString& section, const CString & key) const { for (auto it = m_group.rbegin(); it != m_group.rend(); ++it) { auto const& got = (*it)->GetString(section, key); diff --git a/MissionEditor/IsoView.cpp b/MissionEditor/IsoView.cpp index eed8806..9a08cd1 100644 --- a/MissionEditor/IsoView.cpp +++ b/MissionEditor/IsoView.cpp @@ -547,24 +547,33 @@ inline void CalculateHouseColorPalette(int house_pal[houseColorRelMax + 1], cons /* There is no need for newpal */ -__forceinline void BlitPic(void* dst, int x, int y, int dleft, int dtop, int dpitch, int dright, int dbottom, PICDATA& pd, int* color = NULL, const int* newPal = NULL)//BYTE* src, int swidth, int sheight) +__forceinline void BlitPic(void* dst, int x, int y, int dleft, int dtop, int dpitch, int dright, int dbottom, + PICDATA& pd, int* color = NULL, const int* newPal = NULL)//BYTE* src, int swidth, int sheight) { ASSERT(pd.bType != PICDATA_TYPE_BMP); - if (newPal == NULL) newPal = pd.pal; + if (newPal == NULL) { + newPal = pd.pal; + } BYTE* src = (BYTE*)pd.pic; int swidth = pd.wMaxWidth; int sheight = pd.wMaxHeight; - if (src == NULL || dst == NULL) return; + if (src == NULL || dst == NULL) { + return; + } //x += 1; //y += 1; //y -= f_y; - if (x + swidth < dleft || y + sheight < dtop) return; - if (x >= dright || y >= dbottom) return; + if (x + swidth < dleft || y + sheight < dtop) { + return; + } + if (x >= dright || y >= dbottom) { + return; + } RECT blrect; From 48c90655370026d1df5eaa586888a3e67eca893b Mon Sep 17 00:00:00 2001 From: Zero Fanker Date: Sun, 19 May 2024 11:37:40 -0400 Subject: [PATCH 06/13] fixed bug that INI group might already been destroyed while iterating the group --- MissionEditor/INIMeta.h | 11 ++++++++--- UnitTest/CIni_Meta_Test.cpp | 8 +++++++- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/MissionEditor/INIMeta.h b/MissionEditor/INIMeta.h index 57528b5..6339d69 100644 --- a/MissionEditor/INIMeta.h +++ b/MissionEditor/INIMeta.h @@ -103,12 +103,17 @@ public: const CString& m_section; }; - IniSectionGroup(const IniFileGroup& source, const CString& secName) : - m_source(source), + IniSectionGroup(IniFileGroup&& source, const CString& secName) : + m_source(std::move(source)), m_section(secName) { } + IniSectionGroup(const IniFileGroup& source, const CString& secName) : + IniSectionGroup(IniFileGroup(source), secName) + { + } + Iterator begin() const { auto groupBeg = m_source.begin(); auto [secItBeg, secItEnd] = acquireNextKvGroup(groupBeg); @@ -146,6 +151,6 @@ private: return acquireNextKvGroup(m_section, beg, m_source.end()); } - const IniFileGroup& m_source; + const IniFileGroup m_source; CString m_section; }; diff --git a/UnitTest/CIni_Meta_Test.cpp b/UnitTest/CIni_Meta_Test.cpp index 41a6142..c20d274 100644 --- a/UnitTest/CIni_Meta_Test.cpp +++ b/UnitTest/CIni_Meta_Test.cpp @@ -29,12 +29,18 @@ TEST(IniFileGroup, ValidIniWithValidContentTest) { auto const bldTypes = group.GetSection("BuildingTypes"); auto idx = 0; - //for (auto const& [key, val] : bldTypes) { + for (auto it = bldTypes.begin(); it != bldTypes.end(); ++it) { auto const& [key, val] = *it; EXPECT_EQ(val, referenceList[idx++]); } + // This is to test RHS issue + idx = 0; + for (auto const& [key, val] : group.GetSection("BuildingTypes")) { + EXPECT_EQ(val, referenceList[idx++]); + } + EXPECT_EQ(group.GetString("GACNST", "Strength"), "2000"); } #endif From 7962824be73b35d7696f35ec1daa3d1af340ff0c Mon Sep 17 00:00:00 2001 From: Zero Fanker Date: Sun, 19 May 2024 11:38:09 -0400 Subject: [PATCH 07/13] Bug fix of image background color issue . --- MissionEditor/Loading.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/MissionEditor/Loading.cpp b/MissionEditor/Loading.cpp index 050800b..85b212a 100644 --- a/MissionEditor/Loading.cpp +++ b/MissionEditor/Loading.cpp @@ -579,6 +579,7 @@ void CLoading::UnionSHP_GetAndClear(unsigned char*& pOutBuffer, int* OutWidth, i // just make it work like unsigned char[W][H]; pOutBuffer = new(unsigned char[W * H]); + ZeroMemory(pOutBuffer, W * H); *OutWidth = W; *OutHeight = H; From c94515c6867f75ee20e917b17549d32eb95465a1 Mon Sep 17 00:00:00 2001 From: Zero Fanker Date: Sun, 19 May 2024 11:39:40 -0400 Subject: [PATCH 08/13] renamed inner variable of SHP image blend queue --- MissionEditor/Loading.cpp | 6 +++--- MissionEditor/Loading.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/MissionEditor/Loading.cpp b/MissionEditor/Loading.cpp index 85b212a..533e48a 100644 --- a/MissionEditor/Loading.cpp +++ b/MissionEditor/Loading.cpp @@ -558,7 +558,7 @@ void CLoading::UnionSHP_GetAndClear(unsigned char*& pOutBuffer, int* OutWidth, i // never calls it when UnionSHP_Data is empty if (UnionSHP_Data[UseTemp].size() == 1) { - pOutBuffer = UnionSHP_Data[UseTemp][0].pBuffer; + pOutBuffer = UnionSHP_Data[UseTemp][0].Buffer; *OutWidth = UnionSHP_Data[UseTemp][0].Width; *OutHeight = UnionSHP_Data[UseTemp][0].Height; UnionSHP_Data[UseTemp].clear(); @@ -593,10 +593,10 @@ void CLoading::UnionSHP_GetAndClear(unsigned char*& pOutBuffer, int* OutWidth, i for (int j = 0; j < data.Height; ++j) for (int i = 0; i < data.Width; ++i) - if (auto nPalIdx = data.pBuffer[j * data.Width + i]) + if (auto nPalIdx = data.Buffer[j * data.Width + i]) pOutBuffer[(nStartY + j) * W + nStartX + i] = nPalIdx; - delete[](data.pBuffer); + delete[](data.Buffer); } UnionSHP_Data[UseTemp].clear(); diff --git a/MissionEditor/Loading.h b/MissionEditor/Loading.h index c2137c0..96f650b 100644 --- a/MissionEditor/Loading.h +++ b/MissionEditor/Loading.h @@ -229,7 +229,7 @@ private: struct SHPUnionData { - unsigned char* pBuffer; + unsigned char* Buffer;// This buffer allocated from outside int Width; int Height; int DeltaX; From 4171effebf0b55fed49335275329cc702b3b9a6f Mon Sep 17 00:00:00 2001 From: Zero Fanker Date: Sun, 19 May 2024 11:44:56 -0400 Subject: [PATCH 09/13] fixed SHP image blending overlapping issue . --- MissionEditor/Loading.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MissionEditor/Loading.cpp b/MissionEditor/Loading.cpp index 533e48a..95da362 100644 --- a/MissionEditor/Loading.cpp +++ b/MissionEditor/Loading.cpp @@ -1507,7 +1507,7 @@ void CLoading::LoadBuilding(const CString& ID) } auto loadAnimFrame = [this, &ArtID, &ID](const CString& key, const CString& controlKey) { - auto const imageID = art.GetStringOr(ArtID, key, ArtID); + auto const imageID = art.GetString(ArtID, key); if (!imageID.IsEmpty()) { if (!g_data.GetBool(controlKey, ID)) { int nStartFrame = art.GetInteger(imageID, "LoopStart"); From 6627e9563c33ae8a3754b0734b8808171ed41e93 Mon Sep 17 00:00:00 2001 From: Zero Fanker Date: Sun, 19 May 2024 11:45:25 -0400 Subject: [PATCH 10/13] Silence some compile warning . --- MissionEditor/Loading.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/MissionEditor/Loading.cpp b/MissionEditor/Loading.cpp index 95da362..eb8a26f 100644 --- a/MissionEditor/Loading.cpp +++ b/MissionEditor/Loading.cpp @@ -1554,7 +1554,7 @@ void CLoading::LoadBuilding(const CString& ID) // No turret if (!rules.GetBool(ID, "Turret")) { - DictName.Format("%s%d", ID, 0); + DictName.Format("%s%d", ID.operator LPCSTR(), 0); SetImageData(pBuffer, DictName, width, height, m_palettes.LoadPalette(PaletteName)); return; } @@ -1911,7 +1911,7 @@ void CLoading::LoadVehicleOrAircraft(const CString& ID) if (!bHasTurret) { for (int i = 0; i < 8; ++i) { CString DictName; - DictName.Format("%s%d", ImageID, i); + DictName.Format("%s%d", ImageID.operator LPCSTR(), i); unsigned char* outBuffer; int outW = 0x100, outH = 0x100; @@ -1973,7 +1973,7 @@ void CLoading::LoadVehicleOrAircraft(const CString& ID) for (int i = 0; i < 8; ++i) { CString DictName; - DictName.Format("%s%d", ImageID, i); + DictName.Format("%s%d", ImageID.operator LPCSTR(), i); unsigned char* outBuffer; int outW = 0x100, outH = 0x100; @@ -1984,17 +1984,17 @@ void CLoading::LoadVehicleOrAircraft(const CString& ID) } CString pKey; if (pTurretImage[i]) { - pKey.Format("%sX%d", ID, i); + pKey.Format("%sX%d", ID.operator LPCSTR(), i); int turdeltaX = g_data.GetInteger("VehicleVoxelTurretsRA2", pKey); - pKey.Format("%sY%d", ID, i); + pKey.Format("%sY%d", ID.operator LPCSTR(), i); int turdeltaY = g_data.GetInteger("VehicleVoxelTurretsRA2", pKey); VXL_Add(pTurretImage[i], turretrect[i].X + turdeltaX, turretrect[i].Y + turdeltaY, turretrect[i].Width, turretrect[i].Height); delete[] pTurretImage[i]; if (pBarrelImage[i]) { - pKey.Format("%sX%d", ID, i); + pKey.Format("%sX%d", ID.operator LPCSTR(), i); int barldeltaX = g_data.GetInteger("VehicleVoxelBarrelsRA2", pKey); - pKey.Format("%sY%d", ID, i); + pKey.Format("%sY%d", ID.operator LPCSTR(), i); int barldeltaY = g_data.GetInteger("VehicleVoxelBarrelsRA2", pKey); VXL_Add(pBarrelImage[i], barrelrect[i].X + barldeltaX, barrelrect[i].Y + barldeltaY, barrelrect[i].Width, barrelrect[i].Height); From 47a4dde7aab1cc21f11caa2693856c67484aba6a Mon Sep 17 00:00:00 2001 From: Zero Fanker Date: Mon, 20 May 2024 23:27:53 -0400 Subject: [PATCH 11/13] investigating voxel issue . --- MissionEditor/Loading.cpp | 68 +++++++++++++++++++++++++++++++++------ MissionEditor/Loading.h | 4 ++- 2 files changed, 61 insertions(+), 11 deletions(-) diff --git a/MissionEditor/Loading.cpp b/MissionEditor/Loading.cpp index eb8a26f..56b2f60 100644 --- a/MissionEditor/Loading.cpp +++ b/MissionEditor/Loading.cpp @@ -102,6 +102,8 @@ CLoading::CLoading(CWnd* pParent /*=NULL*/) : m_hECache[i] = NULL; } + VXL_Reset(); + errstream << "CLoading::CLoading() called" << endl; errstream.flush(); } @@ -638,9 +640,14 @@ void CLoading::VXL_GetAndClear(unsigned char*& pBuffer, int* OutWidth, int* OutH } } */ - pBuffer = new unsigned char[0x10000]; - memcpy_s(pBuffer, 0x10000, VXL_Data, 0x10000); - memset(VXL_Data, 0, 0x10000); + pBuffer = new unsigned char[VoxelBlendCacheLength]; + memcpy_s(pBuffer, VoxelBlendCacheLength, VXL_Data, VoxelBlendCacheLength); + VXL_Reset(); +} + +void CLoading::VXL_Reset() +{ + memset(VXL_Data, 0, VoxelBlendCacheLength); } bool IsImageLoaded(const CString& ID) { @@ -1548,10 +1555,6 @@ void CLoading::LoadBuilding(const CString& ID) int width, height; UnionSHP_GetAndClear(pBuffer, &width, &height); - if (ID == "NAWEAP2") { - printf(""); - } - // No turret if (!rules.GetBool(ID, "Turret")) { DictName.Format("%s%d", ID.operator LPCSTR(), 0); @@ -1579,6 +1582,7 @@ void CLoading::LoadBuilding(const CString& ID) CString VXLName = BarlName + ".vxl"; CString HVAName = BarlName + ".hva"; +#if 0 HMIXFILE hBarl = FindFileInMix(BarlName); if (hBarl && FSunPackLib::SetCurrentVXL(VXLName, hBarl)) { auto vnc = FSunPackLib::VoxelNormalClass::Unknown; @@ -1618,15 +1622,60 @@ void CLoading::LoadBuilding(const CString& ID) VXL_Add(vxlColors[i].data(), x, y, width, height); VXL_Add(vxlLighting[i].data(), x, y, width, height); VXL_GetAndClear(pTurImages[i], nullptr, nullptr); - turrect[i] = { x, y, width, height }; + barlrect[i] = { x, y, width, height }; } } +#endif + if (ID == "NAFLAK") { + printf(""); + } VXLName = TurName + ".vxl"; HVAName = TurName + ".hva"; HMIXFILE hVXL = FindFileInMix(VXLName); + if (hVXL && FSunPackLib::SetCurrentVXL(VXLName, hVXL)) { + auto vnc = FSunPackLib::VoxelNormalClass::Unknown; + std::vector vxlColors[8]; + std::vector vxlLighting[8]; + // we assume the voxel normal class is always the same for the combined voxels + FSunPackLib::GetVXLSectionInfo(0, vnc); + for (int i = 0; i < 8; ++i) { + float r_x, r_y, r_z; + const int dir = i; + r_x = 300; + r_y = 0; + r_z = 45 * dir + 90; + + // convert + const double pi = 3.141592654; + const Vec3f rotation(r_x / 180.0f * pi, r_y / 180.0f * pi, r_z / 180.0f * pi); + RECT r; + int center_x, center_y; + if (!FSunPackLib::LoadVXLImage( + *m_voxelNormalTables, + lightDirection, + rotation, + Vec3f{}, + vxlColors[i], + vxlLighting[i], + ¢er_x, ¢er_y, + 0, nullptr, nullptr, 0, 0, &r)) { + break; + } + + auto const x = center_x; + auto const y = center_y; + auto const width = r.right - r.left; + auto const height = r.bottom - r.top; + + VXL_Add(vxlColors[i].data(), x, y, width, height); + VXL_Add(vxlLighting[i].data(), x, y, width, height); + VXL_GetAndClear(pTurImages[i], nullptr, nullptr); + turrect[i] = { x, y, width, height }; + } + } //if (DrawStuff::load_vxl(VXLName) && DrawStuff::load_hva(HVAName)) { // for (int i = 0; i < 8; ++i) { @@ -1889,7 +1938,7 @@ void CLoading::LoadVehicleOrAircraft(const CString& ID) *m_voxelNormalTables, lightDirection, rotation, - 0, + Vec3f{}, vxlColors[i], vxlLighting[i], ¢er_x, ¢er_y, @@ -2016,7 +2065,6 @@ void CLoading::SetImageData(unsigned char* pBuffer, const CString& NameInDict, i SetImageData(pBuffer, data, FullWidth, FullHeight, pPal); } -// TODO: do not do this here, but in the calling position of "LoadUnitGraphic" void CLoading::SetImageData(unsigned char* pBuffer, PICDATA& pData, const int FullWidth, const int FullHeight, Palette* pPal) { if (pData.pic) { diff --git a/MissionEditor/Loading.h b/MissionEditor/Loading.h index 96f650b..b7f949e 100644 --- a/MissionEditor/Loading.h +++ b/MissionEditor/Loading.h @@ -121,6 +121,7 @@ public: void UnionSHP_GetAndClear(unsigned char*& pOutBuffer, int* OutWidth, int* OutHeight, bool UseTemp = false); void VXL_Add(const unsigned char* pCache, int X, int Y, int Width, int Height); void VXL_GetAndClear(unsigned char*& pBuffer, int* OutWidth, int* OutHeight); + void VXL_Reset(); BOOL LoadUnitGraphic(const CString& lpUnittype); void LoadBuildingSubGraphic(const CString& subkey, const CIniFileSection& artSection, BOOL bAlwaysSetChar, char theat, HMIXFILE hShpMix, SHPHEADER& shp_h, BYTE*& shp); void LoadOverlayGraphic(const CString& lpOvrlName, int iOvrlNum); @@ -238,7 +239,8 @@ private: std::map ObjectTypes; std::vector UnionSHP_Data[2]; - unsigned char VXL_Data[0x10000]; + static auto constexpr VoxelBlendCacheLength = 0x10000; + unsigned char VXL_Data[VoxelBlendCacheLength]; }; //{{AFX_INSERT_LOCATION}} From 5648034cc5f47c1e585aaa374cca066f2628ca34 Mon Sep 17 00:00:00 2001 From: Zero Fanker Date: Fri, 24 May 2024 20:18:55 -0400 Subject: [PATCH 12/13] attempt to make Voxel render work . --- MissionEditor/Loading.cpp | 52 +++++++++++++++++++++++++-------------- MissionEditor/Loading.h | 2 +- 2 files changed, 34 insertions(+), 20 deletions(-) diff --git a/MissionEditor/Loading.cpp b/MissionEditor/Loading.cpp index 56b2f60..f2dd2b7 100644 --- a/MissionEditor/Loading.cpp +++ b/MissionEditor/Loading.cpp @@ -555,14 +555,18 @@ void CLoading::UnionSHP_Add(unsigned char* pBuffer, int Width, int Height, int D } -void CLoading::UnionSHP_GetAndClear(unsigned char*& pOutBuffer, int* OutWidth, int* OutHeight, bool UseTemp) +void CLoading::UnionSHP_GetAndClear(unsigned char*& pOutBuffer, int* OutWidth, int* OutHeight, bool clearBuffer, bool UseTemp) { // never calls it when UnionSHP_Data is empty if (UnionSHP_Data[UseTemp].size() == 1) { pOutBuffer = UnionSHP_Data[UseTemp][0].Buffer; - *OutWidth = UnionSHP_Data[UseTemp][0].Width; - *OutHeight = UnionSHP_Data[UseTemp][0].Height; + if (OutWidth) { + *OutWidth = UnionSHP_Data[UseTemp][0].Width; + } + if (OutHeight) { + *OutHeight = UnionSHP_Data[UseTemp][0].Height; + } UnionSHP_Data[UseTemp].clear(); return; } @@ -582,8 +586,12 @@ void CLoading::UnionSHP_GetAndClear(unsigned char*& pOutBuffer, int* OutWidth, i // just make it work like unsigned char[W][H]; pOutBuffer = new(unsigned char[W * H]); ZeroMemory(pOutBuffer, W * H); - *OutWidth = W; - *OutHeight = H; + if (OutWidth) { + *OutWidth = W; + } + if (OutHeight) { + *OutHeight = H; + } int ImageCenterX = W / 2; int ImageCenterY = H / 2; @@ -598,7 +606,9 @@ void CLoading::UnionSHP_GetAndClear(unsigned char*& pOutBuffer, int* OutWidth, i if (auto nPalIdx = data.Buffer[j * data.Width + i]) pOutBuffer[(nStartY + j) * W + nStartX + i] = nPalIdx; - delete[](data.Buffer); + if (clearBuffer) { + delete[](data.Buffer); + } } UnionSHP_Data[UseTemp].clear(); @@ -1582,7 +1592,6 @@ void CLoading::LoadBuilding(const CString& ID) CString VXLName = BarlName + ".vxl"; CString HVAName = BarlName + ".hva"; -#if 0 HMIXFILE hBarl = FindFileInMix(BarlName); if (hBarl && FSunPackLib::SetCurrentVXL(VXLName, hBarl)) { auto vnc = FSunPackLib::VoxelNormalClass::Unknown; @@ -1625,11 +1634,7 @@ void CLoading::LoadBuilding(const CString& ID) barlrect[i] = { x, y, width, height }; } } -#endif - if (ID == "NAFLAK") { - printf(""); - } VXLName = TurName + ".vxl"; HVAName = TurName + ".hva"; @@ -1670,9 +1675,17 @@ void CLoading::LoadBuilding(const CString& ID) auto const width = r.right - r.left; auto const height = r.bottom - r.top; - VXL_Add(vxlColors[i].data(), x, y, width, height); - VXL_Add(vxlLighting[i].data(), x, y, width, height); - VXL_GetAndClear(pTurImages[i], nullptr, nullptr); + //Blit_PalD(lpT[i], destRect, turretColors[i].data(), srcRect, ddsd.dwWidth, head.cx, ddsd.dwHeight, head.cy); + //Blit_PalD(lighting[i].data(), destRect, turretLighting[i].data(), srcRect, ddsd.dwWidth, head.cx, ddsd.dwHeight, head.cy, turretColors[i].data()); + //if (std::find_if(lighting[i].begin(), lighting[i].end(), [](const BYTE b) { return b != 255; }) != lighting[i].end()) + // p.lighting = std::shared_ptr>(new std::vector(std::move(lighting[i]))); + + UnionSHP_Add(vxlColors[i].data(), width, height); + UnionSHP_Add(vxlLighting[i].data(), width, height); + UnionSHP_GetAndClear(pTurImages[i], nullptr, nullptr, false); + //VXL_Add(vxlColors[i].data(), x, y, width, height); + //VXL_Add(vxlLighting[i].data(), x, y, width, height); + //VXL_GetAndClear(pTurImages[i], nullptr, nullptr); turrect[i] = { x, y, width, height }; } } @@ -1707,8 +1720,9 @@ void CLoading::LoadBuilding(const CString& ID) pKey.Format("%sY%d", ID, (15 - i) % 8); int turdeltaY = g_data.GetInteger("BuildingVoxelTurretsRA2", pKey); - VXL_Add(pTurImages[i], turretRect.X + turdeltaX, turretRect.Y + turdeltaY, turretRect.Width, turretRect.Height); - delete[] pTurImages[i]; + //VXL_Add(pTurImages[i], turretRect.X + turdeltaX, turretRect.Y + turdeltaY, turretRect.Width, turretRect.Height); + UnionSHP_Add(pTurImages[i], turretRect.Width, turretRect.Height, turretRect.X + turdeltaX, turretRect.Y + turdeltaY); + //delete[] pTurImages[i]; if (pBarlImages[i]) { pKey.Format("%sX%d", ID, (15 - i) % 8); @@ -1721,10 +1735,10 @@ void CLoading::LoadBuilding(const CString& ID) } } - int nW = 0x100, nH = 0x100; - VXL_GetAndClear(pTurImages[i], &nW, &nH); + //int nW = 0x100, nH = 0x100; + //VXL_GetAndClear(pTurImages[i], &nW, &nH); - UnionSHP_Add(pTurImages[i], 0x100, 0x100, deltaX, deltaY); + //UnionSHP_Add(pTurImages[i], 0x100, 0x100, deltaX, deltaY); unsigned char* pImage; int width1, height1; diff --git a/MissionEditor/Loading.h b/MissionEditor/Loading.h index b7f949e..084c572 100644 --- a/MissionEditor/Loading.h +++ b/MissionEditor/Loading.h @@ -118,7 +118,7 @@ public: void SetImageData(unsigned char* pBuffer, const CString& NameInDict, int FullWidth, int FullHeight, Palette* pPal); void SetImageData(unsigned char* pBuffer, PICDATA& pData, const int FullWidth, const int FullHeight, Palette* pPal); void UnionSHP_Add(unsigned char* pBuffer, int Width, int Height, int DeltaX = 0, int DeltaY = 0, bool UseTemp = false); - void UnionSHP_GetAndClear(unsigned char*& pOutBuffer, int* OutWidth, int* OutHeight, bool UseTemp = false); + void UnionSHP_GetAndClear(unsigned char*& pOutBuffer, int* OutWidth, int* OutHeight, bool clearBuffer = true, bool UseTemp = false); void VXL_Add(const unsigned char* pCache, int X, int Y, int Width, int Height); void VXL_GetAndClear(unsigned char*& pBuffer, int* OutWidth, int* OutHeight); void VXL_Reset(); From 38ddc52d2883819686064a4dbfce32c895682b70 Mon Sep 17 00:00:00 2001 From: Zero Fanker Date: Mon, 20 May 2024 23:27:42 -0400 Subject: [PATCH 13/13] Introduced voxel render lib written by Thomas Sneddon . --- .gitmodules | 3 + 3rdParty/CncVxlRender | 1 + 3rdParty/xcc/misc/cc_file.h | 2 +- 3rdParty/xcc/misc/tmp_ts_file.h | 5 +- MissionEditor.sln | 65 ++++ MissionEditor/Loading.cpp | 304 ++++++------------ MissionEditor/MissionEditor.vcxproj | 4 +- MissionEditor/MissionEditor.vcxproj.filters | 6 + MissionEditor/PropertySheets/Common.props | 2 +- MissionEditor/PropertySheets/Debug.props | 3 +- .../PropertySheets/Distribution.props | 4 + MissionEditor/PropertySheets/Release.props | 3 +- MissionEditor/VoxelDrawer.cpp | 83 +++++ MissionEditor/VoxelDrawer.h | 27 ++ MissionEditorPackLib/MissionEditorPackLib.cpp | 29 ++ MissionEditorPackLib/MissionEditorPackLib.h | 3 + 16 files changed, 329 insertions(+), 215 deletions(-) create mode 160000 3rdParty/CncVxlRender create mode 100644 MissionEditor/VoxelDrawer.cpp create mode 100644 MissionEditor/VoxelDrawer.h diff --git a/.gitmodules b/.gitmodules index d49ab5c..e35d075 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "gtest-lib"] path = googletest url = ../gtest-lib.git +[submodule "3rdParty/CncVxlRender"] + path = 3rdParty/CncVxlRender + url = ../CncVxlRenderText.git diff --git a/3rdParty/CncVxlRender b/3rdParty/CncVxlRender new file mode 160000 index 0000000..ebea5a3 --- /dev/null +++ b/3rdParty/CncVxlRender @@ -0,0 +1 @@ +Subproject commit ebea5a3718f27be0a57e717fafa8cc2afbede0e1 diff --git a/3rdParty/xcc/misc/cc_file.h b/3rdParty/xcc/misc/cc_file.h index ef7e9b1..ba157d7 100644 --- a/3rdParty/xcc/misc/cc_file.h +++ b/3rdParty/xcc/misc/cc_file.h @@ -191,5 +191,5 @@ private: bool m_is_open = false; int64_t m_p; const bool m_read_on_open; - size_t m_size; + int64_t m_size; }; diff --git a/3rdParty/xcc/misc/tmp_ts_file.h b/3rdParty/xcc/misc/tmp_ts_file.h index 22358eb..2963b42 100644 --- a/3rdParty/xcc/misc/tmp_ts_file.h +++ b/3rdParty/xcc/misc/tmp_ts_file.h @@ -34,7 +34,10 @@ public: bool is_valid() const { const t_tmp_ts_header& h = header(); - auto const size = get_size(); + if (get_size() < 0) { + return false; + } + auto const size = static_cast(get_size()); if (sizeof(t_tmp_ts_header) > size || !h.cblocks_x || !h.cblocks_y || h.cx != 48 && h.cx != 60 || diff --git a/MissionEditor.sln b/MissionEditor.sln index 9993885..4197936 100644 --- a/MissionEditor.sln +++ b/MissionEditor.sln @@ -6,6 +6,7 @@ MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MissionEditor", "MissionEditor\MissionEditor.vcxproj", "{9326D29A-6547-42B9-A668-519F3C0720A9}" ProjectSection(ProjectDependencies) = postProject {5E445578-CB45-4D82-9A1C-FC7D3E8D866A} = {5E445578-CB45-4D82-9A1C-FC7D3E8D866A} + {BAE32EF7-4F88-40D8-8984-A2EAF14C0A63} = {BAE32EF7-4F88-40D8-8984-A2EAF14C0A63} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MissionEditorPackLib", "MissionEditorPackLib\MissionEditorPackLib.vcxproj", "{DEB40EF0-E215-4C2F-A0AD-3742E2E01A8C}" @@ -17,6 +18,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XCC Library", "3rdParty\xcc EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UnitTest", "UnitTest\UnitTest.vcxproj", "{75E18879-7564-4A2C-8C00-393A5A17171F}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CncVxlRenderText", "3rdParty\CncVxlRender\CncVxlRenderText.vcxproj", "{BAE32EF7-4F88-40D8-8984-A2EAF14C0A63}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -39,6 +42,8 @@ Global Template|x64 = Template|x64 Tests FinalAlertDebug YR|Win32 = Tests FinalAlertDebug YR|Win32 Tests FinalAlertDebug YR|x64 = Tests FinalAlertDebug YR|x64 + Tool|Win32 = Tool|Win32 + Tool|x64 = Tool|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {9326D29A-6547-42B9-A668-519F3C0720A9}.Debug|Win32.ActiveCfg = Tests FinalAlertDebug YR|Win32 @@ -81,6 +86,10 @@ Global {9326D29A-6547-42B9-A668-519F3C0720A9}.Tests FinalAlertDebug YR|Win32.Build.0 = Tests FinalAlertDebug YR|Win32 {9326D29A-6547-42B9-A668-519F3C0720A9}.Tests FinalAlertDebug YR|x64.ActiveCfg = Tests FinalAlertDebug YR|x64 {9326D29A-6547-42B9-A668-519F3C0720A9}.Tests FinalAlertDebug YR|x64.Build.0 = Tests FinalAlertDebug YR|x64 + {9326D29A-6547-42B9-A668-519F3C0720A9}.Tool|Win32.ActiveCfg = Template|Win32 + {9326D29A-6547-42B9-A668-519F3C0720A9}.Tool|Win32.Build.0 = Template|Win32 + {9326D29A-6547-42B9-A668-519F3C0720A9}.Tool|x64.ActiveCfg = Template|x64 + {9326D29A-6547-42B9-A668-519F3C0720A9}.Tool|x64.Build.0 = Template|x64 {DEB40EF0-E215-4C2F-A0AD-3742E2E01A8C}.Debug|Win32.ActiveCfg = Debug|Win32 {DEB40EF0-E215-4C2F-A0AD-3742E2E01A8C}.Debug|Win32.Build.0 = Debug|Win32 {DEB40EF0-E215-4C2F-A0AD-3742E2E01A8C}.Debug|x64.ActiveCfg = Debug|x64 @@ -121,6 +130,10 @@ Global {DEB40EF0-E215-4C2F-A0AD-3742E2E01A8C}.Tests FinalAlertDebug YR|Win32.Build.0 = Debug|Win32 {DEB40EF0-E215-4C2F-A0AD-3742E2E01A8C}.Tests FinalAlertDebug YR|x64.ActiveCfg = Debug|x64 {DEB40EF0-E215-4C2F-A0AD-3742E2E01A8C}.Tests FinalAlertDebug YR|x64.Build.0 = Debug|x64 + {DEB40EF0-E215-4C2F-A0AD-3742E2E01A8C}.Tool|Win32.ActiveCfg = Release|Win32 + {DEB40EF0-E215-4C2F-A0AD-3742E2E01A8C}.Tool|Win32.Build.0 = Release|Win32 + {DEB40EF0-E215-4C2F-A0AD-3742E2E01A8C}.Tool|x64.ActiveCfg = Release|x64 + {DEB40EF0-E215-4C2F-A0AD-3742E2E01A8C}.Tool|x64.Build.0 = Release|x64 {5E445578-CB45-4D82-9A1C-FC7D3E8D866A}.Debug|Win32.ActiveCfg = Debug|Win32 {5E445578-CB45-4D82-9A1C-FC7D3E8D866A}.Debug|Win32.Build.0 = Debug|Win32 {5E445578-CB45-4D82-9A1C-FC7D3E8D866A}.Debug|x64.ActiveCfg = Debug|x64 @@ -161,6 +174,10 @@ Global {5E445578-CB45-4D82-9A1C-FC7D3E8D866A}.Tests FinalAlertDebug YR|Win32.Build.0 = DebugMinimal|Win32 {5E445578-CB45-4D82-9A1C-FC7D3E8D866A}.Tests FinalAlertDebug YR|x64.ActiveCfg = Debug|x64 {5E445578-CB45-4D82-9A1C-FC7D3E8D866A}.Tests FinalAlertDebug YR|x64.Build.0 = Debug|x64 + {5E445578-CB45-4D82-9A1C-FC7D3E8D866A}.Tool|Win32.ActiveCfg = Release|Win32 + {5E445578-CB45-4D82-9A1C-FC7D3E8D866A}.Tool|Win32.Build.0 = Release|Win32 + {5E445578-CB45-4D82-9A1C-FC7D3E8D866A}.Tool|x64.ActiveCfg = ReleaseMinimal|x64 + {5E445578-CB45-4D82-9A1C-FC7D3E8D866A}.Tool|x64.Build.0 = ReleaseMinimal|x64 {75E18879-7564-4A2C-8C00-393A5A17171F}.Debug|Win32.ActiveCfg = Debug|Win32 {75E18879-7564-4A2C-8C00-393A5A17171F}.Debug|Win32.Build.0 = Debug|Win32 {75E18879-7564-4A2C-8C00-393A5A17171F}.Debug|x64.ActiveCfg = Debug|x64 @@ -201,6 +218,54 @@ Global {75E18879-7564-4A2C-8C00-393A5A17171F}.Tests FinalAlertDebug YR|Win32.Build.0 = Debug|Win32 {75E18879-7564-4A2C-8C00-393A5A17171F}.Tests FinalAlertDebug YR|x64.ActiveCfg = Debug|x64 {75E18879-7564-4A2C-8C00-393A5A17171F}.Tests FinalAlertDebug YR|x64.Build.0 = Debug|x64 + {75E18879-7564-4A2C-8C00-393A5A17171F}.Tool|Win32.ActiveCfg = Release|Win32 + {75E18879-7564-4A2C-8C00-393A5A17171F}.Tool|Win32.Build.0 = Release|Win32 + {75E18879-7564-4A2C-8C00-393A5A17171F}.Tool|x64.ActiveCfg = Release|x64 + {75E18879-7564-4A2C-8C00-393A5A17171F}.Tool|x64.Build.0 = Release|x64 + {BAE32EF7-4F88-40D8-8984-A2EAF14C0A63}.Debug|Win32.ActiveCfg = Debug|Win32 + {BAE32EF7-4F88-40D8-8984-A2EAF14C0A63}.Debug|Win32.Build.0 = Debug|Win32 + {BAE32EF7-4F88-40D8-8984-A2EAF14C0A63}.Debug|x64.ActiveCfg = Debug|x64 + {BAE32EF7-4F88-40D8-8984-A2EAF14C0A63}.Debug|x64.Build.0 = Debug|x64 + {BAE32EF7-4F88-40D8-8984-A2EAF14C0A63}.FinalAlertDebug YR|Win32.ActiveCfg = Debug|Win32 + {BAE32EF7-4F88-40D8-8984-A2EAF14C0A63}.FinalAlertDebug YR|Win32.Build.0 = Debug|Win32 + {BAE32EF7-4F88-40D8-8984-A2EAF14C0A63}.FinalAlertDebug YR|x64.ActiveCfg = Debug|x64 + {BAE32EF7-4F88-40D8-8984-A2EAF14C0A63}.FinalAlertDebug YR|x64.Build.0 = Debug|x64 + {BAE32EF7-4F88-40D8-8984-A2EAF14C0A63}.FinalAlertDebug|Win32.ActiveCfg = Debug|Win32 + {BAE32EF7-4F88-40D8-8984-A2EAF14C0A63}.FinalAlertDebug|Win32.Build.0 = Debug|Win32 + {BAE32EF7-4F88-40D8-8984-A2EAF14C0A63}.FinalAlertDebug|x64.ActiveCfg = Debug|x64 + {BAE32EF7-4F88-40D8-8984-A2EAF14C0A63}.FinalAlertDebug|x64.Build.0 = Debug|x64 + {BAE32EF7-4F88-40D8-8984-A2EAF14C0A63}.FinalAlertRelease YR|Win32.ActiveCfg = Release|Win32 + {BAE32EF7-4F88-40D8-8984-A2EAF14C0A63}.FinalAlertRelease YR|Win32.Build.0 = Release|Win32 + {BAE32EF7-4F88-40D8-8984-A2EAF14C0A63}.FinalAlertRelease YR|x64.ActiveCfg = Release|x64 + {BAE32EF7-4F88-40D8-8984-A2EAF14C0A63}.FinalAlertRelease YR|x64.Build.0 = Release|x64 + {BAE32EF7-4F88-40D8-8984-A2EAF14C0A63}.FinalAlertRelease|Win32.ActiveCfg = Release|Win32 + {BAE32EF7-4F88-40D8-8984-A2EAF14C0A63}.FinalAlertRelease|Win32.Build.0 = Release|Win32 + {BAE32EF7-4F88-40D8-8984-A2EAF14C0A63}.FinalAlertRelease|x64.ActiveCfg = Release|x64 + {BAE32EF7-4F88-40D8-8984-A2EAF14C0A63}.FinalAlertRelease|x64.Build.0 = Release|x64 + {BAE32EF7-4F88-40D8-8984-A2EAF14C0A63}.FinalSunDebug|Win32.ActiveCfg = Debug|Win32 + {BAE32EF7-4F88-40D8-8984-A2EAF14C0A63}.FinalSunDebug|Win32.Build.0 = Debug|Win32 + {BAE32EF7-4F88-40D8-8984-A2EAF14C0A63}.FinalSunDebug|x64.ActiveCfg = Debug|x64 + {BAE32EF7-4F88-40D8-8984-A2EAF14C0A63}.FinalSunDebug|x64.Build.0 = Debug|x64 + {BAE32EF7-4F88-40D8-8984-A2EAF14C0A63}.FinalSunRelease|Win32.ActiveCfg = Release|Win32 + {BAE32EF7-4F88-40D8-8984-A2EAF14C0A63}.FinalSunRelease|Win32.Build.0 = Release|Win32 + {BAE32EF7-4F88-40D8-8984-A2EAF14C0A63}.FinalSunRelease|x64.ActiveCfg = Release|x64 + {BAE32EF7-4F88-40D8-8984-A2EAF14C0A63}.FinalSunRelease|x64.Build.0 = Release|x64 + {BAE32EF7-4F88-40D8-8984-A2EAF14C0A63}.Release|Win32.ActiveCfg = Release|Win32 + {BAE32EF7-4F88-40D8-8984-A2EAF14C0A63}.Release|Win32.Build.0 = Release|Win32 + {BAE32EF7-4F88-40D8-8984-A2EAF14C0A63}.Release|x64.ActiveCfg = Release|x64 + {BAE32EF7-4F88-40D8-8984-A2EAF14C0A63}.Release|x64.Build.0 = Release|x64 + {BAE32EF7-4F88-40D8-8984-A2EAF14C0A63}.Template|Win32.ActiveCfg = Tool|Win32 + {BAE32EF7-4F88-40D8-8984-A2EAF14C0A63}.Template|Win32.Build.0 = Tool|Win32 + {BAE32EF7-4F88-40D8-8984-A2EAF14C0A63}.Template|x64.ActiveCfg = Tool|x64 + {BAE32EF7-4F88-40D8-8984-A2EAF14C0A63}.Template|x64.Build.0 = Tool|x64 + {BAE32EF7-4F88-40D8-8984-A2EAF14C0A63}.Tests FinalAlertDebug YR|Win32.ActiveCfg = Debug|Win32 + {BAE32EF7-4F88-40D8-8984-A2EAF14C0A63}.Tests FinalAlertDebug YR|Win32.Build.0 = Debug|Win32 + {BAE32EF7-4F88-40D8-8984-A2EAF14C0A63}.Tests FinalAlertDebug YR|x64.ActiveCfg = Debug|x64 + {BAE32EF7-4F88-40D8-8984-A2EAF14C0A63}.Tests FinalAlertDebug YR|x64.Build.0 = Debug|x64 + {BAE32EF7-4F88-40D8-8984-A2EAF14C0A63}.Tool|Win32.ActiveCfg = Tool|Win32 + {BAE32EF7-4F88-40D8-8984-A2EAF14C0A63}.Tool|Win32.Build.0 = Tool|Win32 + {BAE32EF7-4F88-40D8-8984-A2EAF14C0A63}.Tool|x64.ActiveCfg = Tool|x64 + {BAE32EF7-4F88-40D8-8984-A2EAF14C0A63}.Tool|x64.Build.0 = Tool|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/MissionEditor/Loading.cpp b/MissionEditor/Loading.cpp index f2dd2b7..ad95c86 100644 --- a/MissionEditor/Loading.cpp +++ b/MissionEditor/Loading.cpp @@ -40,6 +40,7 @@ #include "VoxelNormals.h" #include #include "IniMega.h" +#include "VoxelDrawer.h" #ifdef _DEBUG #define new DEBUG_NEW @@ -47,14 +48,6 @@ static char THIS_FILE[] = __FILE__; #endif -struct DrawRect -{ - int X{}; - int Y{}; - int Width{}; - int Height{}; -}; - ///////////////////////////////////////////////////////////////////////////// // Dialogfeld CLoading @@ -103,6 +96,7 @@ CLoading::CLoading(CWnd* pParent /*=NULL*/) : } VXL_Reset(); + VoxelDrawer::Initalize(); errstream << "CLoading::CLoading() called" << endl; errstream.flush(); @@ -1578,129 +1572,47 @@ void CLoading::LoadBuilding(const CString& ID) CString TurName = rules.GetStringOr(ID, "TurretAnim", ID + "tur"); CString BarlName = ID + "barl"; + auto finder = [this](LPCTSTR lpFilename, char* pTheaterChar) { + return this->FindFileInMix(lpFilename, reinterpret_cast(pTheaterChar)); + }; - //if (!DrawStuff::is_vpl_loaded()) { - // DrawStuff::load_vpl("voxels.vpl"); - //} + if (!VoxelDrawer::IsVPLLoaded()) { + VoxelDrawer::LoadVPLFile("voxels.vpl", finder); + } unsigned char* pTurImages[8]{ nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr }; unsigned char* pBarlImages[8]{ nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr }; - DrawRect turrect[8] = { 0 }; - int barlrect[8][4] = { 0 }; + VoxelRectangle turrect[8] = { 0 }; + VoxelRectangle barlrect[8] = { 0 }; CString VXLName = BarlName + ".vxl"; CString HVAName = BarlName + ".hva"; - HMIXFILE hBarl = FindFileInMix(BarlName); - if (hBarl && FSunPackLib::SetCurrentVXL(VXLName, hBarl)) { - auto vnc = FSunPackLib::VoxelNormalClass::Unknown; - std::vector vxlColors[8]; - std::vector vxlLighting[8]; - // we assume the voxel normal class is always the same for the combined voxels - FSunPackLib::GetVXLSectionInfo(0, vnc); - for (int i = 0; i < 8; ++i) { - float r_x, r_y, r_z; - const int dir = i; - r_x = 300; - r_y = 0; - r_z = 45 * dir + 90; - - // convert - const double pi = 3.141592654; - const Vec3f rotation(r_x / 180.0f * pi, r_y / 180.0f * pi, r_z / 180.0f * pi); - RECT r; - int center_x, center_y; - if (!FSunPackLib::LoadVXLImage( - *m_voxelNormalTables, - lightDirection, - rotation, - 0, - vxlColors[i], - vxlLighting[i], - ¢er_x, ¢er_y, - 0, nullptr, nullptr, 0, 0, &r)) { - break; + if (VoxelDrawer::LoadVXLFile(VXLName, finder)) { + if (VoxelDrawer::LoadHVAFile(HVAName, finder)) { + for (int i = 0; i < 8; ++i) { + // (13 - i) % 8 for facing fix + bool result = VoxelDrawer::GetImageData((13 - i) % 8, pBarlImages[i], barlrect[i], turzadjust); + if (!result) + break; } - - auto const x = center_x; - auto const y = center_y; - auto const width = r.right - r.left; - auto const height = r.bottom - r.top; - - VXL_Add(vxlColors[i].data(), x, y, width, height); - VXL_Add(vxlLighting[i].data(), x, y, width, height); - VXL_GetAndClear(pTurImages[i], nullptr, nullptr); - barlrect[i] = { x, y, width, height }; } } - VXLName = TurName + ".vxl"; HVAName = TurName + ".hva"; - HMIXFILE hVXL = FindFileInMix(VXLName); - if (hVXL && FSunPackLib::SetCurrentVXL(VXLName, hVXL)) { - auto vnc = FSunPackLib::VoxelNormalClass::Unknown; - std::vector vxlColors[8]; - std::vector vxlLighting[8]; - // we assume the voxel normal class is always the same for the combined voxels - FSunPackLib::GetVXLSectionInfo(0, vnc); + if (VoxelDrawer::LoadVXLFile(VXLName, finder) && VoxelDrawer::LoadHVAFile(HVAName, finder)) { for (int i = 0; i < 8; ++i) { - float r_x, r_y, r_z; - const int dir = i; - r_x = 300; - r_y = 0; - r_z = 45 * dir + 90; - - // convert - const double pi = 3.141592654; - const Vec3f rotation(r_x / 180.0f * pi, r_y / 180.0f * pi, r_z / 180.0f * pi); - RECT r; - int center_x, center_y; - if (!FSunPackLib::LoadVXLImage( - *m_voxelNormalTables, - lightDirection, - rotation, - Vec3f{}, - vxlColors[i], - vxlLighting[i], - ¢er_x, ¢er_y, - 0, nullptr, nullptr, 0, 0, &r)) { + // (13 - i) % 8 for facing fix + bool result = VoxelDrawer::GetImageData((13 - i) % 8, pTurImages[i], turrect[i], pBarlImages[i] ? 0 : turzadjust); + if (!result) { break; } - - auto const x = center_x; - auto const y = center_y; - auto const width = r.right - r.left; - auto const height = r.bottom - r.top; - - //Blit_PalD(lpT[i], destRect, turretColors[i].data(), srcRect, ddsd.dwWidth, head.cx, ddsd.dwHeight, head.cy); - //Blit_PalD(lighting[i].data(), destRect, turretLighting[i].data(), srcRect, ddsd.dwWidth, head.cx, ddsd.dwHeight, head.cy, turretColors[i].data()); - //if (std::find_if(lighting[i].begin(), lighting[i].end(), [](const BYTE b) { return b != 255; }) != lighting[i].end()) - // p.lighting = std::shared_ptr>(new std::vector(std::move(lighting[i]))); - - UnionSHP_Add(vxlColors[i].data(), width, height); - UnionSHP_Add(vxlLighting[i].data(), width, height); - UnionSHP_GetAndClear(pTurImages[i], nullptr, nullptr, false); - //VXL_Add(vxlColors[i].data(), x, y, width, height); - //VXL_Add(vxlLighting[i].data(), x, y, width, height); - //VXL_GetAndClear(pTurImages[i], nullptr, nullptr); - turrect[i] = { x, y, width, height }; } } - //if (DrawStuff::load_vxl(VXLName) && DrawStuff::load_hva(HVAName)) { - // for (int i = 0; i < 8; ++i) { - // // (13 - i) % 8 for facing fix - // bool result = DrawStuff::get_to_image((13 - i) % 8, pTurImages[i], - // turrect[i][0], turrect[i][1], turrect[i][2], turrect[i][3], pBarlImages[i] ? 0 : turzadjust); - // if (!result) { - // break; - // } - // } - //} - for (int i = 0; i < 8; ++i) { auto pTempBuf = new(unsigned char[width * height]); memcpy_s(pTempBuf, width * height, pBuffer, width * height); @@ -1720,9 +1632,8 @@ void CLoading::LoadBuilding(const CString& ID) pKey.Format("%sY%d", ID, (15 - i) % 8); int turdeltaY = g_data.GetInteger("BuildingVoxelTurretsRA2", pKey); - //VXL_Add(pTurImages[i], turretRect.X + turdeltaX, turretRect.Y + turdeltaY, turretRect.Width, turretRect.Height); - UnionSHP_Add(pTurImages[i], turretRect.Width, turretRect.Height, turretRect.X + turdeltaX, turretRect.Y + turdeltaY); - //delete[] pTurImages[i]; + VXL_Add(pTurImages[i], turretRect.X + turdeltaX, turretRect.Y + turdeltaY, turretRect.W, turretRect.H); + delete[] pTurImages[i]; if (pBarlImages[i]) { pKey.Format("%sX%d", ID, (15 - i) % 8); @@ -1730,15 +1641,15 @@ void CLoading::LoadBuilding(const CString& ID) pKey.Format("%sY%d", ID, (15 - i) % 8); int barldeltaY = g_data.GetInteger("BuildingVoxelBarrelsRA2", pKey); - VXL_Add(pBarlImages[i], barlRect[2] + barldeltaX, barlRect[3] + barldeltaY, barlRect[0], barlRect[1]); + VXL_Add(pBarlImages[i], barlRect.X + barldeltaX, barlRect.Y + barldeltaY, barlRect.W, barlRect.H); delete[] pBarlImages[i]; } } - //int nW = 0x100, nH = 0x100; - //VXL_GetAndClear(pTurImages[i], &nW, &nH); + int nW = 0x100, nH = 0x100; + VXL_GetAndClear(pTurImages[i], &nW, &nH); - //UnionSHP_Add(pTurImages[i], 0x100, 0x100, deltaX, deltaY); + UnionSHP_Add(pTurImages[i], 0x100, 0x100, deltaX, deltaY); unsigned char* pImage; int width1, height1; @@ -1897,13 +1808,17 @@ void CLoading::LoadVehicleOrAircraft(const CString& ID) return; } + auto finder = [this](LPCTSTR lpFilename, char* pTheaterChar) { + return this->FindFileInMix(lpFilename, reinterpret_cast(pTheaterChar)); + }; + // As VXL CString FileName = ImageID + ".vxl"; CString HVAName = ImageID + ".hva"; - //if (!DrawStuff::is_vpl_loaded()) { - // DrawStuff::load_vpl("voxels.vpl"); - //} + if (!VoxelDrawer::IsVPLLoaded()) { + VoxelDrawer::LoadVPLFile("voxels.vpl", finder); + } CString PaletteName = art.GetStringOr(ArtID, "Palette", "unit"); GetFullPaletteName(PaletteName, cur_theat); @@ -1911,9 +1826,9 @@ void CLoading::LoadVehicleOrAircraft(const CString& ID) unsigned char* pImage[8]{ nullptr,nullptr ,nullptr ,nullptr ,nullptr ,nullptr ,nullptr ,nullptr }; unsigned char* pTurretImage[8]{ nullptr ,nullptr ,nullptr ,nullptr ,nullptr ,nullptr ,nullptr ,nullptr }; unsigned char* pBarrelImage[8]{ nullptr ,nullptr ,nullptr ,nullptr ,nullptr ,nullptr ,nullptr ,nullptr }; - DrawRect rect[8]; - DrawRect turretrect[8]; - DrawRect barrelrect[8]; + VoxelRectangle rect[8]; + VoxelRectangle turretrect[8]; + VoxelRectangle barrelrect[8]; int nMix = this->FindFileInMix(FileName); if (!nMix || !FSunPackLib::SetCurrentVXL(FileName, nMix)) { @@ -1923,52 +1838,18 @@ void CLoading::LoadVehicleOrAircraft(const CString& ID) std::vector vxlColors[8]; std::vector vxlLighting[8]; - //if (!DrawStuff::load_vxl(FileName)) { - // return; - //} - //if (!DrawStuff::load_hva(HVAName)) { - // return; - //} + if (!VoxelDrawer::LoadVXLFile(FileName, finder)) { + return; + } + if (!VoxelDrawer::LoadHVAFile(HVAName, finder)) { + return; + } for (int i = 0; i < 8; ++i) { // (i+6) % 8 to fix the facing - //bool result = DrawStuff::get_to_image((i + 6) % 8, pImage[i], - // rect[i][0], rect[i][1], rect[i][2], rect[i][3]); - //if (!result) { - // return; - //} - - float r_x, r_y, r_z; - const int dir = i; - r_x = 300; - r_y = 0; - r_z = 45 * dir + 90; - - // convert - const double pi = 3.141592654; - const Vec3f rotation(r_x / 180.0f * pi, r_y / 180.0f * pi, r_z / 180.0f * pi); - RECT r; - int center_x, center_y; - if (!FSunPackLib::LoadVXLImage( - *m_voxelNormalTables, - lightDirection, - rotation, - Vec3f{}, - vxlColors[i], - vxlLighting[i], - ¢er_x, ¢er_y, - 0, nullptr, nullptr, 0, 0, &r)) { - break; + bool result = VoxelDrawer::GetImageData((i + 6) % 8, pImage[i], rect[i]); + if (!result) { + return; } - - auto const x = center_x; - auto const y = center_y; - auto const width = r.right - r.left; - auto const height = r.bottom - r.top; - - VXL_Add(vxlColors[i].data(), x, y, width, height); - VXL_Add(vxlLighting[i].data(), x, y, width, height); - VXL_GetAndClear(pImage[i], nullptr, nullptr); - rect[i] = { x,y,width,height }; } if (!bHasTurret) { @@ -1979,7 +1860,7 @@ void CLoading::LoadVehicleOrAircraft(const CString& ID) unsigned char* outBuffer; int outW = 0x100, outH = 0x100; - VXL_Add(pImage[i], rect[i].X, rect[i].Y, rect[i].Width, rect[i].Height); + VXL_Add(pImage[i], rect[i].X, rect[i].Y, rect[i].W, rect[i].H); delete[] pImage[i]; VXL_GetAndClear(outBuffer, &outW, &outH); @@ -2000,38 +1881,42 @@ void CLoading::LoadVehicleOrAircraft(const CString& ID) CString turFileName = ImageID + "tur.vxl"; CString turHVAName = ImageID + "tur.hva"; - //if (DrawStuff::load_vxl(turFileName)) { - // return; - //} - //if (DrawStuff::load_hva(turHVAName)) { - // return; - //} + + if (VoxelDrawer::LoadVXLFile(turFileName, finder)) { + return; + } + if (VoxelDrawer::LoadHVAFile(turHVAName, finder)) { + return; + } + for (int i = 0; i < 8; ++i) { // (i+6) % 8 to fix the facing - //bool result = DrawStuff::get_to_image((i + 6) % 8, pTurretImage[i], - // turretrect[i][0], turretrect[i][1], turretrect[i][2], turretrect[i][3], F, L, H); + bool result = VoxelDrawer::GetImageData((i + 6) % 8, pTurretImage[i], + turretrect[i], F, L, H); - //if (!result) { - // break; - //} + if (!result) { + break; + } } CString barlFileName = ImageID + "barl.vxl"; CString barlHVAName = ImageID + "barl.hva"; - //if (!DrawStuff::load_vxl(barlFileName)) { - // return; - //} - //if (!DrawStuff::load_hva(barlHVAName)) { - // return; - //} + + if (!VoxelDrawer::LoadVXLFile(barlFileName, finder)) { + return; + } + if (!VoxelDrawer::LoadHVAFile(barlHVAName, finder)) { + return; + } + for (int i = 0; i < 8; ++i) { // (i+6) % 8 to fix the facing - //bool result = DrawStuff::get_to_image((i + 6) % 8, pBarrelImage[i], - // barrelrect[i][0], barrelrect[i][1], barrelrect[i][2], barrelrect[i][3], F, L, H); + bool result = VoxelDrawer::GetImageData((i + 6) % 8, pBarrelImage[i], + barrelrect[i], F, L, H); - //if (!result) { - // break; - //} + if (!result) { + break; + } } for (int i = 0; i < 8; ++i) { @@ -2042,7 +1927,7 @@ void CLoading::LoadVehicleOrAircraft(const CString& ID) int outW = 0x100, outH = 0x100; if (pImage[i]) { - VXL_Add(pImage[i], rect[i].X, rect[i].Y, rect[i].Width, rect[i].Height); + VXL_Add(pImage[i], rect[i].X, rect[i].Y, rect[i].W, rect[i].H); delete[] pImage[i]; } CString pKey; @@ -2051,7 +1936,7 @@ void CLoading::LoadVehicleOrAircraft(const CString& ID) int turdeltaX = g_data.GetInteger("VehicleVoxelTurretsRA2", pKey); pKey.Format("%sY%d", ID.operator LPCSTR(), i); int turdeltaY = g_data.GetInteger("VehicleVoxelTurretsRA2", pKey); - VXL_Add(pTurretImage[i], turretrect[i].X + turdeltaX, turretrect[i].Y + turdeltaY, turretrect[i].Width, turretrect[i].Height); + VXL_Add(pTurretImage[i], turretrect[i].X + turdeltaX, turretrect[i].Y + turdeltaY, turretrect[i].W, turretrect[i].H); delete[] pTurretImage[i]; if (pBarrelImage[i]) { @@ -2060,7 +1945,7 @@ void CLoading::LoadVehicleOrAircraft(const CString& ID) pKey.Format("%sY%d", ID.operator LPCSTR(), i); int barldeltaY = g_data.GetInteger("VehicleVoxelBarrelsRA2", pKey); - VXL_Add(pBarrelImage[i], barrelrect[i].X + barldeltaX, barrelrect[i].Y + barldeltaY, barrelrect[i].Width, barrelrect[i].Height); + VXL_Add(pBarrelImage[i], barrelrect[i].X + barldeltaX, barrelrect[i].Y + barldeltaY, barrelrect[i].W, barrelrect[i].H); delete[] pBarrelImage[i]; } } @@ -2522,6 +2407,7 @@ BOOL CLoading::InitMixFiles() CLoading::~CLoading() { Unload(); + VoxelDrawer::Finalize(); } void CLoading::Unload() @@ -3481,7 +3367,7 @@ void CLoading::LoadOverlayGraphic(const CString& lpOvrlName_, int iOvrlNum) FSunPackLib::SetTSPaletteEntry(hPalette, 0x10 + i, &rgbNew, &rgbOld[i]); } - } + } #endif FSunPackLib::LoadSHPImage(0, maxPics, lpT); @@ -3562,9 +3448,9 @@ void CLoading::LoadOverlayGraphic(const CString& lpOvrlName_, int iOvrlNum) delete[] lpT; - } + } -} + } int i; for (i = 0; i < 0xFF; i++) { @@ -3575,7 +3461,7 @@ void CLoading::LoadOverlayGraphic(const CString& lpOvrlName_, int iOvrlNum) } - } +} #endif void CLoading::OnDestroy() @@ -4043,21 +3929,21 @@ void CLoading::FreeAll() #endif i->second.pic = NULL; - } catch (...) { - CString err; - err = "Access violation while trying to release surface "; - char c[6]; - itoa(e, c, 10); - err += c; + } catch (...) { + CString err; + err = "Access violation while trying to release surface "; + char c[6]; + itoa(e, c, 10); + err += c; - err += "\n"; - OutputDebugString(err); - continue; - } - - i++; + err += "\n"; + OutputDebugString(err); + continue; } + i++; + } + try { @@ -4077,7 +3963,7 @@ void CLoading::FreeAll() } catch (...) { errstream << "Exception while freeing DirectDraw" << endl; } - } +} void CLoading::PostNcDestroy() { @@ -4346,7 +4232,7 @@ void CLoading::LoadStrings() //CCStrings[*rules.GetSectionName(i)].SetString=rul CCStrings[*rules.GetSectionName(i)].SetString((LPSTR)(LPCSTR)rules.GetSection(i)->values["Name"]); } -} + } #endif diff --git a/MissionEditor/MissionEditor.vcxproj b/MissionEditor/MissionEditor.vcxproj index ab01a2f..907abb3 100644 --- a/MissionEditor/MissionEditor.vcxproj +++ b/MissionEditor/MissionEditor.vcxproj @@ -348,7 +348,7 @@ NOMINMAX;RA2_MODE;YR_MODE;%(PreprocessorDefinitions) - ..\MissionEditorPackLib + ..\MissionEditorPackLib;..\3rdParty\CncVxlRender\inc RA2_MODE;YR_MODE;%(PreprocessorDefinitions) @@ -589,6 +589,7 @@ + @@ -691,6 +692,7 @@ + diff --git a/MissionEditor/MissionEditor.vcxproj.filters b/MissionEditor/MissionEditor.vcxproj.filters index 58193e5..59b1f8d 100644 --- a/MissionEditor/MissionEditor.vcxproj.filters +++ b/MissionEditor/MissionEditor.vcxproj.filters @@ -288,6 +288,9 @@ Source Files + + Source Files + @@ -586,6 +589,9 @@ Header Files + + Header Files + diff --git a/MissionEditor/PropertySheets/Common.props b/MissionEditor/PropertySheets/Common.props index cc6956b..1972aa8 100644 --- a/MissionEditor/PropertySheets/Common.props +++ b/MissionEditor/PropertySheets/Common.props @@ -30,7 +30,7 @@ true true - $(XccVcpkgDir)\lib + $(VxlLibDir);$(XccVcpkgDir)\lib Windows 11194304 11194304 diff --git a/MissionEditor/PropertySheets/Debug.props b/MissionEditor/PropertySheets/Debug.props index 3f12aa6..a0fb20e 100644 --- a/MissionEditor/PropertySheets/Debug.props +++ b/MissionEditor/PropertySheets/Debug.props @@ -6,6 +6,7 @@ $(XccDir)\vcpkg_installed\$(Platform)-windows\$(Platform)-windows $(XccVcpkgDirTriplet)\debug + $(SolutionDir)$(Platform)\Debug @@ -25,7 +26,7 @@ _DEBUG;%(PreprocessorDefinitions) - ddraw.lib;dxguid.lib;winmm.lib;gdiplus.lib;lzo2.lib;bz2d.lib;zlibd.lib;%(AdditionalDependencies) + CncVxlRenderText.lib;ddraw.lib;dxguid.lib;winmm.lib;gdiplus.lib;lzo2.lib;bz2d.lib;zlibd.lib;%(AdditionalDependencies) libcmt.lib diff --git a/MissionEditor/PropertySheets/Distribution.props b/MissionEditor/PropertySheets/Distribution.props index 65a9f22..358acad 100644 --- a/MissionEditor/PropertySheets/Distribution.props +++ b/MissionEditor/PropertySheets/Distribution.props @@ -15,6 +15,7 @@ + @@ -29,6 +30,9 @@ + + + diff --git a/MissionEditor/PropertySheets/Release.props b/MissionEditor/PropertySheets/Release.props index 6f1c942..f8f4f0f 100644 --- a/MissionEditor/PropertySheets/Release.props +++ b/MissionEditor/PropertySheets/Release.props @@ -6,6 +6,7 @@ $(XccDir)\vcpkg_installed\$(Platform)-windows\$(Platform)-windows $(XccVcpkgDirTriplet) + $(SolutionDir)$(Platform)\Release @@ -25,7 +26,7 @@ NDEBUG;_AFXDLL;%(PreprocessorDefinitions) - ddraw.lib;dxguid.lib;winmm.lib;gdiplus.lib;lzo2.lib;bz2.lib;zlib.lib;%(AdditionalDependencies) + CncVxlRenderText.lib;ddraw.lib;dxguid.lib;winmm.lib;gdiplus.lib;lzo2.lib;bz2.lib;zlib.lib;%(AdditionalDependencies) libcmt.lib; libcmtd.lib; msvcrtd.lib diff --git a/MissionEditor/VoxelDrawer.cpp b/MissionEditor/VoxelDrawer.cpp new file mode 100644 index 0000000..f5ec254 --- /dev/null +++ b/MissionEditor/VoxelDrawer.cpp @@ -0,0 +1,83 @@ +#include "stdafx.h" +#include "VoxelDrawer.h" +#include +#include "variables.h" +#include "MissionEditorPackLib.h" + +CString makeFullPath(const CString& name) +{ + return TSPath + name; +} + +std::pair readFile(const CString& name, HMIXFILE hMix) +{ + if (hMix == NULL) { + return FSunPackLib::LoadCCFile(makeFullPath(name), NULL); + } + return FSunPackLib::LoadCCFile(name, hMix); +} + +void VoxelDrawer::Initalize() +{ + CncImgCreate(); + CncImgSetMaxFacing(32); +} + +void VoxelDrawer::Finalize() +{ + CncImgRelease(); +} + +bool VoxelDrawer::LoadVPLFile(const CString& name, const FindFileInMixHandler& mixFindler) +{ + bool result = false; + auto const&& ret = readFile(name, mixFindler(name, nullptr)); + if (ret.second) { + result = CncImgLoadVPLFile(reinterpret_cast(ret.first.data())); + } + return result; +} + +bool VoxelDrawer::LoadVXLFile(const CString& name, const FindFileInMixHandler& mixFindler) +{ + bool result = false; + auto const&& ret = readFile(name, mixFindler(name, nullptr)); + if (ret.second) { + if (CncImgIsVXLLoaded()) { + CncImgClearCurrentVXL(); + } + result = CncImgLoadVXLFile(reinterpret_cast(ret.first.data())); + } + return result; +} + +bool VoxelDrawer::LoadHVAFile(const CString& name, const FindFileInMixHandler& mixFindler) +{ + bool result = false; + auto const&& ret = readFile(name, mixFindler(name, nullptr)); + if (ret.second) { + result = CncImgLoadHVAFile(reinterpret_cast(ret.first.data())); + } + return result; +} + +bool VoxelDrawer::GetImageData(unsigned int nFacing, unsigned char*& pBuffer, int& width, + int& height, int& x, int& y, const int F, const int L, const int H) +{ + const unsigned int nIndex = nFacing * 4; + CncImgPrepareVXLCache(nIndex, F, L, H); + CncImgGetImageFrame(nIndex, &width, &height, &x, &y); + if (width < 0 || height < 0) + return false; + return CncImgGetImageData(nIndex, &pBuffer); +} + +bool VoxelDrawer::GetImageData(unsigned int nFacing, unsigned char*& pBuffer, VoxelRectangle& rect, const int F, const int L, const int H) +{ + return GetImageData(nFacing, pBuffer, rect.W, rect.H, rect.X, rect.Y, F, L, H); +} + +bool VoxelDrawer::IsVPLLoaded() +{ + return CncImgIsVPLLoaded(); +} diff --git a/MissionEditor/VoxelDrawer.h b/MissionEditor/VoxelDrawer.h new file mode 100644 index 0000000..71418ba --- /dev/null +++ b/MissionEditor/VoxelDrawer.h @@ -0,0 +1,27 @@ +#pragma once + +#include +#include + +using HMIXFILE = DWORD; +using FindFileInMixHandler = std::function; + +struct VoxelRectangle +{ + int X, Y, W, H; +}; + +class VoxelDrawer +{ +public: + static void Initalize(); + static void Finalize(); + static bool LoadVPLFile(const CString& name, const FindFileInMixHandler& mixFindler); + static bool LoadVXLFile(const CString& name, const FindFileInMixHandler& mixFindler); + static bool LoadHVAFile(const CString& name, const FindFileInMixHandler& mixFindler); + static bool GetImageData(unsigned int nFacing, unsigned char*& pBuffer, + int& width, int& height, int& x, int& y, const int F = 0, const int L = 0, const int H = 0); + static bool GetImageData(unsigned int nFacing, unsigned char*& pBuffer, + VoxelRectangle& rect, const int F = 0, const int L = 0, const int H = 0); + static bool IsVPLLoaded(); +}; \ No newline at end of file diff --git a/MissionEditorPackLib/MissionEditorPackLib.cpp b/MissionEditorPackLib/MissionEditorPackLib.cpp index f4c0705..1723b0c 100644 --- a/MissionEditorPackLib/MissionEditorPackLib.cpp +++ b/MissionEditorPackLib/MissionEditorPackLib.cpp @@ -349,6 +349,35 @@ namespace FSunPackLib return pDDS->SetColorKey(DDCKEY_SRCBLT, &color_key); } + std::pair LoadCCFile(LPCTSTR filepath, HMIXFILE hMix) + { + MemoryBuffer buffer; + Ccc_file file(true); + + if (hMix != NULL) { + if (file.open(filepath, mixfiles[hMix - 1])) { + return {}; + } + } else { + if (file.open(filepath)) { + return {}; + } + } + + auto const size = file.get_size(); + + if (size < 0) { + return {}; + } + + buffer.resize(size); + + if (file.read(buffer.data(), size)) { + return {}; + } + return { std::move(buffer), true }; + } + BOOL XCC_Initialize(BOOL bLoadFromRegistry) { if (bLoadFromRegistry) diff --git a/MissionEditorPackLib/MissionEditorPackLib.h b/MissionEditorPackLib/MissionEditorPackLib.h index 842bde3..75ebccb 100644 --- a/MissionEditorPackLib/MissionEditorPackLib.h +++ b/MissionEditorPackLib/MissionEditorPackLib.h @@ -45,6 +45,8 @@ class VoxelNormalTables; typedef DWORD HMIXFILE; typedef DWORD HTSPALETTE; +using MemoryBuffer = std::vector; + struct SHPHEADER { __int16 zero;// type @@ -249,6 +251,7 @@ namespace FSunPackLib HRESULT SetColorKey(IDirectDrawSurface4* pDDS, COLORREF rgb); + std::pair LoadCCFile(LPCTSTR name, HMIXFILE hMix); }; #endif \ No newline at end of file