/* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * * For complete copyright and license terms please see the LICENSE at the root of this * distribution (the "License"). All use of this software is governed by the License, * or, if provided, by the license below or the license accompanying this file. Do not * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ // Original file Copyright Crytek GMBH or its affiliates, used under license. #include "StdAfx.h" #include "SmoothingGroupTool.h" #include "Tools/DesignerTool.h" #include "Core/Model.h" #include "Core/SmoothingGroupManager.h" #include "ToolFactory.h" namespace { ISmoothingGroupPanel* g_pSmoothingGroupPanel = NULL; } void SmoothingGroupTool::Enter() { SelectTool::Enter(); ElementManager* pSelected = CD::GetDesigner()->GetSelectedElements(); pSelected->Erase(CD::ePF_Vertex | CD::ePF_Edge); } void SmoothingGroupTool::BeginEditParams() { if (!g_pSmoothingGroupPanel) { g_pSmoothingGroupPanel = (ISmoothingGroupPanel*)uiPanelFactory::the().Create(Tool(), this); } } void SmoothingGroupTool::EndEditParams() { CD::DestroyPanel(&g_pSmoothingGroupPanel); } string SmoothingGroupTool::SetSmoothingGroup(const char* id_name) { ElementManager* pSelected = CD::GetDesigner()->GetSelectedElements(); if (pSelected->IsEmpty()) { return ""; } std::vector<CD::PolygonPtr> polygons; for (int i = 0, iElementCount(pSelected->GetCount()); i < iElementCount; ++i) { if (!(*pSelected)[i].IsFace() || !(*pSelected)[i].m_pPolygon) { continue; } polygons.push_back((*pSelected)[i].m_pPolygon); } SmoothingGroupManager* pSmoothingGroupMgr = GetModel()->GetSmoothingGroupMgr(); string newName = id_name ? string(id_name) : pSmoothingGroupMgr->GetEmptyGroupID(); pSmoothingGroupMgr->RemoveSmoothingGroup(newName); pSmoothingGroupMgr->AddSmoothingGroup(newName, new SmoothingGroup(polygons)); UpdateAll(CD::eUT_Mesh | CD::eUT_SyncPrefab); return newName; } void SmoothingGroupTool::AddPolygonsToSmoothingGroup(const char* id_name) { ElementManager* pSelected = CD::GetDesigner()->GetSelectedElements(); if (pSelected->IsEmpty()) { return; } SmoothingGroupManager* pSmoothingGroupMgr = GetModel()->GetSmoothingGroupMgr(); for (int i = 0, iElementCount(pSelected->GetCount()); i < iElementCount; ++i) { if (!(*pSelected)[i].IsFace() || !(*pSelected)[i].m_pPolygon) { continue; } pSmoothingGroupMgr->AddPolygon(id_name, (*pSelected)[i].m_pPolygon); } UpdateAll(CD::eUT_Mesh | CD::eUT_SyncPrefab); } bool SmoothingGroupTool::HasSmoothingGroup(const char* id_name) const { SmoothingGroupManager* pSmoothingGroupMgr = GetModel()->GetSmoothingGroupMgr(); return pSmoothingGroupMgr->GetSmoothingGroup(id_name) != NULL; } bool SmoothingGroupTool::IsEmpty(const char* id_name) const { SmoothingGroupManager* pSmoothingGroupMgr = GetModel()->GetSmoothingGroupMgr(); DesignerSmoothingGroupPtr pSmoothingGroup = pSmoothingGroupMgr->GetSmoothingGroup(id_name); if (!pSmoothingGroup) { return true; } return pSmoothingGroup->GetPolygonCount() == 0; } int SmoothingGroupTool::GetSmoothingGroupCount() const { return GetModel()->GetSmoothingGroupMgr()->GetCount(); } std::vector<SSyncItem> SmoothingGroupTool::GetAll() const { SmoothingGroupManager* pSmoothingGroupMgr = GetModel()->GetSmoothingGroupMgr(); std::vector<std::pair<string, DesignerSmoothingGroupPtr> > groupList = pSmoothingGroupMgr->GetSmoothingGroupList(); std::vector<SSyncItem> items; for (int i = 0, iGroupCount(groupList.size()); i < iGroupCount; ++i) { SSyncItem item; item.name = groupList[i].first; item.polygons = groupList[i].second->GetAll(); items.push_back(item); } return items; } void SmoothingGroupTool::SyncAll(std::vector<SSyncItem>& items) { SmoothingGroupManager* pSmoothingGroupMgr = GetModel()->GetSmoothingGroupMgr(); pSmoothingGroupMgr->Clear(); for (int i = 0, iCount(items.size()); i < iCount; ++i) { pSmoothingGroupMgr->AddSmoothingGroup(items[i].name, new SmoothingGroup(items[i].polygons)); } UpdateAll(CD::eUT_Mesh | CD::eUT_SyncPrefab); } void SmoothingGroupTool::RenameGroup(const char* id_name, const char* new_id_name) { SmoothingGroupManager* pSmoothingGroupMgr = GetModel()->GetSmoothingGroupMgr(); DesignerSmoothingGroupPtr pSmoothingGroup = pSmoothingGroupMgr->GetSmoothingGroup(id_name); if (pSmoothingGroup) { pSmoothingGroupMgr->RemoveSmoothingGroup(id_name); pSmoothingGroupMgr->AddSmoothingGroup(new_id_name, pSmoothingGroup); } } void SmoothingGroupTool::RemovePolygonsFromSmoothingGroups() { ElementManager* pSelected = CD::GetDesigner()->GetSelectedElements(); SmoothingGroupManager* pSmoothingGroupMgr = GetModel()->GetSmoothingGroupMgr(); for (int i = 0, iElementCount(pSelected->GetCount()); i < iElementCount; ++i) { if (!(*pSelected)[i].IsFace() || !(*pSelected)[i].m_pPolygon) { continue; } pSmoothingGroupMgr->RemovePolygon((*pSelected)[i].m_pPolygon); } UpdateAll(CD::eUT_Mesh | CD::eUT_SyncPrefab); } bool IsLessThanAngleOfSeedPolygons(CD::PolygonPtr pPolygon, const std::set<CD::PolygonPtr>& seedPolygons, BrushFloat fRadian) { std::set<CD::PolygonPtr>::const_iterator ii = seedPolygons.begin(); for (; ii != seedPolygons.end(); ++ii) { BrushFloat dot = (*ii)->GetPlane().Normal().Dot(pPolygon->GetPlane().Normal()); if (std::acos(dot) <= fRadian) { return true; } } return false; } bool IsAdjacentWithSeedPolygons(CD::PolygonPtr pPolygon, const std::set<CD::PolygonPtr>& seedPolygons) { std::set<CD::PolygonPtr>::const_iterator ii = seedPolygons.begin(); for (; ii != seedPolygons.end(); ++ii) { bool bHadCommonEdge = false; int nEdgeCount = pPolygon->GetEdgeCount(); for (int k = 0; k < nEdgeCount; ++k) { BrushEdge3D e = pPolygon->GetEdge(k); if ((*ii)->HasEdge(e)) { bHadCommonEdge = true; break; } } if (bHadCommonEdge) { return true; } } return false; } void SmoothingGroupTool::ApplyAutoSmooth(int nAngle) { BrushFloat fRadian = ((BrushFloat)nAngle / (BrushFloat)180) * CD::PI; ElementManager* pSelected = CD::GetDesigner()->GetSelectedElements(); std::set<CD::PolygonPtr> usedPolygons; SmoothingGroupManager* pSmoothingGroupMgr = GetModel()->GetSmoothingGroupMgr(); int iSelectedElementCount(pSelected->GetCount()); std::set<CD::PolygonPtr> seedPolygons; std::vector<CD::PolygonPtr> polygonsInGroup; while (1) { CD::PolygonPtr pStartingSeedPolygon = NULL; if (seedPolygons.empty()) { for (int i = 0; i < iSelectedElementCount; ++i) { if (usedPolygons.find((*pSelected)[i].m_pPolygon) == usedPolygons.end()) { pStartingSeedPolygon = (*pSelected)[i].m_pPolygon; seedPolygons.insert(pStartingSeedPolygon); polygonsInGroup.push_back(pStartingSeedPolygon); usedPolygons.insert(pStartingSeedPolygon); break; } } if (seedPolygons.empty()) { break; } } bool bFinishLoop = false; while (!bFinishLoop && !seedPolygons.empty()) { int nOffset = polygonsInGroup.size(); for (int i = 0; i < iSelectedElementCount; ++i) { CD::PolygonPtr pPolygon = (*pSelected)[i].m_pPolygon; if (usedPolygons.find(pPolygon) != usedPolygons.end()) { continue; } if (!IsLessThanAngleOfSeedPolygons(pPolygon, seedPolygons, fRadian)) { continue; } if (!IsAdjacentWithSeedPolygons(pPolygon, seedPolygons)) { continue; } polygonsInGroup.push_back(pPolygon); usedPolygons.insert(pPolygon); } seedPolygons.clear(); if (nOffset < polygonsInGroup.size()) { seedPolygons.insert(polygonsInGroup.begin() + nOffset, polygonsInGroup.end()); } else { if (polygonsInGroup.empty()) { bFinishLoop = true; break; } for (int i = 0, iPolygonCount(polygonsInGroup.size()); i < iPolygonCount; ++i) { pSmoothingGroupMgr->RemovePolygon(polygonsInGroup[i]); } string emptyGroupID = pSmoothingGroupMgr->GetEmptyGroupID(); if (emptyGroupID.empty()) { bFinishLoop = true; break; } pSmoothingGroupMgr->AddSmoothingGroup(emptyGroupID, new SmoothingGroup(polygonsInGroup)); polygonsInGroup.clear(); break; } } if (bFinishLoop) { break; } } UpdateAll(CD::eUT_Mesh | CD::eUT_SyncPrefab); } void SmoothingGroupTool::SelectPolygonsInSmoothingGroup(const char* id_name) { SmoothingGroupManager* pSmoothingGroupMgr = GetModel()->GetSmoothingGroupMgr(); DesignerSmoothingGroupPtr pSmoothingGroup = pSmoothingGroupMgr->GetSmoothingGroup(id_name); if (pSmoothingGroup == NULL) { return; } ElementManager* pSelected = CD::GetDesigner()->GetSelectedElements(); for (int i = 0, iPolygonCount(pSmoothingGroup->GetPolygonCount()); i < iPolygonCount; ++i) { CD::PolygonPtr pPolygon = pSmoothingGroup->GetPolygon(i); pSelected->Add(SElement(GetBaseObject(), pPolygon)); } CD::GetDesigner()->UpdateSelectionMeshFromSelectedElements(GetMainContext()); } void SmoothingGroupTool::OnLButtonUp(CViewport* view, UINT nFlags, const QPoint& point) { SelectTool::OnLButtonUp(view, nFlags, point); g_pSmoothingGroupPanel->ClearAllSelectionsOfNumbers(); } bool SmoothingGroupTool::OnKeyDown(CViewport* view, uint32 nChar, uint32 nRepCnt, uint32 nFlags) { if (nChar == VK_ESCAPE) { return CD::GetDesigner()->EndCurrentEditSession(); } return true; } void SmoothingGroupTool::ClearSelectedElements() { ElementManager* pSelected = CD::GetDesigner()->GetSelectedElements(); pSelected->Clear(); CD::GetDesigner()->UpdateSelectionMeshFromSelectedElements(GetMainContext()); } #include "UIs/SmoothingGroupPanel.h" REGISTER_DESIGNER_TOOL_WITH_PANEL(CD::eDesigner_SmoothingGroup, CD::eToolGroup_Surface, "Smoothing Group", SmoothingGroupTool, SmoothingGroupPanel)