diff --git a/src/level.cpp b/src/level.cpp index 5be77a8..4daf385 100644 --- a/src/level.cpp +++ b/src/level.cpp @@ -502,6 +502,11 @@ bool Level::LoadPreset(const std::filesystem::path& filename) m_propVisTreeTransparent.SetPreview(material, json[material + "_visTreeTransparent"]); m_propVisTreeTransparent.Apply(material, m_materialToQuadblocks[material], m_quadblocks); } + if (json.contains(material + "_drawOrderHigh")) + { + m_propDrawOrderHigh.SetPreview(material, json[material + "_drawOrderHigh"]); + m_propDrawOrderHigh.Apply(material, m_materialToQuadblocks[material], m_quadblocks); + } } } } @@ -606,6 +611,7 @@ bool Level::SavePreset(const std::filesystem::path& path) materialJson[key + "_visTreeTransparent"] = m_propVisTreeTransparent.GetBackup(key); materialJson[key + "_trigger"] = m_propTurboPads.GetBackup(key); materialJson[key + "_speedImpact"] = m_propSpeedImpact.GetBackup(key); + materialJson[key + "_drawOrderHigh"] = m_propDrawOrderHigh.GetBackup(key); } materialJson["materials"] = materials; SaveJSON(dirPath / "material.json", materialJson); @@ -688,6 +694,7 @@ void Level::ManageTurbopad(Quadblock& quadblock) turboPad.SetTurboPadIndex(TURBO_PAD_INDEX_NONE); turboPad.SetHide(true); turboPad.SetAnimated(false); + turboPad.SetDrawOrderHigh(0); size_t index = m_quadblocks.size(); turboPadIndex = quadblock.GetTurboPadIndex(); @@ -1617,6 +1624,7 @@ bool Level::LoadOBJ(const std::filesystem::path& objFile) m_propTurboPads.SetDefaultValue(material, QuadblockTrigger::NONE); m_propCheckpointPathable.SetDefaultValue(material, true); m_propVisTreeTransparent.SetDefaultValue(material, false); + m_propDrawOrderHigh.SetDefaultValue(material, static_cast(0)); m_propTerrain.RegisterMaterial(this); m_propQuadFlags.RegisterMaterial(this); m_propDoubleSided.RegisterMaterial(this); @@ -1625,6 +1633,7 @@ bool Level::LoadOBJ(const std::filesystem::path& objFile) m_propSpeedImpact.RegisterMaterial(this); m_propCheckpointPathable.RegisterMaterial(this); m_propVisTreeTransparent.RegisterMaterial(this); + m_propDrawOrderHigh.RegisterMaterial(this); } } bool sameUVs = true; diff --git a/src/level.h b/src/level.h index bf98ad3..3ae0421 100644 --- a/src/level.h +++ b/src/level.h @@ -144,6 +144,7 @@ class Level MaterialProperty m_propSpeedImpact; MaterialProperty m_propCheckpointPathable; MaterialProperty m_propVisTreeTransparent; + MaterialProperty m_propDrawOrderHigh; std::array m_models; diff --git a/src/levelui.cpp b/src/levelui.cpp index 177c684..9b73f71 100644 --- a/src/levelui.cpp +++ b/src/levelui.cpp @@ -233,18 +233,27 @@ bool MaterialProperty::RenderUI(const std::string& material, const std::ve } else if constexpr (M == MaterialType::DRAW_FLAGS) { - if (ImGui::TreeNode("Draw Flags")) + T& preview = GetPreview(material); + ImGui::Checkbox("Double Sided", &preview); + ImGui::SameLine(); + static ButtonUI drawFlagsApplyButton = ButtonUI(); + if (drawFlagsApplyButton.Show(("Apply##drawflags" + material).c_str(), "Draw flags successfully updated.", UnsavedChanges(material))) { - T& preview = GetPreview(material); - ImGui::Checkbox("Double Sided", &preview); - - static ButtonUI drawFlagsApplyButton = ButtonUI(); - if (drawFlagsApplyButton.Show(("Apply##drawflags" + material).c_str(), "Draw flags successfully updated.", UnsavedChanges(material))) - { - Apply(material, quadblockIndexes, quadblocks); - return true; - } - ImGui::TreePop(); + Apply(material, quadblockIndexes, quadblocks); + return true; + } + } + else if constexpr (M == MaterialType::DRAW_ORDER_HIGH) + { + T& preview = GetPreview(material); + ImGui::Text("Z depth bias:"); ImGui::SameLine(); + if (ImGui::InputInt("##draworderHigh", &preview)) { preview = Clamp(preview, static_cast(INT8_MIN), static_cast(INT8_MAX)); } + ImGui::SameLine(); + static ButtonUI drawOrderHighButton = ButtonUI(); + if (drawOrderHighButton.Show(("Apply##draworderHigh" + material).c_str(), "Draw Order High successfully updated.", UnsavedChanges(material))) + { + Apply(material, quadblockIndexes, quadblocks); + return true; } } else if constexpr (M == MaterialType::CHECKPOINT) @@ -549,7 +558,13 @@ void Level::RenderUI(Renderer& renderer) m_propTerrain.RenderUI(material, quadblockIndexes, m_quadblocks); m_propQuadFlags.RenderUI(material, quadblockIndexes, m_quadblocks); - m_propDoubleSided.RenderUI(material, quadblockIndexes, m_quadblocks); + if (ImGui::TreeNode("Draw Flags")) + { + m_propDoubleSided.RenderUI(material, quadblockIndexes, m_quadblocks); + m_propDrawOrderHigh.RenderUI(material, quadblockIndexes, m_quadblocks); + ImGui::TreePop(); + } + m_propCheckpoints.RenderUI(material, quadblockIndexes, m_quadblocks); m_propCheckpointPathable.RenderUI(material, quadblockIndexes, m_quadblocks); m_propVisTreeTransparent.RenderUI(material, quadblockIndexes, m_quadblocks); @@ -1415,6 +1430,9 @@ bool Quadblock::RenderUI(size_t checkpointCount, bool& resetBsp) if (ImGui::TreeNode("Draw Flags")) { ImGui::Checkbox("Double Sided", &m_doubleSided); + ImGui::Text("Z depth bias:"); + ImGui::SameLine(); + if (ImGui::InputInt("##draworderHigh", &m_drawOrderHigh)) { m_drawOrderHigh = Clamp(m_drawOrderHigh, static_cast(INT8_MIN), static_cast(INT8_MAX)); } const std::vector s_rotateFlip = {"None", "Rotate 90", "Rotate 180", "Rotate -90", "Flip + Rotate 90", "Flip + Rotate 180", "Flip + Rotate -90", "Flip"}; const std::vector s_faceDrawMode = {"Both", "Left", "Right", "None"}; diff --git a/src/material.cpp b/src/material.cpp index c800a15..a5e8ce9 100644 --- a/src/material.cpp +++ b/src/material.cpp @@ -12,6 +12,7 @@ template class MaterialProperty; template class MaterialProperty; template class MaterialProperty; template class MaterialProperty; +template class MaterialProperty; static std::unordered_map> g_materials; @@ -119,6 +120,7 @@ void MaterialProperty::Apply(const std::string& material, const std::vecto else if constexpr (M == MaterialType::SPEED_IMPACT) { quadblock.SetSpeedImpact(preview); } else if constexpr (M == MaterialType::CHECKPOINT_PATHABLE) { quadblock.SetCheckpointPathable(preview); } else if constexpr (M == MaterialType::VISTREE_TRANSPARENT) { quadblock.SetVisTreeTransparent(preview); } + else if constexpr (M == MaterialType::DRAW_ORDER_HIGH) { quadblock.SetDrawOrderHigh(preview); } } } m_backup[material] = preview; diff --git a/src/material.h b/src/material.h index 2f15005..066dd27 100644 --- a/src/material.h +++ b/src/material.h @@ -8,7 +8,7 @@ enum class MaterialType { - TERRAIN, QUAD_FLAGS, DRAW_FLAGS, CHECKPOINT, TURBO_PAD, SPEED_IMPACT, CHECKPOINT_PATHABLE, VISTREE_TRANSPARENT + TERRAIN, QUAD_FLAGS, DRAW_FLAGS, CHECKPOINT, TURBO_PAD, SPEED_IMPACT, CHECKPOINT_PATHABLE, VISTREE_TRANSPARENT, DRAW_ORDER_HIGH }; class MaterialBase diff --git a/src/psx_types.h b/src/psx_types.h index 8988f4e..185c639 100644 --- a/src/psx_types.h +++ b/src/psx_types.h @@ -251,7 +251,7 @@ namespace PSX uint16_t index[NUM_VERTICES_QUADBLOCK]; // 0x0 uint16_t flags; // 0x12 uint32_t drawOrderLow; // 0x14 - uint32_t drawOrderHigh; // 0x18 + int8_t drawOrderHigh[4]; // 0x18 uint32_t offMidTextures[4]; // 0x1C PSX::BoundingBox bbox; // 0x2C uint8_t terrain; // 0x38 diff --git a/src/quadblock.cpp b/src/quadblock.cpp index d6c7df9..69d7996 100644 --- a/src/quadblock.cpp +++ b/src/quadblock.cpp @@ -409,6 +409,7 @@ Quadblock::Quadblock(const PSX::Quadblock& quadblock, const std::vector> (8 + i * 5)) & 0b11111; m_faceRotateFlip[i] = packedFace & 0b111; m_faceDrawMode[i] = (packedFace >> 3) & 0b11; + if (quadblock.drawOrderHigh[i] != 0) { m_drawOrderHigh = static_cast(quadblock.drawOrderHigh[i]); } } m_terrain = quadblock.terrain; m_checkpointIndex = quadblock.checkpointIndex; @@ -561,6 +562,11 @@ bool Quadblock::GetVisTreeTransparent() const return m_visTreeTransparent; } +int Quadblock::GetDrawOrderHigh() const +{ + return m_drawOrderHigh; +} + const QuadUV& Quadblock::GetQuadUV(size_t quad) const { return m_uvs[quad]; @@ -631,6 +637,11 @@ void Quadblock::SetVisTreeTransparent(bool transparent) m_visTreeTransparent = transparent; } +void Quadblock::SetDrawOrderHigh(int drawOrderHigh) +{ + m_drawOrderHigh = drawOrderHigh; +} + void Quadblock::SetName(const std::string& name) { m_name = name; @@ -837,8 +848,8 @@ std::vector Quadblock::Serialize(size_t id, size_t offTextures, const s { uint32_t packedFace = m_faceRotateFlip[i] | (m_faceDrawMode[i] << 3); quadblock.drawOrderLow |= packedFace << (8 + i * 5); + quadblock.drawOrderHigh[i] = static_cast(m_drawOrderHigh); } - quadblock.drawOrderHigh = 0; if (m_animated) { quadblock.offMidTextures[0] = static_cast(m_animTexOffset[0] | 1); @@ -902,6 +913,7 @@ void Quadblock::SetDefaultValues() m_checkpointPathable = true; m_checkpointStatus = false; m_visTreeTransparent = false; + m_drawOrderHigh = 0x0; m_trigger = QuadblockTrigger::NONE; m_turboPadIndex = TURBO_PAD_INDEX_NONE; m_hide = false; diff --git a/src/quadblock.h b/src/quadblock.h index 805938a..f6029c6 100644 --- a/src/quadblock.h +++ b/src/quadblock.h @@ -133,6 +133,7 @@ class Quadblock bool GetCheckpointStatus() const; bool GetCheckpointPathable() const; bool GetVisTreeTransparent() const; + int GetDrawOrderHigh() const; const QuadUV& GetQuadUV(size_t quad) const; const std::filesystem::path& GetTexPath() const; const std::array& GetUVs() const; @@ -147,6 +148,7 @@ class Quadblock void SetCheckpointStatus(bool active); void SetCheckpointPathable(bool pathable); void SetVisTreeTransparent(bool transparent); + void SetDrawOrderHigh(int drawOrderHigh); void SetName(const std::string& name); void SetTurboPadIndex(size_t index); void SetHide(bool active); @@ -189,6 +191,7 @@ class Quadblock bool m_checkpointPathable; bool m_checkpointStatus; bool m_visTreeTransparent; + int m_drawOrderHigh; bool m_hide; Vertex m_p[NUM_VERTICES_QUADBLOCK]; BoundingBox m_bbox;