diff --git a/resources/shaders/CollisionShader.ps b/resources/shaders/CollisionShader.ps index fafa23e6..138164de 100644 --- a/resources/shaders/CollisionShader.ps +++ b/resources/shaders/CollisionShader.ps @@ -1,17 +1,33 @@ #version 330 core // Input -in vec2 TexCoord; +in vec4 LightColor; // Output out vec4 PixelColor; // Uniforms -uniform sampler2D Texture; uniform vec4 TintColor; +// Functions +float InterpolateDecelerate(float Min, float Max, float t, float Factor) +{ + float Alpha = (1.0 - pow(1.0 - t, Factor)); + return mix(Min, Max, Alpha); +} + // Main void main() { - PixelColor = vec4(texture(Texture, TexCoord).rgb, 0) * TintColor; + const float kMaxDepth = 75.0; // Controls the max depth range that kDepthTintNear and kDepthTintFar are interpolated between + const float kDepthTintNear = 0.0; // Sets the pixel color offset for pixels close to the screen + const float kDepthTintFar = -0.2; // Sets the pixel color offset for pixels far from the screen + const float kDepthCurveFactor = 2; // Controls the strength of the interpolation curve (higher = color chabges faster from up close and slower from further away) + + // Apply some fake fog so pixels closer to the camera appear slightly brighter + float Depth = ( (2.0 * gl_FragCoord.z - gl_DepthRange.near - gl_DepthRange.far) / (gl_DepthRange.far - gl_DepthRange.near) ) / gl_FragCoord.w; + float DepthAlpha = min(Depth, kMaxDepth) / kMaxDepth; + DepthAlpha = clamp(DepthAlpha, 0.0, 1.0); + float DepthTint = InterpolateDecelerate(kDepthTintNear, kDepthTintFar, DepthAlpha, kDepthCurveFactor); + PixelColor = (LightColor + vec4(DepthTint, DepthTint, DepthTint, 1.0)) * TintColor; } diff --git a/resources/shaders/CollisionShader.vs b/resources/shaders/CollisionShader.vs index cbb5419c..92ac2424 100644 --- a/resources/shaders/CollisionShader.vs +++ b/resources/shaders/CollisionShader.vs @@ -1,11 +1,11 @@ -// This shader will be obsoleted soon when the collision rendering is improved #version 330 core // Input -layout(location = 0) in vec3 Position; +layout(location = 0) in vec3 RawPosition; +layout(location = 1) in vec3 RawNormal; // Output -out vec2 TexCoord; +out vec4 LightColor; // Uniforms layout(std140) uniform MVPBlock @@ -15,14 +15,28 @@ layout(std140) uniform MVPBlock mat4 ProjMtx; }; +uniform bool IsFloor; +uniform bool IsUnstandable; + // Main void main() { - mat4 MVP = ModelMtx * ViewMtx * ProjMtx; - gl_Position = vec4(Position, 1) * MVP; + const vec3 kLightDir = normalize( vec3(0.3, 0, -1) ); // Sets the direction of the light + const float kLightColorMin = 0.5; // Sets the minimum light color (color of a vertex facing away from the light) + const float kLightColorMax = 0.9; // Sets the maximum light color (color of a vertex facing towards the light) - // UV Generation - float avg = (Position.x + Position.z) / 2; - TexCoord.x = avg; - TexCoord.y = Position.y + (avg / 2); + // Calculate vertex position + mat4 MVP = ModelMtx * ViewMtx * ProjMtx; + gl_Position = vec4(RawPosition, 1) * MVP; + + // Apply some simple lighting + float LightDot = dot(RawNormal, kLightDir); + float Alpha = (-LightDot + 1.0) / 2; + float LightAlpha = mix(kLightColorMin, kLightColorMax, Alpha); + LightColor = vec4(LightAlpha, LightAlpha, LightAlpha, 1.0); + + // If this is not a floor, make the surface significantly darker + // The surface is considered a floor if IsFloor is true OR if the floor normal Z is greater than 0.85 + float FloorMul = (!IsUnstandable && (IsFloor || RawNormal.z > 0.85)) ? 1.0 : 0.5; + LightColor *= FloorMul; } diff --git a/src/.qmake.conf b/src/.qmake.conf index 4e9eebf4..a8bc5fb1 100644 --- a/src/.qmake.conf +++ b/src/.qmake.conf @@ -5,7 +5,7 @@ EXTERNALS_DIR = $$PWD/../externals PWE_MAIN_INCLUDE = $$PWD DEFINES += 'APP_NAME=\"\\\"Prime World Editor\\\"\"' \ - 'APP_VERSION=\"\\\"1.1.0\\\"\"' + 'APP_VERSION=\"\\\"1.1.1\\\"\"' PUBLIC_RELEASE { DEFINES += 'PUBLIC_RELEASE=1' \ diff --git a/src/Common/TString.h b/src/Common/TString.h index 51a26037..6858504e 100644 --- a/src/Common/TString.h +++ b/src/Common/TString.h @@ -409,12 +409,22 @@ public: inline u32 ToInt32(int Base = 16) const { - return std::stoul(mInternalString, nullptr, Base); + try { + return std::stoul(mInternalString, nullptr, Base); + } + catch(...) { + return 0; + } } inline u64 ToInt64(int Base = 16) const { - return std::stoull(mInternalString, nullptr, Base); + try { + return std::stoull(mInternalString, nullptr, Base); + } + catch(...) { + return 0; + } } void ToInt128(CharType* pOut, int Base = 16) const @@ -531,6 +541,10 @@ public: if (HasPrefix) Str = Str.ChopFront(2); + // If the string is empty other than the prefix, then this is not a valid hex string + if (Str.IsEmpty()) + return false; + // If we have a variable width then assign the width value to the string size Width = Str.Size(); } diff --git a/src/Core/Core.pro b/src/Core/Core.pro index 732236a4..7b0a6733 100644 --- a/src/Core/Core.pro +++ b/src/Core/Core.pro @@ -183,6 +183,7 @@ HEADERS += \ Render/EDepthGroup.h \ Scene/CScriptAttachNode.h \ ScriptExtra/CSandwormExtra.h \ + Resource/CCollisionMaterial.h \ GameProject/CGameProject.h \ GameProject/CPackage.h \ GameProject/CGameExporter.h \ @@ -298,6 +299,7 @@ SOURCES += \ Resource/Model/EVertexAttribute.cpp \ Scene/CScriptAttachNode.cpp \ ScriptExtra/CSandwormExtra.cpp \ + Resource/CCollisionMaterial.cpp \ GameProject/CGameProject.cpp \ GameProject/CGameExporter.cpp \ GameProject/CResourceStore.cpp \ diff --git a/src/Core/Render/CDrawUtil.cpp b/src/Core/Render/CDrawUtil.cpp index 2f97d64f..aafc8135 100644 --- a/src/Core/Render/CDrawUtil.cpp +++ b/src/Core/Render/CDrawUtil.cpp @@ -329,15 +329,23 @@ void CDrawUtil::UseTextureShader(const CColor& TintColor) CMaterial::KillCachedMaterial(); } -void CDrawUtil::UseCollisionShader(const CColor& TintColor /*= CColor::skWhite*/) +void CDrawUtil::UseCollisionShader(bool IsFloor, bool IsUnstandable, const CColor& TintColor /*= CColor::skWhite*/) { Init(); mpCollisionShader->SetCurrent(); - LoadCheckerboardTexture(0); + + // Force blend mode to opaque + set alpha to 0 to ensure collision geometry isn't bloomed + glBlendFuncSeparate(GL_ONE, GL_ZERO, GL_ZERO, GL_ZERO); static GLuint TintColorLoc = mpCollisionShader->GetUniformLocation("TintColor"); glUniform4f(TintColorLoc, TintColor.R, TintColor.G, TintColor.B, TintColor.A); + static GLuint IsFloorLoc = mpCollisionShader->GetUniformLocation("IsFloor"); + glUniform1i(IsFloorLoc, IsFloor ? 1 : 0); + + static GLuint IsUnstandableLoc = mpCollisionShader->GetUniformLocation("IsUnstandable"); + glUniform1i(IsUnstandableLoc, IsUnstandable ? 1 : 0); + CMaterial::KillCachedMaterial(); } diff --git a/src/Core/Render/CDrawUtil.h b/src/Core/Render/CDrawUtil.h index 6fe5ba3d..13014945 100644 --- a/src/Core/Render/CDrawUtil.h +++ b/src/Core/Render/CDrawUtil.h @@ -89,7 +89,7 @@ public: static void UseColorShaderLighting(const CColor& Color); static void UseTextureShader(); static void UseTextureShader(const CColor& TintColor); - static void UseCollisionShader(const CColor& TintColor = CColor::skWhite); + static void UseCollisionShader(bool IsFloor, bool IsUnstandable, const CColor& TintColor = CColor::skWhite); static CShader* GetTextShader(); static void LoadCheckerboardTexture(u32 GLTextureUnit); diff --git a/src/Core/Render/SViewInfo.h b/src/Core/Render/SViewInfo.h index 4607b417..2c75e3d0 100644 --- a/src/Core/Render/SViewInfo.h +++ b/src/Core/Render/SViewInfo.h @@ -1,11 +1,34 @@ #ifndef SVIEWINFO #define SVIEWINFO +#include "Core/Resource/CCollisionMaterial.h" #include "Core/Scene/FShowFlags.h" #include #include #include +struct SCollisionRenderSettings +{ + u64 HighlightMask; + u64 HideMask; + + CCollisionMaterial HideMaterial; + bool DrawWireframe; + bool DrawBackfaces; + bool DrawAreaCollisionBounds; + bool TintWithSurfaceColor; + bool TintUnwalkableTris; + + SCollisionRenderSettings() + : HighlightMask(0) + , HideMask(0) + , DrawWireframe(true) + , DrawBackfaces(false) + , DrawAreaCollisionBounds(true) + , TintWithSurfaceColor(true) + , TintUnwalkableTris(true) {} +}; + struct SViewInfo { class CScene *pScene; @@ -14,6 +37,7 @@ struct SViewInfo bool GameMode; FShowFlags ShowFlags; + SCollisionRenderSettings CollisionSettings; CFrustumPlanes ViewFrustum; CMatrix4f RotationOnlyViewMatrix; }; diff --git a/src/Core/Resource/CCollisionMaterial.cpp b/src/Core/Resource/CCollisionMaterial.cpp new file mode 100644 index 00000000..a76a9aac --- /dev/null +++ b/src/Core/Resource/CCollisionMaterial.cpp @@ -0,0 +1,83 @@ +#include "CCollisionMaterial.h" +#include +#include + +ECollisionFlag CCollisionMaterial::SurfaceType(EGame Game) const +{ + // Arrays determining the type hierarchy for each game. + // Flags earlier in the list take priority over flags later in the list. + static const ECollisionFlag skPrimeTypeHierarchy[] = { + eCF_Organic, eCF_Wood, eCF_Sand, eCF_Shield, eCF_Glass, eCF_Mud, eCF_SlowMud, + eCF_Snow, eCF_Lava, eCF_Dirt, eCF_Phazon, eCF_MetalGrating, eCF_Ice, eCF_Grass, + eCF_Metal, eCF_Stone + }; + static const ECollisionFlag skEchoesTypeHierarchy[] = { + eCF_Rubber, eCF_Organic, eCF_Wood, eCF_Web, eCF_MothSeedOrganics, eCF_Sand, + eCF_Shield, eCF_Fabric, eCF_Snow, eCF_Glass, eCF_AltMetal, eCF_Dirt, eCF_Phazon, + eCF_MetalGrating, eCF_Ice, eCF_Grass, eCF_Metal, eCF_Stone + }; + + // Determine which list we should use. + const ECollisionFlag* pkFlagArray; + u32 Num; + + if (Game <= ePrime) + { + pkFlagArray = skPrimeTypeHierarchy; + Num = sizeof(skPrimeTypeHierarchy) / sizeof(ECollisionFlag); + } + else + { + pkFlagArray = skEchoesTypeHierarchy; + Num = sizeof(skEchoesTypeHierarchy) / sizeof(ECollisionFlag); + } + + // Locate type. + for (u32 iType = 0; iType < Num; iType++) + { + if (*this & pkFlagArray[iType]) + return pkFlagArray[iType]; + } + return eCF_Unknown; +} + +// Type-to-color mappings +const std::unordered_map gkTypeToColor = { + { eCF_Stone, CColor::Integral(220, 215, 160) }, // Brownish/greenish + { eCF_Metal, CColor::Integral(143, 143, 143) }, // Gray + { eCF_Grass, CColor::Integral( 90, 150, 70) }, // Green + { eCF_Ice, CColor::Integral(200, 255, 255) }, // Light blue + { eCF_MetalGrating, CColor::Integral(180, 180, 180) }, // Gray + { eCF_Phazon, CColor::Integral( 0, 128, 255) }, // Blue + { eCF_Dirt, CColor::Integral(107, 84, 40) }, // Brown + { eCF_Lava, CColor::Integral(200, 30, 30) }, // Red + { eCF_AltMetal, CColor::Integral(100, 100, 100) }, // Gray + { eCF_Snow, CColor::Integral(230, 255, 255) }, // *Very* light blue + { eCF_Fabric, CColor::Integral( 64, 133, 236) }, // Blue + { eCF_SlowMud, CColor::Integral(109, 91, 66) }, // Brown + { eCF_Mud, CColor::Integral(121, 106, 84) }, // Brown + { eCF_Glass, CColor::Integral(172, 209, 254) }, // Greenish blue + { eCF_Shield, CColor::Integral(230, 250, 60) }, // Yellow + { eCF_Sand, CColor::Integral(225, 188, 133) }, // Light brown + { eCF_MothSeedOrganics, CColor::Integral(172, 170, 202) }, // Light purple + { eCF_Web, CColor::Integral(191, 176, 162) }, // Light grayish/brown + { eCF_Wood, CColor::Integral(139, 90, 43) }, // Brown + { eCF_Organic, CColor::Integral(130, 130, 250) }, // Purple + { eCF_Rubber, CColor::Integral( 58, 58, 58) } // Black +}; +CColor CCollisionMaterial::SurfaceColor(EGame Game) const +{ + ECollisionFlag SurfType = SurfaceType(Game); + auto FindColor = gkTypeToColor.find(SurfType); + return (FindColor == gkTypeToColor.end() ? CColor::skWhite : FindColor->second); +} + +bool CCollisionMaterial::IsFloor() const +{ + return HasFlag(eCF_Floor) && !HasFlag(eCF_JumpNotAllowed); +} + +bool CCollisionMaterial::IsUnstandable(EGame Game) const +{ + return HasFlag(eCF_JumpNotAllowed) || (Game >= eEchoesDemo && !HasFlag(eCF_Floor) && HasAnyFlags(eCF_Wall | eCF_Ceiling)); +} diff --git a/src/Core/Resource/CCollisionMaterial.h b/src/Core/Resource/CCollisionMaterial.h new file mode 100644 index 00000000..021fdf8c --- /dev/null +++ b/src/Core/Resource/CCollisionMaterial.h @@ -0,0 +1,66 @@ +#ifndef CCOLLISIONMATERIAL +#define CCOLLISIONMATERIAL + +#include +#include +#include + +// Game-neutral collision property flags. +// IMPORTANT: This is an incomplete list. Keep in mind that MP2, MP3, and DKCR store +// collision materials via a 64-bit flag where every bit is used, and some flags differ +// between games. Therefore a single enum doesn't have the resolution to represent EVERY +// flag from EVERY game. In the future, the storage medium needs to be changed to a struct, +// OR we need to be okay with excluding certain flags (which we probably are, because a +// lot of them aren't meant to be used by collision geometry, such as the "Player" flag). +enum ECollisionFlag +{ + eCF_Unknown = 0x00000001, + eCF_Stone = 0x00000002, + eCF_Metal = 0x00000004, + eCF_Grass = 0x00000008, + eCF_Ice = 0x00000010, + eCF_MetalGrating = 0x00000020, + eCF_Phazon = 0x00000040, + eCF_Dirt = 0x00000080, + eCF_Lava = 0x00000100, + eCF_AltMetal = 0x00000200, + eCF_Snow = 0x00000400, + eCF_Fabric = 0x00000800, + eCF_SlowMud = 0x00001000, + eCF_Mud = 0x00002000, + eCF_Glass = 0x00004000, + eCF_Shield = 0x00008000, + eCF_Sand = 0x00010000, + eCF_MothSeedOrganics = 0x00020000, + eCF_Web = 0x00040000, + eCF_Wood = 0x00080000, + eCF_Organic = 0x00100000, + eCF_Rubber = 0x00200000, + eCF_ShootThru = 0x00400000, + eCF_CameraThru = 0x00800000, + eCF_ScanThru = 0x01000000, + eCF_AiWalkThru = 0x02000000, + eCF_FlippedTri = 0x04000000, + eCF_Ceiling = 0x08000000, + eCF_Wall = 0x10000000, + eCF_Floor = 0x20000000, + eCF_AiBlock = 0x40000000, + eCF_JumpNotAllowed = 0x80000000 +}; + +class CCollisionMaterial : public TFlags +{ + friend class CCollisionLoader; + u64 mRawFlags; + +public: + ECollisionFlag SurfaceType(EGame Game) const; + CColor SurfaceColor(EGame Game) const; + bool IsFloor() const; + bool IsUnstandable(EGame Game) const; + + inline u64 RawFlags() const { return mRawFlags; } +}; + +#endif // CCOLLISIONMATERIAL + diff --git a/src/Core/Resource/CCollisionMesh.cpp b/src/Core/Resource/CCollisionMesh.cpp index ee8f9187..b5744919 100644 --- a/src/Core/Resource/CCollisionMesh.cpp +++ b/src/Core/Resource/CCollisionMesh.cpp @@ -1,10 +1,11 @@ #include "CCollisionMesh.h" #include "Core/Render/CRenderer.h" #include "Core/Render/CDrawUtil.h" +#include CCollisionMesh::CCollisionMesh() { - mVBO.SetVertexDesc(ePosition); + mVBO.SetVertexDesc(ePosition | eNormal); mVertexCount = 0; mLineCount = 0; mFaceCount = 0; @@ -31,23 +32,39 @@ void CCollisionMesh::BufferGL() mBuffered = false; } - // Add all the verts to our VBO, first... - mVBO.Reserve(mCollisionVertices.size()); - for (u16 iVtx = 0; iVtx < mCollisionVertices.size(); iVtx++) - mVBO.AddVertex(CVertex(mCollisionVertices[iVtx].Pos)); + // Create new list of collision faces sorted by material index + std::vector SortedTris = mCollisionFaces; + std::sort(SortedTris.begin(), SortedTris.end(), [](CCollisionFace& rLeft, CCollisionFace& rRight) -> bool { + return rLeft.MaterialIdx < rRight.MaterialIdx; + }); - // Then add all the relevant indices to the IBO - mIBO.Reserve(mCollisionFaces.size() * 3); - for (u32 iVtx = 0; iVtx < mCollisionFaces.size(); iVtx++) + // Add all the relevant indices to the IBO + mVBO.Reserve(SortedTris.size() * 3); + mIBO.Reserve(SortedTris.size() * 3); + + mMaterialOffsets.reserve(mMaterials.size()); + u32 CurMat = 0; + + for (u32 iTri = 0; iTri < SortedTris.size(); iTri++) { u16 Verts[3]; - CCollisionFace *pFace = &mCollisionFaces[iVtx]; + CCollisionFace *pFace = &SortedTris[iTri]; CCollisionLine *pLineA = GetLine(pFace->Lines[0]); CCollisionLine *pLineB = GetLine(pFace->Lines[1]); Verts[0] = pLineA->Vertices[0]; Verts[1] = pLineA->Vertices[1]; + // Check if we've reached a new material + if (pFace->MaterialIdx != CurMat) + { + while (CurMat != pFace->MaterialIdx) + { + mMaterialOffsets.push_back(mIBO.GetSize()); + CurMat++; + } + } + // We have two vertex indices; the last one is one of the ones on line B, but we're not sure which one if ((pLineB->Vertices[0] != Verts[0]) && (pLineB->Vertices[0] != Verts[1])) @@ -56,17 +73,40 @@ void CCollisionMesh::BufferGL() Verts[2] = pLineB->Vertices[1]; // Some faces have a property that indicates they need to be inverted - if (!pFace->Properties.Invert) - mIBO.AddIndices(&Verts[0], 3); - - else + if (GetMaterial(pFace->MaterialIdx) & eCF_FlippedTri) { - mIBO.AddIndex(Verts[2]); - mIBO.AddIndex(Verts[1]); - mIBO.AddIndex(Verts[0]); + u16 V0 = Verts[0]; + Verts[0] = Verts[2]; + Verts[2] = V0; + } + + // Generate vertices - we don't share vertices between triangles in order to get the generated normals looking correct + CCollisionVertex& rVert0 = mCollisionVertices[Verts[0]]; + CCollisionVertex& rVert1 = mCollisionVertices[Verts[1]]; + CCollisionVertex& rVert2 = mCollisionVertices[Verts[2]]; + + CVector3f V0toV1 = (rVert1.Pos - rVert0.Pos).Normalized(); + CVector3f V0toV2 = (rVert2.Pos - rVert0.Pos).Normalized(); + CVector3f FaceNormal = V0toV1.Cross(V0toV2).Normalized(); + + for (u32 iVtx = 0; iVtx < 3; iVtx++) + { + CVertex Vtx; + Vtx.Position = mCollisionVertices[ Verts[iVtx] ].Pos; + Vtx.Normal = FaceNormal; + u16 Index = mVBO.AddVertex(Vtx); + mIBO.AddIndex(Index); } } + while (CurMat != mMaterials.size()) + { + mMaterialOffsets.push_back(mIBO.GetSize()); + CurMat++; + } + + ASSERT(mMaterialOffsets.size() == mMaterials.size()); + // Buffer, and done mVBO.Buffer(); mIBO.Buffer(); @@ -82,6 +122,29 @@ void CCollisionMesh::Draw() mVBO.Unbind(); } +void CCollisionMesh::DrawMaterial(u32 MatIdx, bool Wireframe) +{ + if (!mBuffered) BufferGL(); + ASSERT(MatIdx < mMaterials.size()); + + mVBO.Bind(); + u32 StartIdx = (MatIdx == 0 ? 0 : mMaterialOffsets[MatIdx - 1]); + u32 NumElements = mMaterialOffsets[MatIdx] - StartIdx; + + if (Wireframe) + { + CDrawUtil::UseColorShader(CColor::skBlack); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + } + + mIBO.DrawElements(StartIdx, NumElements); + + if (Wireframe) + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + + mVBO.Unbind(); +} + void CCollisionMesh::DrawWireframe() { CDrawUtil::UseColorShader(CColor::skBlack); diff --git a/src/Core/Resource/CCollisionMesh.h b/src/Core/Resource/CCollisionMesh.h index e29710e2..bd9bbe59 100644 --- a/src/Core/Resource/CCollisionMesh.h +++ b/src/Core/Resource/CCollisionMesh.h @@ -1,6 +1,7 @@ #ifndef CCOLLISIONMESH_H #define CCOLLISIONMESH_H +#include "CCollisionMaterial.h" #include "CResource.h" #include "Core/OpenGL/CVertexBuffer.h" #include "Core/OpenGL/CIndexBuffer.h" @@ -30,30 +31,24 @@ class CCollisionMesh SOctreeNode* mpRoot; }; - struct SCollisionProperties - { - // todo: figure out what the other properties are - bool Invert; - }; - class CCollisionVertex { public: - SCollisionProperties Properties; + u32 MaterialIdx; CVector3f Pos; }; class CCollisionLine { public: - SCollisionProperties Properties; + u32 MaterialIdx; u16 Vertices[2]; }; class CCollisionFace { public: - SCollisionProperties Properties; + u32 MaterialIdx; u16 Lines[3]; }; @@ -66,10 +61,11 @@ class CCollisionMesh CAABox mAABox; CCollisionOctree *mpOctree; - std::vector mFlags; + std::vector mMaterials; std::vector mCollisionVertices; std::vector mCollisionLines; std::vector mCollisionFaces; + std::vector mMaterialOffsets; bool mOctreeLoaded; CCollisionVertex *GetVertex(u16 Index); @@ -82,7 +78,12 @@ public: void BufferGL(); void Draw(); + void DrawMaterial(u32 MatIdx, bool Wireframe); void DrawWireframe(); + + inline u32 NumMaterials() const { return mMaterials.size(); } + inline CCollisionMaterial& GetMaterial(u32 Index) { return mMaterials[Index]; } + inline const CAABox& BoundingBox() const { return mAABox; } }; #endif // CCOLLISIONMESH_H diff --git a/src/Core/Resource/Factory/CCollisionLoader.cpp b/src/Core/Resource/Factory/CCollisionLoader.cpp index e6179ebe..ff4ae5e4 100644 --- a/src/Core/Resource/Factory/CCollisionLoader.cpp +++ b/src/Core/Resource/Factory/CCollisionLoader.cpp @@ -38,27 +38,79 @@ void CCollisionLoader::ParseOBBNode(IInputStream& rDCLN) void CCollisionLoader::ReadPropertyFlags(IInputStream& rSrc) { - CCollisionMesh::SCollisionProperties Property; + CCollisionMaterial Material; + u64 RawFlags = (mVersion <= ePrime ? rSrc.ReadLong() : rSrc.ReadLongLong()); + Material.mRawFlags = RawFlags; - if (mVersion == ePrime) + if (mVersion <= ePrime) { - u32 Flag = rSrc.ReadLong(); - Property.Invert = (Flag >> 25) & 0x1; + if (RawFlags & 0x00000001) Material |= eCF_Unknown; + if (RawFlags & 0x00000002) Material |= eCF_Stone; + if (RawFlags & 0x00000004) Material |= eCF_Metal; + if (RawFlags & 0x00000008) Material |= eCF_Grass; + if (RawFlags & 0x00000010) Material |= eCF_Ice; + if (RawFlags & 0x00000040) Material |= eCF_MetalGrating; + if (RawFlags & 0x00000080) Material |= eCF_Phazon; + if (RawFlags & 0x00000100) Material |= eCF_Dirt; + if (RawFlags & 0x00000200) Material |= eCF_Lava; + if (RawFlags & 0x00000800) Material |= eCF_Snow; + if (RawFlags & 0x00001000) Material |= eCF_SlowMud; + if (RawFlags & 0x00004000) Material |= eCF_Mud; + if (RawFlags & 0x00008000) Material |= eCF_Glass; + if (RawFlags & 0x00010000) Material |= eCF_Shield; + if (RawFlags & 0x00020000) Material |= eCF_Sand; + if (RawFlags & 0x00040000) Material |= eCF_ShootThru; + if (RawFlags & 0x00200000) Material |= eCF_CameraThru; + if (RawFlags & 0x00400000) Material |= eCF_Wood; + if (RawFlags & 0x00800000) Material |= eCF_Organic; + if (RawFlags & 0x02000000) Material |= eCF_FlippedTri; + if (RawFlags & 0x08000000) Material |= eCF_ScanThru; + if (RawFlags & 0x10000000) Material |= eCF_AiWalkThru; + if (RawFlags & 0x20000000) Material |= eCF_Ceiling; + if (RawFlags & 0x40000000) Material |= eCF_Wall; + if (RawFlags & 0x80000000) Material |= eCF_Floor; } - else if (mVersion == eEchoes) + else if (mVersion <= eCorruption) { - u64 Flag = rSrc.ReadLongLong(); - Property.Invert = (Flag >> 24) & 0x1; + if (RawFlags & 0x00000001) Material |= eCF_Unknown; + if (RawFlags & 0x00000002) Material |= eCF_Stone; + if (RawFlags & 0x00000004) Material |= eCF_Metal; + if (RawFlags & 0x00000008) Material |= eCF_Grass; + if (RawFlags & 0x00000010) Material |= eCF_Ice; + if (RawFlags & 0x00000040) Material |= eCF_MetalGrating; + if (RawFlags & 0x00000080) Material |= eCF_Phazon; + if (RawFlags & 0x00000100) Material |= eCF_Dirt; + if (RawFlags & 0x00000200) Material |= eCF_AltMetal; + if (RawFlags & 0x00000400) Material |= eCF_Glass; + if (RawFlags & 0x00000800) Material |= eCF_Snow; + if (RawFlags & 0x00001000) Material |= eCF_Fabric; + if (RawFlags & 0x00010000) Material |= eCF_Shield; + if (RawFlags & 0x00020000) Material |= eCF_Sand; + if (RawFlags & 0x00040000) Material |= eCF_MothSeedOrganics; + if (RawFlags & 0x00080000) Material |= eCF_Web; + if (RawFlags & 0x00100000) Material |= eCF_ShootThru; + if (RawFlags & 0x00200000) Material |= eCF_CameraThru; + if (RawFlags & 0x00400000) Material |= eCF_Wood; + if (RawFlags & 0x00800000) Material |= eCF_Organic; + if (RawFlags & 0x01000000) Material |= eCF_FlippedTri; + if (RawFlags & 0x02000000) Material |= eCF_Rubber; + if (RawFlags & 0x08000000) Material |= eCF_ScanThru; + if (RawFlags & 0x10000000) Material |= eCF_AiWalkThru; + if (RawFlags & 0x20000000) Material |= eCF_Ceiling; + if (RawFlags & 0x40000000) Material |= eCF_Wall; + if (RawFlags & 0x80000000) Material |= eCF_Floor; + + if (RawFlags & 0x0001000000000000) Material |= eCF_AiBlock; + if (RawFlags & 0x0400000000000000) Material |= eCF_JumpNotAllowed; } else if (mVersion == eReturns) { - u64 Flag = rSrc.ReadLongLong(); - Property.Invert = (Flag >> 28) & 0x1; + if (RawFlags & 0x10000000) Material |= eCF_FlippedTri; } - mProperties.push_back(Property); + mpMesh->mMaterials.push_back(Material); } void CCollisionLoader::LoadCollisionIndices(IInputStream &rFile, bool BuildAABox) @@ -89,7 +141,7 @@ void CCollisionLoader::LoadCollisionIndices(IInputStream &rFile, bool BuildAABox CCollisionMesh::CCollisionLine *pLine = &mpMesh->mCollisionLines[iLine]; pLine->Vertices[0] = rFile.ReadShort(); pLine->Vertices[1] = rFile.ReadShort(); - pLine->Properties = mProperties[LineIndices[iLine]]; + pLine->MaterialIdx = LineIndices[iLine]; } // Faces @@ -102,7 +154,7 @@ void CCollisionLoader::LoadCollisionIndices(IInputStream &rFile, bool BuildAABox pFace->Lines[0] = rFile.ReadShort(); pFace->Lines[1] = rFile.ReadShort(); pFace->Lines[2] = rFile.ReadShort(); - pFace->Properties = mProperties[FaceIndices[iFace]]; + pFace->MaterialIdx = FaceIndices[iFace]; } // Echoes introduces a new data chunk; don't know what it is yet, skipping for now @@ -121,7 +173,7 @@ void CCollisionLoader::LoadCollisionIndices(IInputStream &rFile, bool BuildAABox { CCollisionMesh::CCollisionVertex *pVtx = &mpMesh->mCollisionVertices[iVtx]; pVtx->Pos = CVector3f(rFile); - pVtx->Properties = mProperties[VtxIndices[iVtx]]; + pVtx->MaterialIdx = VtxIndices[iVtx]; if (BuildAABox) Bounds.ExpandBounds(pVtx->Pos); } if (BuildAABox) mpMesh->mAABox = Bounds; diff --git a/src/Core/Resource/Factory/CCollisionLoader.h b/src/Core/Resource/Factory/CCollisionLoader.h index 5d3f5d0d..91f3b90c 100644 --- a/src/Core/Resource/Factory/CCollisionLoader.h +++ b/src/Core/Resource/Factory/CCollisionLoader.h @@ -10,7 +10,6 @@ class CCollisionLoader TResPtr mpGroup; CCollisionMesh *mpMesh; EGame mVersion; - std::vector mProperties; CCollisionLoader(); CCollisionMesh::CCollisionOctree* ParseOctree(IInputStream& rSrc); diff --git a/src/Core/Resource/Script/CScriptTemplate.cpp b/src/Core/Resource/Script/CScriptTemplate.cpp index f91feafc..a15eac19 100644 --- a/src/Core/Resource/Script/CScriptTemplate.cpp +++ b/src/Core/Resource/Script/CScriptTemplate.cpp @@ -160,6 +160,7 @@ CResource* CScriptTemplate::FindDisplayAsset(CPropertyStruct *pProperties, u32& for (auto it = mAssets.begin(); it != mAssets.end(); it++) { + if (it->AssetType == SEditorAsset::eCollision) continue; CResource *pRes = nullptr; // File diff --git a/src/Core/Scene/CCollisionNode.cpp b/src/Core/Scene/CCollisionNode.cpp index 4730c6c3..99254ffe 100644 --- a/src/Core/Scene/CCollisionNode.cpp +++ b/src/Core/Scene/CCollisionNode.cpp @@ -37,10 +37,56 @@ void CCollisionNode::Draw(FRenderOptions /*Options*/, int /*ComponentIndex*/, ER glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glDepthMask(GL_TRUE); - CDrawUtil::UseCollisionShader(TintColor(rkViewInfo)); - mpCollision->Draw(); - CDrawUtil::UseColorShader(CColor::skTransparentBlack); - mpCollision->DrawWireframe(); + // Turn off backface culling + EGame CollisionGame = mpCollision->Game(); + bool ForceDisableBackfaceCull = (rkViewInfo.CollisionSettings.DrawBackfaces || CollisionGame == eReturns) && glIsEnabled(GL_CULL_FACE); + + if (ForceDisableBackfaceCull) + glDisable(GL_CULL_FACE); + + CColor BaseTint = TintColor(rkViewInfo); + + for (u32 iMesh = 0; iMesh < mpCollision->NumMeshes(); iMesh++) + { + CCollisionMesh *pMesh = mpCollision->MeshByIndex(iMesh); + + for (u32 iMat = 0; iMat < pMesh->NumMaterials(); iMat++) + { + CCollisionMaterial& rMat = pMesh->GetMaterial(iMat); + + if (rkViewInfo.CollisionSettings.HideMaterial & rMat) + continue; + + if (rkViewInfo.CollisionSettings.HideMask != 0 && (rMat.RawFlags() & rkViewInfo.CollisionSettings.HideMask) != 0) + continue; + + CColor Tint = BaseTint; + + if (rkViewInfo.CollisionSettings.HighlightMask != 0 && (rMat.RawFlags() & rkViewInfo.CollisionSettings.HighlightMask) == rkViewInfo.CollisionSettings.HighlightMask) + Tint *= CColor::skRed; + + else if (CollisionGame != eReturns && rkViewInfo.CollisionSettings.TintWithSurfaceColor) + Tint *= rMat.SurfaceColor(CollisionGame); + + bool IsFloor = (rkViewInfo.CollisionSettings.TintUnwalkableTris ? rMat.IsFloor() : true) || CollisionGame == eReturns; + bool IsUnstandable = (rkViewInfo.CollisionSettings.TintUnwalkableTris ? rMat.IsUnstandable(CollisionGame) : false) && CollisionGame != eReturns; + CDrawUtil::UseCollisionShader(IsFloor, IsUnstandable, Tint); + pMesh->DrawMaterial(iMat, false); + + if (rkViewInfo.CollisionSettings.DrawWireframe) + pMesh->DrawMaterial(iMat, true); + } + } + + // Restore backface culling setting + if (ForceDisableBackfaceCull) + glEnable(GL_CULL_FACE); + + // Draw collision bounds for area collision + // note: right now checking parent is the best way to check whether this node is area collision instead of actor collision + // actor collision will have a script node parent whereas area collision will have a root node parent + if (rkViewInfo.CollisionSettings.DrawAreaCollisionBounds && Parent()->NodeType() == eRootNode && CollisionGame != eReturns) + CDrawUtil::DrawWireCube( mpCollision->MeshByIndex(0)->BoundingBox(), CColor::skRed ); } void CCollisionNode::RayAABoxIntersectTest(CRayCollisionTester& /*rTester*/, const SViewInfo& /*rkViewInfo*/) diff --git a/src/Editor/CAboutDialog.ui b/src/Editor/CAboutDialog.ui index d649bc6f..0a3031be 100644 --- a/src/Editor/CAboutDialog.ui +++ b/src/Editor/CAboutDialog.ui @@ -17,7 +17,7 @@ - <html><head/><body><p><span style=" font-size:12pt; font-weight:600;">%APP_FULL_NAME%</span></p><p>%APP_NAME% is developed by <span style=" font-weight:600;">Parax</span>.<br/>All the games it edits are developed by <span style=" font-weight:600;">Retro Studios</span> and published by <span style=" font-weight:600;">Nintendo</span>.</p><p>Special thanks to:</p><p><ul><li> The community at <span style=" font-weight:600;">Metroid2002</span> that contributed to reverse engineering the game and documenting its internals and file formats; in particular, <span style=" font-weight:600;">Antidote</span> and <span style=" font-weight:600;">jackoalan</span>, among others!</li><li> <span style=" font-weight:600;">Miles: </span>In addition to helping reverse engineer a few formats (in particular MLVL and MREA), also contributed greatly to putting together the script object templates and documenting object properties.</li><li> <span style=" font-weight:600;">Bearborg:</span> Lots of testing and feedback, plus the UI icons and some script object assets.</li><li> <span style=" font-weight:600;">Omega: </span>Script object assets.</li></ul>Check the <a href="http://www.metroid2002.com/retromodding/wiki/Retro_Modding_Wiki">Retro Modding Wiki</a> for file format documentation.</p><p>%APP_NAME% uses <span style=" font-weight:600;">Assimp</span> (Open Asset Import Library).<br/>Copyright © 2006-2015 assimp team<br/>All rights reserved.</p></body></html> + <html><head/><body><p><span style=" font-size:12pt; font-weight:600;">%APP_FULL_NAME%</span></p><p>%APP_NAME% is developed by <span style=" font-weight:600;">Aruki</span>.<br/>All the games it edits are developed by <span style=" font-weight:600;">Retro Studios</span> and published by <span style=" font-weight:600;">Nintendo</span>.</p><p>Special thanks to:</p><p><ul><li> The community at <span style=" font-weight:600;">Metroid2002</span> that contributed to reverse engineering the game and documenting its internals and file formats; in particular, <span style=" font-weight:600;">Antidote</span> and <span style=" font-weight:600;">jackoalan</span>, among others!</li><li> <span style=" font-weight:600;">Claris: </span>In addition to helping reverse engineer a few formats (in particular MLVL and MREA), also contributed greatly to putting together the script object templates and documenting object properties.</li><li> <span style=" font-weight:600;">Bearborg:</span> Lots of testing and feedback, plus the UI icons and some script object assets.</li><li> <span style=" font-weight:600;">Omega: </span>Script object assets.</li></ul>Check the <a href="http://www.metroid2002.com/retromodding/wiki/Retro_Modding_Wiki">Retro Modding Wiki</a> for file format documentation.</p><p>%APP_NAME% uses <span style=" font-weight:600;">Assimp</span> (Open Asset Import Library).<br/>Copyright © 2006-2015 assimp team<br/>All rights reserved.</p></body></html> true diff --git a/src/Editor/CBasicViewport.h b/src/Editor/CBasicViewport.h index 99a9ecad..01337254 100644 --- a/src/Editor/CBasicViewport.h +++ b/src/Editor/CBasicViewport.h @@ -64,6 +64,7 @@ public: CVector2f MouseDeviceCoordinates(); double LastRenderDuration(); + inline SCollisionRenderSettings& CollisionRenderSettings() { return mViewInfo.CollisionSettings; } public slots: void ProcessInput(); void Render(); diff --git a/src/Editor/Editor.pro b/src/Editor/Editor.pro index 740fa849..7a0b07cc 100644 --- a/src/Editor/Editor.pro +++ b/src/Editor/Editor.pro @@ -163,6 +163,7 @@ HEADERS += \ CGridRenderable.h \ CharacterEditor/CSkeletonHierarchyModel.h \ CLineRenderable.h \ + WorldEditor/CCollisionRenderSettingsDialog.h \ CProjectOverviewDialog.h \ ResourceBrowser/CResourceBrowser.h \ ResourceBrowser/CResourceTableModel.h \ @@ -229,6 +230,7 @@ SOURCES += \ CharacterEditor/CCharacterEditor.cpp \ CharacterEditor/CCharacterEditorViewport.cpp \ CharacterEditor/CSkeletonHierarchyModel.cpp \ + WorldEditor/CCollisionRenderSettingsDialog.cpp \ CProjectOverviewDialog.cpp \ ResourceBrowser/CResourceBrowser.cpp \ CEditorApplication.cpp @@ -253,5 +255,6 @@ FORMS += \ WorldEditor/CRepackInfoDialog.ui \ CAboutDialog.ui \ CharacterEditor/CCharacterEditor.ui \ + WorldEditor/CCollisionRenderSettingsDialog.ui \ CProjectOverviewDialog.ui \ ResourceBrowser/CResourceBrowser.ui diff --git a/src/Editor/WorldEditor/CCollisionRenderSettingsDialog.cpp b/src/Editor/WorldEditor/CCollisionRenderSettingsDialog.cpp new file mode 100644 index 00000000..2a9589b8 --- /dev/null +++ b/src/Editor/WorldEditor/CCollisionRenderSettingsDialog.cpp @@ -0,0 +1,115 @@ +#include "CCollisionRenderSettingsDialog.h" +#include "ui_CCollisionRenderSettingsDialog.h" +#include "CWorldEditor.h" +#include "Editor/UICommon.h" + +CCollisionRenderSettingsDialog::CCollisionRenderSettingsDialog(CWorldEditor *pEditor, QWidget *pParent /*= 0*/) + : QDialog(pParent) + , mpEditor(pEditor) + , mpUi(new Ui::CCollisionRenderSettingsDialog) +{ + mpUi->setupUi(this); + + SetupWidgets(); + connect(mpUi->HideMaskLineEdit, SIGNAL(textChanged(QString)), this, SLOT(OnHideMaskChanged(QString))); + connect(mpUi->HighlightMaskLineEdit, SIGNAL(textChanged(QString)), this, SLOT(OnHighlightMaskChanged(QString))); + connect(mpUi->WireframeCheckBox, SIGNAL(toggled(bool)), this, SLOT(OnWireframeToggled(bool))); + connect(mpUi->SurfaceTypeCheckBox, SIGNAL(toggled(bool)), this, SLOT(OnSurfaceTypeToggled(bool))); + connect(mpUi->StandableTrisCheckBox, SIGNAL(toggled(bool)), this, SLOT(OnStandableTrisToggled(bool))); + connect(mpUi->AreaBoundsCheckBox, SIGNAL(toggled(bool)), this, SLOT(OnAreaBoundsToggled(bool))); + connect(mpUi->BackfacesCheckBox, SIGNAL(toggled(bool)), this, SLOT(OnBackfacesToggled(bool))); + + connect(mpUi->HideShootThruCheckBox, SIGNAL(toggled(bool)), this, SLOT(OnHideCheckboxesToggled())); + connect(mpUi->HideCameraThruCheckBox, SIGNAL(toggled(bool)), this, SLOT(OnHideCheckboxesToggled())); + connect(mpUi->HideScanThruCheckBox, SIGNAL(toggled(bool)), this, SLOT(OnHideCheckboxesToggled())); + connect(mpUi->HideAiWalkThruCheckBox, SIGNAL(toggled(bool)), this, SLOT(OnHideCheckboxesToggled())); + connect(mpUi->HideAiBlockCheckBox, SIGNAL(toggled(bool)), this, SLOT(OnHideCheckboxesToggled())); +} + +CCollisionRenderSettingsDialog::~CCollisionRenderSettingsDialog() +{ + delete mpUi; +} + +void CCollisionRenderSettingsDialog::SetupWidgets() +{ + SCollisionRenderSettings& rSettings = mpEditor->Viewport()->CollisionRenderSettings(); + EGame Game = mpEditor->CurrentGame(); + + // Set widgets to match current render setting values + mpUi->HideMaskLineEdit->setText( "0x" + QString::number(rSettings.HideMask, 16).toUpper() ); + mpUi->HighlightMaskLineEdit->setText( "0x" + QString::number(rSettings.HighlightMask, 16).toUpper() ); + mpUi->WireframeCheckBox->setChecked(rSettings.DrawWireframe); + mpUi->SurfaceTypeCheckBox->setChecked(rSettings.TintWithSurfaceColor); + mpUi->StandableTrisCheckBox->setChecked(rSettings.TintUnwalkableTris); + mpUi->AreaBoundsCheckBox->setChecked(rSettings.DrawAreaCollisionBounds); + mpUi->BackfacesCheckBox->setChecked(rSettings.DrawBackfaces); + + mpUi->HideShootThruCheckBox->setChecked(rSettings.HideMaterial.HasFlag(eCF_ShootThru)); + mpUi->HideCameraThruCheckBox->setChecked(rSettings.HideMaterial.HasFlag(eCF_CameraThru)); + mpUi->HideScanThruCheckBox->setChecked(rSettings.HideMaterial.HasFlag(eCF_ScanThru)); + mpUi->HideAiWalkThruCheckBox->setChecked(rSettings.HideMaterial.HasFlag(eCF_AiWalkThru)); + mpUi->HideAiBlockCheckBox->setChecked(rSettings.HideMaterial.HasFlag(eCF_AiBlock)); + + // Toggle visibility of game-exclusive widgets + mpUi->SurfaceTypeCheckBox->setHidden( Game == eReturns ); + mpUi->StandableTrisCheckBox->setHidden( Game == eReturns ); + mpUi->AreaBoundsCheckBox->setHidden( Game == eReturns ); + mpUi->BackfacesCheckBox->setHidden( Game == eReturns ); + + mpUi->VisibilityGroupBox->setHidden( Game == eReturns ); + mpUi->HideShootThruCheckBox->setHidden( Game == eReturns ); + mpUi->HideCameraThruCheckBox->setHidden( Game == eReturns ); + mpUi->HideScanThruCheckBox->setHidden( Game == eReturns ); + mpUi->HideAiWalkThruCheckBox->setHidden( Game == eReturns ); + mpUi->HideAiBlockCheckBox->setHidden( Game < eEchoesDemo || Game == eReturns ); +} + +void CCollisionRenderSettingsDialog::OnHideMaskChanged(QString NewMask) +{ + TString MaskStr = TO_TSTRING(NewMask); + u64 Mask = (MaskStr.IsHexString() ? MaskStr.ToInt64(16) : 0); + mpEditor->Viewport()->CollisionRenderSettings().HideMask = Mask; +} + +void CCollisionRenderSettingsDialog::OnHighlightMaskChanged(QString NewMask) +{ + TString MaskStr = TO_TSTRING(NewMask); + u64 Mask = (MaskStr.IsHexString() ? MaskStr.ToInt64(16) : 0); + mpEditor->Viewport()->CollisionRenderSettings().HighlightMask = Mask; +} + +void CCollisionRenderSettingsDialog::OnWireframeToggled(bool Enable) +{ + mpEditor->Viewport()->CollisionRenderSettings().DrawWireframe = Enable; +} + +void CCollisionRenderSettingsDialog::OnSurfaceTypeToggled(bool Enable) +{ + mpEditor->Viewport()->CollisionRenderSettings().TintWithSurfaceColor = Enable; +} + +void CCollisionRenderSettingsDialog::OnStandableTrisToggled(bool Enable) +{ + mpEditor->Viewport()->CollisionRenderSettings().TintUnwalkableTris = Enable; +} + +void CCollisionRenderSettingsDialog::OnAreaBoundsToggled(bool Enable) +{ + mpEditor->Viewport()->CollisionRenderSettings().DrawAreaCollisionBounds = Enable; +} + +void CCollisionRenderSettingsDialog::OnBackfacesToggled(bool Enable) +{ + mpEditor->Viewport()->CollisionRenderSettings().DrawBackfaces = Enable; +} + +void CCollisionRenderSettingsDialog::OnHideCheckboxesToggled() +{ + CCollisionMaterial& rMat = mpEditor->Viewport()->CollisionRenderSettings().HideMaterial; + mpUi->HideShootThruCheckBox->isChecked() ? rMat |= eCF_ShootThru : rMat &= ~eCF_ShootThru; + mpUi->HideCameraThruCheckBox->isChecked() ? rMat |= eCF_CameraThru : rMat &= ~eCF_CameraThru; + mpUi->HideScanThruCheckBox->isChecked() ? rMat |= eCF_ScanThru : rMat &= ~eCF_ScanThru; + mpUi->HideAiWalkThruCheckBox->isChecked() ? rMat |= eCF_AiWalkThru : rMat &= ~eCF_AiWalkThru; + mpUi->HideAiBlockCheckBox->isChecked() ? rMat |= eCF_AiBlock : rMat &= ~eCF_AiBlock; +} diff --git a/src/Editor/WorldEditor/CCollisionRenderSettingsDialog.h b/src/Editor/WorldEditor/CCollisionRenderSettingsDialog.h new file mode 100644 index 00000000..6219dce2 --- /dev/null +++ b/src/Editor/WorldEditor/CCollisionRenderSettingsDialog.h @@ -0,0 +1,35 @@ +#ifndef CCOLLISIONRENDERSETTINGSDIALOG_H +#define CCOLLISIONRENDERSETTINGSDIALOG_H + +#include + +class CWorldEditor; + +namespace Ui { +class CCollisionRenderSettingsDialog; +} + +class CCollisionRenderSettingsDialog : public QDialog +{ + Q_OBJECT + Ui::CCollisionRenderSettingsDialog *mpUi; + + CWorldEditor *mpEditor; + +public: + explicit CCollisionRenderSettingsDialog(CWorldEditor *pEditor, QWidget *pParent = 0); + ~CCollisionRenderSettingsDialog(); + +public slots: + void SetupWidgets(); + void OnHideMaskChanged(QString NewMask); + void OnHighlightMaskChanged(QString NewMask); + void OnWireframeToggled(bool Enable); + void OnSurfaceTypeToggled(bool Enable); + void OnStandableTrisToggled(bool Enable); + void OnAreaBoundsToggled(bool Enable); + void OnBackfacesToggled(bool Enable); + void OnHideCheckboxesToggled(); +}; + +#endif // CCOLLISIONRENDERSETTINGSDIALOG_H diff --git a/src/Editor/WorldEditor/CCollisionRenderSettingsDialog.ui b/src/Editor/WorldEditor/CCollisionRenderSettingsDialog.ui new file mode 100644 index 00000000..d37c78bb --- /dev/null +++ b/src/Editor/WorldEditor/CCollisionRenderSettingsDialog.ui @@ -0,0 +1,151 @@ + + + CCollisionRenderSettingsDialog + + + + 0 + 0 + 247 + 395 + + + + + 0 + 0 + + + + Collision Render Settings + + + + QLayout::SetFixedSize + + + + + Settings + + + + + + Wireframe + + + + + + + Show Standable Tris + + + + + + + Show Surface Type + + + + + + + Show Area Collision Bounds + + + + + + + Draw Backfaces + + + + + + + + + + Visibility + + + + + + Hide Shoot Thru + + + + + + + Hide Camera Thru + + + + + + + Hide Scan Thru + + + + + + + Hide AI Walk Thru + + + + + + + Hide AI Block + + + + + + + + + + Advanced + + + + + + + + Hide Mask + + + + + + + + + + Highlight Mask + + + + + + + + + + + + + + + + diff --git a/src/Editor/WorldEditor/CWorldEditor.cpp b/src/Editor/WorldEditor/CWorldEditor.cpp index 09326404..9a95bf36 100644 --- a/src/Editor/WorldEditor/CWorldEditor.cpp +++ b/src/Editor/WorldEditor/CWorldEditor.cpp @@ -88,6 +88,8 @@ CWorldEditor::CWorldEditor(QWidget *parent) ui->ActionDelete->setAutoRepeat(false); ui->ActionDelete->setShortcut(QKeySequence::Delete); + mpCollisionDialog = new CCollisionRenderSettingsDialog(this, this); + // Connect signals and slots connect(ui->MainViewport, SIGNAL(ViewportClick(SRayIntersection,QMouseEvent*)), this, SLOT(OnViewportClick(SRayIntersection,QMouseEvent*))); connect(ui->MainViewport, SIGNAL(InputProcessed(SRayIntersection,QMouseEvent*)), this, SLOT(OnViewportInputProcessed(SRayIntersection,QMouseEvent*))); @@ -124,7 +126,6 @@ CWorldEditor::CWorldEditor(QWidget *parent) connect(ui->ActionDrawLights, SIGNAL(triggered()), this, SLOT(ToggleDrawLights())); connect(ui->ActionDrawSky, SIGNAL(triggered()), this, SLOT(ToggleDrawSky())); connect(ui->ActionGameMode, SIGNAL(triggered()), this, SLOT(ToggleGameMode())); - connect(ui->ActionDisableBackfaceCull, SIGNAL(triggered()), this, SLOT(ToggleBackfaceCull())); connect(ui->ActionDisableAlpha, SIGNAL(triggered()), this, SLOT(ToggleDisableAlpha())); connect(ui->ActionNoLighting, SIGNAL(triggered()), this, SLOT(SetNoLighting())); connect(ui->ActionBasicLighting, SIGNAL(triggered()), this, SLOT(SetBasicLighting())); @@ -135,6 +136,7 @@ CWorldEditor::CWorldEditor(QWidget *parent) connect(ui->ActionBloom, SIGNAL(triggered()), this, SLOT(SetBloom())); connect(ui->ActionIncrementGizmo, SIGNAL(triggered()), this, SLOT(IncrementGizmo())); connect(ui->ActionDecrementGizmo, SIGNAL(triggered()), this, SLOT(DecrementGizmo())); + connect(ui->ActionCollisionRenderSettings, SIGNAL(triggered()), this, SLOT(EditCollisionRenderSettings())); connect(ui->ActionEditLayers, SIGNAL(triggered()), this, SLOT(EditLayers())); connect(ui->ActionEditPoiToWorldMap, SIGNAL(triggered()), this, SLOT(EditPoiToWorldMap())); @@ -156,6 +158,7 @@ void CWorldEditor::closeEvent(QCloseEvent *pEvent) if (ShouldClose) { mUndoStack.clear(); + mpCollisionDialog->close(); mpLinkDialog->close(); if (mpPoiDialog) @@ -222,6 +225,7 @@ void CWorldEditor::SetArea(CWorld *pWorld, CGameArea *pArea) ui->InstancesTabContents->SetMaster(pMaster); // Set up dialogs + mpCollisionDialog->SetupWidgets(); // Won't modify any settings but will update widget visibility status if we've changed games mpLinkDialog->SetMaster(pMaster); // Set window title @@ -1020,11 +1024,6 @@ void CWorldEditor::ToggleGameMode() ui->MainViewport->SetGameMode(ui->ActionGameMode->isChecked()); } -void CWorldEditor::ToggleBackfaceCull() -{ - ui->MainViewport->Renderer()->ToggleBackfaceCull(!ui->ActionDisableBackfaceCull->isChecked()); -} - void CWorldEditor::ToggleDisableAlpha() { ui->MainViewport->Renderer()->ToggleAlphaDisabled(ui->ActionDisableAlpha->isChecked()); @@ -1100,6 +1099,11 @@ void CWorldEditor::DecrementGizmo() mGizmo.DecrementSize(); } +void CWorldEditor::EditCollisionRenderSettings() +{ + mpCollisionDialog->show(); +} + void CWorldEditor::EditLayers() { // Launch layer editor diff --git a/src/Editor/WorldEditor/CWorldEditor.h b/src/Editor/WorldEditor/CWorldEditor.h index a0265441..b08fb493 100644 --- a/src/Editor/WorldEditor/CWorldEditor.h +++ b/src/Editor/WorldEditor/CWorldEditor.h @@ -1,6 +1,7 @@ #ifndef CWORLDEDITOR_H #define CWORLDEDITOR_H +#include "CCollisionRenderSettingsDialog.h" #include "CLinkDialog.h" #include "CPoiMapEditDialog.h" #include "Editor/INodeEditor.h" @@ -38,6 +39,7 @@ class CWorldEditor : public INodeEditor TResPtr mpWorld; TResPtr mpArea; + CCollisionRenderSettingsDialog *mpCollisionDialog; CLinkDialog *mpLinkDialog; CPoiMapEditDialog *mpPoiDialog; @@ -120,7 +122,6 @@ private slots: void ToggleDrawLights(); void ToggleDrawSky(); void ToggleGameMode(); - void ToggleBackfaceCull(); void ToggleDisableAlpha(); void SetNoLighting(); void SetBasicLighting(); @@ -131,6 +132,7 @@ private slots: void SetBloom(); void IncrementGizmo(); void DecrementGizmo(); + void EditCollisionRenderSettings(); void EditLayers(); void EditPoiToWorldMap(); diff --git a/src/Editor/WorldEditor/CWorldEditor.ui b/src/Editor/WorldEditor/CWorldEditor.ui index 073fc5c9..ae3e34d6 100644 --- a/src/Editor/WorldEditor/CWorldEditor.ui +++ b/src/Editor/WorldEditor/CWorldEditor.ui @@ -463,7 +463,7 @@ - + @@ -818,6 +818,11 @@ Ctrl+Shift+S + + + Collision Render Settings + + diff --git a/templates/Properties.xml b/templates/Properties.xml index 6a70fa51..cae29023 100644 --- a/templates/Properties.xml +++ b/templates/Properties.xml @@ -1081,7 +1081,7 @@ - + @@ -2054,7 +2054,7 @@ - + @@ -2158,7 +2158,7 @@ - + @@ -2622,7 +2622,7 @@ - + @@ -3502,7 +3502,7 @@ - + @@ -4076,7 +4076,7 @@ - + @@ -5139,7 +5139,7 @@ - + @@ -5212,7 +5212,7 @@ - + @@ -6285,7 +6285,7 @@ - + @@ -6989,7 +6989,7 @@ - + @@ -7191,7 +7191,7 @@ - + @@ -8031,7 +8031,7 @@ - + @@ -8910,7 +8910,7 @@ - + @@ -10806,7 +10806,7 @@ - + diff --git a/templates/dkcr/MasterTemplate.xml b/templates/dkcr/MasterTemplate.xml index 76748888..9604456e 100644 --- a/templates/dkcr/MasterTemplate.xml +++ b/templates/dkcr/MasterTemplate.xml @@ -178,13 +178,13 @@ - + - + - + @@ -210,57 +210,57 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -268,12 +268,12 @@ - - + + - + @@ -282,12 +282,12 @@ - - - - - - + + + + + + @@ -296,7 +296,7 @@ - + @@ -326,40 +326,40 @@ - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + diff --git a/templates/dkcr/Script/AreaNode.xml b/templates/dkcr/Script/AreaNode.xml index aa593bbb..ae47be49 100644 --- a/templates/dkcr/Script/AreaNode.xml +++ b/templates/dkcr/Script/AreaNode.xml @@ -15,14 +15,14 @@ 0x24E6FE6B - - - - - - - - + + + + + + + + @@ -30,6 +30,7 @@ 0 + Seems to affect the number displayed on the file select screen for "last completed stage" 0.0, 0.0, 0.0 diff --git a/templates/dkcr/Script/AreaPath.xml b/templates/dkcr/Script/AreaPath.xml index 5ef827a8..7cf27a28 100644 --- a/templates/dkcr/Script/AreaPath.xml +++ b/templates/dkcr/Script/AreaPath.xml @@ -45,7 +45,9 @@ - + + 0xC27FFA8F + enabled enabled