diff --git a/Ballance/BMapInspector/Rule.cpp b/Ballance/BMapInspector/Rule.cpp index f01990e..bd1ce54 100644 --- a/Ballance/BMapInspector/Rule.cpp +++ b/Ballance/BMapInspector/Rule.cpp @@ -29,7 +29,10 @@ namespace BMapInspector::Rule { rules.emplace_back(new YYCRule1()); rules.emplace_back(new YYCRule2()); rules.emplace_back(new YYCRule3()); + rules.emplace_back(new YYCRule4()); rules.emplace_back(new BBugRule1()); + rules.emplace_back(new BBugRule2()); + rules.emplace_back(new BBugRule3()); rules.emplace_back(new ZZQRule1()); rules.emplace_back(new ZZQRule2()); rules.emplace_back(new ZZQRule3()); diff --git a/Ballance/BMapInspector/Rule/BBugRules.cpp b/Ballance/BMapInspector/Rule/BBugRules.cpp index d0100d9..6106fdb 100644 --- a/Ballance/BMapInspector/Rule/BBugRules.cpp +++ b/Ballance/BMapInspector/Rule/BBugRules.cpp @@ -27,4 +27,45 @@ namespace BMapInspector::Rule { #pragma endregion +#pragma region BBug Rule 2 + + constexpr char8_t BBUG2[] = u8"BBUG2"; + + BBugRule2::BBugRule2() : IRule() {} + + BBugRule2::~BBugRule2() {} + + std::u8string_view BBugRule2::GetRuleName() const { + return BBUG2; + } + + void BBugRule2::Check(Reporter::Reporter& reporter, Map::Level& level) const { + if (!level.GetTargetCameras().empty()) { + reporter.WriteInfo(BBUG2, u8"Using camera in map is not suggested."); + } + } + +#pragma endregion + +#pragma region BBug Rule 3 + + constexpr char8_t BBUG3[] = u8"BBUG3"; + + BBugRule3::BBugRule3() : IRule() {} + + BBugRule3::~BBugRule3() {} + + std::u8string_view BBugRule3::GetRuleName() const { + return BBUG3; + } + + void BBugRule3::Check(Reporter::Reporter& reporter, Map::Level& level) const { + // TODO: + // This function is already presented in Ballance Blender Plugin, + // so I don't want write it in there now. + // Write this if I have spare time in future. + } + +#pragma endregion + } // namespace BMapInspector::Rule diff --git a/Ballance/BMapInspector/Rule/BBugRules.hpp b/Ballance/BMapInspector/Rule/BBugRules.hpp index 428298d..8f13d32 100644 --- a/Ballance/BMapInspector/Rule/BBugRules.hpp +++ b/Ballance/BMapInspector/Rule/BBugRules.hpp @@ -19,4 +19,36 @@ namespace BMapInspector::Rule { void Check(Reporter::Reporter& reporter, Map::Level& level) const override; }; + /** + * @brief BBug Rule 2 + * @details + * Using camera in map is not suggested. + */ + class BBugRule2 : public IRule { + public: + BBugRule2(); + virtual ~BBugRule2(); + YYCC_DELETE_COPY_MOVE(BBugRule2) + + public: + std::u8string_view GetRuleName() const override; + void Check(Reporter::Reporter& reporter, Map::Level& level) const override; + }; + + /** + * @brief BBug Rule 3 + * @details + * Check whether the parameters of all materials is same with Ballance vanilla settings. + */ + class BBugRule3 : public IRule { + public: + BBugRule3(); + virtual ~BBugRule3(); + YYCC_DELETE_COPY_MOVE(BBugRule3) + + public: + std::u8string_view GetRuleName() const override; + void Check(Reporter::Reporter& reporter, Map::Level& level) const override; + }; + } diff --git a/Ballance/BMapInspector/Rule/Shared.hpp b/Ballance/BMapInspector/Rule/Shared.hpp index 2b69f15..94d0d08 100644 --- a/Ballance/BMapInspector/Rule/Shared.hpp +++ b/Ballance/BMapInspector/Rule/Shared.hpp @@ -62,8 +62,178 @@ namespace BMapInspector::Rule::Shared { // clang-format off constexpr char8_t RAIL_ENVIRONMENT[] = u8"Rail_Environment.bmp"; constexpr char8_t LATERNE_VERLAUF[] = u8"Laterne_Verlauf.tga"; - // clang-format on + + constexpr std::array OPAQUE_TEXS{ + u8"atari.bmp", + u8"Ball_LightningSphere1.bmp", + u8"Ball_LightningSphere2.bmp", + u8"Ball_LightningSphere3.bmp", + u8"Ball_Paper.bmp", + u8"Ball_Stone.bmp", + u8"Ball_Wood.bmp", + u8"Brick.bmp", + u8"Column_beige.bmp", + u8"Column_blue.bmp", + u8"Dome.bmp", + u8"DomeEnvironment.bmp", + u8"ExtraBall.bmp", + u8"ExtraParticle.bmp", + u8"E_Holzbeschlag.bmp", + u8"FloorGlow.bmp", + u8"Floor_Side.bmp", + u8"Floor_Top_Border.bmp", + u8"Floor_Top_Borderless.bmp", + u8"Floor_Top_Checkpoint.bmp", + u8"Floor_Top_Flat.bmp", + u8"Floor_Top_Profil.bmp", + u8"Floor_Top_ProfilFlat.bmp", + u8"Gravitylogo_intro.bmp", + u8"HardShadow.bmp", + u8"Laterne_Glas.bmp", + u8"Logo.bmp", + u8"Metal_stained.bmp", + u8"Misc_Ufo.bmp", + u8"Misc_UFO_Flash.bmp", + u8"Modul03_Floor.bmp", + u8"Modul03_Wall.bmp", + u8"Modul11_13_Wood.bmp", + u8"Modul11_Wood.bmp", + u8"Modul15.bmp", + u8"Modul16.bmp", + u8"Modul18.bmp", + u8"Modul30_d_Seiten.bmp", + u8"Particle_Flames.bmp", + u8"Particle_Smoke.bmp", + u8"PE_Bal_balloons.bmp", + u8"PE_Bal_platform.bmp", + u8"PE_Ufo_env.bmp", + u8"P_Extra_Life_Oil.bmp", + u8"P_Extra_Life_Particle.bmp", + u8"P_Extra_Life_Shadow.bmp", + u8"Rail_Environment.bmp", + u8"sandsack.bmp", + u8"SkyLayer.bmp", + u8"Sky_Vortex.bmp", + u8"Stick_Stripes.bmp", + u8"Target.bmp", + u8"Tower_Roof.bmp", + u8"Trafo_Environment.bmp", + u8"Trafo_FlashField.bmp", + u8"Wood_Metal.bmp", + u8"Wood_MetalStripes.bmp", + u8"Wood_Misc.bmp", + u8"Wood_Nailed.bmp", + u8"Wood_Old.bmp", + u8"Wood_Panel.bmp", + u8"Wood_Plain.bmp", + u8"Wood_Plain2.bmp", + u8"Wood_Raft.bmp", + }; + constexpr std::array TRANSPARENT_TEXS{ + u8"Button01_deselect.tga", + u8"Button01_select.tga", + u8"Button01_special.tga", + u8"Column_beige_fade.tga", + u8"Cursor.tga", + u8"DomeShadow.tga", + u8"Font_1.tga", + u8"Laterne_Schatten.tga", + u8"Laterne_Verlauf.tga", + u8"Modul18_Gitter.tga", + u8"Pfeil.tga", + u8"Stick_Bottom.tga", + u8"Trafo_Shadow_Big.tga", + u8"Tut_Pfeil01.tga", + u8"Tut_Pfeil_Hoch.tga", + u8"Wolken_intro.tga", + }; + + constexpr std::array ALL{ + // u8"atari.avi", + u8"atari.bmp", + u8"Ball_LightningSphere1.bmp", + u8"Ball_LightningSphere2.bmp", + u8"Ball_LightningSphere3.bmp", + u8"Ball_Paper.bmp", + u8"Ball_Stone.bmp", + u8"Ball_Wood.bmp", + u8"Brick.bmp", + u8"Button01_deselect.tga", + u8"Button01_select.tga", + u8"Button01_special.tga", + u8"Column_beige.bmp", + u8"Column_beige_fade.tga", + u8"Column_blue.bmp", + u8"Cursor.tga", + u8"Dome.bmp", + u8"DomeEnvironment.bmp", + u8"DomeShadow.tga", + u8"ExtraBall.bmp", + u8"ExtraParticle.bmp", + u8"E_Holzbeschlag.bmp", + u8"FloorGlow.bmp", + u8"Floor_Side.bmp", + u8"Floor_Top_Border.bmp", + u8"Floor_Top_Borderless.bmp", + u8"Floor_Top_Checkpoint.bmp", + u8"Floor_Top_Flat.bmp", + u8"Floor_Top_Profil.bmp", + u8"Floor_Top_ProfilFlat.bmp", + u8"Font_1.tga", + u8"Gravitylogo_intro.bmp", + u8"HardShadow.bmp", + u8"Laterne_Glas.bmp", + u8"Laterne_Schatten.tga", + u8"Laterne_Verlauf.tga", + u8"Logo.bmp", + u8"Metal_stained.bmp", + u8"Misc_Ufo.bmp", + u8"Misc_UFO_Flash.bmp", + u8"Modul03_Floor.bmp", + u8"Modul03_Wall.bmp", + u8"Modul11_13_Wood.bmp", + u8"Modul11_Wood.bmp", + u8"Modul15.bmp", + u8"Modul16.bmp", + u8"Modul18.bmp", + u8"Modul18_Gitter.tga", + u8"Modul30_d_Seiten.bmp", + u8"Particle_Flames.bmp", + u8"Particle_Smoke.bmp", + u8"PE_Bal_balloons.bmp", + u8"PE_Bal_platform.bmp", + u8"PE_Ufo_env.bmp", + u8"Pfeil.tga", + u8"P_Extra_Life_Oil.bmp", + u8"P_Extra_Life_Particle.bmp", + u8"P_Extra_Life_Shadow.bmp", + u8"Rail_Environment.bmp", + u8"sandsack.bmp", + u8"SkyLayer.bmp", + u8"Sky_Vortex.bmp", + u8"Stick_Bottom.tga", + u8"Stick_Stripes.bmp", + u8"Target.bmp", + u8"Tower_Roof.bmp", + u8"Trafo_Environment.bmp", + u8"Trafo_FlashField.bmp", + u8"Trafo_Shadow_Big.tga", + u8"Tut_Pfeil01.tga", + u8"Tut_Pfeil_Hoch.tga", + u8"Wolken_intro.tga", + u8"Wood_Metal.bmp", + u8"Wood_MetalStripes.bmp", + u8"Wood_Misc.bmp", + u8"Wood_Nailed.bmp", + u8"Wood_Old.bmp", + u8"Wood_Panel.bmp", + u8"Wood_Plain.bmp", + u8"Wood_Plain2.bmp", + u8"Wood_Raft.bmp", + }; + + // clang-format on } // namespace TextureNames #pragma endregion @@ -173,8 +343,8 @@ namespace BMapInspector::Rule::Shared { return yycc::string::op::join( [&cache, &first, &last]() -> std::optional { if (first == last) return std::nullopt; - // YYC MARK: - // We must use "cache", otherwise "use after free" will occur. + // YYC MARK: + // We must use "cache", otherwise "use after free" will occur. cache = QuoteObjectName(*(first++)); return cache; }, diff --git a/Ballance/BMapInspector/Rule/YYCRules.cpp b/Ballance/BMapInspector/Rule/YYCRules.cpp index 88a01c7..a1b0545 100644 --- a/Ballance/BMapInspector/Rule/YYCRules.cpp +++ b/Ballance/BMapInspector/Rule/YYCRules.cpp @@ -14,6 +14,7 @@ namespace L = LibCmo; namespace C = LibCmo::CK2; namespace V = LibCmo::VxMath; namespace O = LibCmo::CK2::ObjImpls; +namespace strop = yycc::string::op; namespace BMapInspector::Rule { @@ -246,7 +247,7 @@ namespace BMapInspector::Rule { if (filename == nullptr) { combiner.update(nullptr); } else { - auto lower_filename = yycc::string::op::to_lower(filename); + auto lower_filename = strop::to_lower(filename); combiner.update(lower_filename); } combiner.update(texdata.GetSaveOptions()); @@ -628,4 +629,72 @@ namespace BMapInspector::Rule { #pragma endregion +#pragma region YYC Rule 4 + + constexpr char8_t YYC4[] = u8"YYC4"; + + YYCRule4::YYCRule4() : IRule() {} + + YYCRule4::~YYCRule4() {} + + std::u8string_view YYCRule4::GetRuleName() const { + return YYC4; + } + + void YYCRule4::Check(Reporter::Reporter& reporter, Map::Level& level) const { + // Build lowercase texture name set first. + std::set opaque_texs; + for (const auto* tex_name : Shared::TextureNames::OPAQUE_TEXS) { + opaque_texs.emplace(strop::to_lower(tex_name)); + } + std::set transparent_texs; + for (const auto* tex_name : Shared::TextureNames::TRANSPARENT_TEXS) { + transparent_texs.emplace(strop::to_lower(tex_name)); + } + + // Check texture one by one + for (auto& tex : level.GetTextures()) { + auto tex_filename = tex->GetUnderlyingData().GetSlotFileName(0); + if (tex_filename == nullptr) continue; + + auto lower_tex_filename = strop::to_lower(tex_filename); + if (opaque_texs.contains(lower_tex_filename)) { + if (tex->GetVideoFormat() != V::VX_PIXELFORMAT::_16_ARGB1555) { + reporter.FormatWarning( + YYC4, + u8"Texture %s is Ballance opaque texture. But its video format is not ARGB1555. This is mismatched with vanilla Ballance.", + Shared::QuoteObjectName(tex).c_str()); + } + } else if (transparent_texs.contains(lower_tex_filename)) { + if (tex->GetVideoFormat() != V::VX_PIXELFORMAT::_32_ARGB8888) { + reporter.FormatWarning( + YYC4, + u8"Texture %s is Ballance transparent texture. But its video format is not ARGB8888. This is mismatched with vanilla Ballance.", + Shared::QuoteObjectName(tex).c_str()); + } + } else { + switch (tex->GetVideoFormat()) { + case V::VX_PIXELFORMAT::_16_ARGB1555: + // Do nothing. + break; + case V::VX_PIXELFORMAT::_32_ARGB8888: + reporter.FormatWarning( + YYC4, + u8"Texture %s is not Ballance texture. Its video format is ARGB8888. " + "This may cause useless performance consumption if there is no transparent inside it. Please check whether this is essential.", + Shared::QuoteObjectName(tex).c_str()); + break; + default: + reporter.FormatWarning( + YYC4, + u8"Texture %s is not Ballance texture. Its video format is not ARGB1555 or ARGB8888. " + "This is mismatched with vanilla Ballance. Please set it to ARGB1555 for opaque texture, or ARGB8888 for transaprent texture, " + "except special scenario.", + Shared::QuoteObjectName(tex).c_str()); + break; + } + } + } + } + } // namespace BMapInspector::Rule diff --git a/Ballance/BMapInspector/Rule/YYCRules.hpp b/Ballance/BMapInspector/Rule/YYCRules.hpp index d043dbe..28da1b6 100644 --- a/Ballance/BMapInspector/Rule/YYCRules.hpp +++ b/Ballance/BMapInspector/Rule/YYCRules.hpp @@ -53,4 +53,22 @@ namespace BMapInspector::Rule { void Check(Reporter::Reporter& reporter, Map::Level& level) const override; }; + /** + * @brief YYC12345 Rule 4 + * @details + * \li Check the video format for opaque and transparent texture respectively. + * \li Warning for video format which is not used by vanilla Ballance. + * \li Warning for transparent used video format in non-Ballance textures to conserve resources. + */ + class YYCRule4 : public IRule { + public: + YYCRule4(); + virtual ~YYCRule4(); + YYCC_DELETE_COPY_MOVE(YYCRule4) + + public: + std::u8string_view GetRuleName() const override; + void Check(Reporter::Reporter& reporter, Map::Level& level) const override; + }; + }