!XT (Code) Update copyright headers in Code/Sandbox.
[CRYENGINE.git] / Code / Sandbox / Plugins / CryDesigner / DesignerSession.cpp
blob62e01de9b63358283a0214750da8c3c5029a0fab
1 // Copyright 2001-2018 Crytek GmbH / Crytek Group. All rights reserved.
3 #include "StdAfx.h"
4 #include "DesignerSession.h"
6 #include "Util/DesignerSettings.h"
7 #include "Util/Converter.h"
8 #include "Core/Helper.h"
10 #include "IEditor.h"
11 #include "Material/MaterialManager.h"
13 #include "Core/ModelCompiler.h"
14 #include "Objects/DesignerObject.h"
15 #include "Objects/AreaSolidObject.h"
16 #include "Objects/ClipVolumeObject.h"
17 #include "Objects/EntityObject.h"
18 #include "Objects/BrushObject.h"
19 #include "RecursionLoopGuard.h"
21 namespace Designer
24 DesignerSession* DesignerSession::s_session = nullptr;
26 DesignerSession::DesignerSession()
27 : m_bActiveSession(false)
28 , m_bSessionFinished(false)
30 GetIEditor()->GetMaterialManager()->AddListener(this);
32 // Brush to Designer
33 GetIEditor()->GetObjectManager()->RegisterTypeConverter(RUNTIME_CLASS(CBrushObject), "Designer", [](CBaseObject* pObject)
35 Converter converter;
36 if (!converter.ConvertToDesignerObject())
37 CryWarning(VALIDATOR_MODULE_EDITOR, VALIDATOR_ERROR, "The selected object(s) can't be converted.");
38 });
40 // Entity to Designer
41 GetIEditor()->GetObjectManager()->RegisterTypeConverter(RUNTIME_CLASS(CEntityObject), "Designer", [](CBaseObject* pObject)
43 Converter converter;
44 if (!converter.ConvertToDesignerObject())
45 CryWarning(VALIDATOR_MODULE_EDITOR, VALIDATOR_ERROR, "The selected object(s) can't be converted.");
46 });
49 DesignerSession::~DesignerSession()
51 GetIEditor()->GetMaterialManager()->RemoveListener(this);
54 DesignerSession* DesignerSession::GetInstance()
56 if (!s_session)
58 s_session = new DesignerSession();
61 return s_session;
64 Model* DesignerSession::GetModel() const
66 if (!m_pBaseObject)
67 return nullptr;
69 Model* pModel;
70 if (Designer::GetModel(m_pBaseObject, pModel))
71 return pModel;
73 DESIGNER_ASSERT(0);
74 return nullptr;
77 CBaseObject* DesignerSession::GetBaseObject() const
79 return m_pBaseObject;
82 MainContext DesignerSession::GetMainContext()
84 MainContext mc(m_pBaseObject, GetCompiler(), GetModel());
85 mc.pSelected = &m_pSelectedElements;
86 return mc;
89 ModelCompiler* DesignerSession::GetCompiler() const
91 DESIGNER_ASSERT(m_pBaseObject);
92 if (!m_pBaseObject)
93 return nullptr;
95 ModelCompiler* pCompiler;
96 if (Designer::GetCompiler(m_pBaseObject, pCompiler))
97 return pCompiler;
99 DESIGNER_ASSERT(0);
100 return nullptr;
103 void DesignerSession::SetBaseObject(CBaseObject* pBaseObject)
105 if (m_pBaseObject == pBaseObject)
106 return;
107 m_pBaseObject = pBaseObject;
108 signalDesignerEvent(eDesignerNotify_ObjectSelect, 0);
111 void DesignerSession::OnEditorNotifyEvent(EEditorNotifyEvent event)
113 bool bExclusiveModeBeforeSave = false;
114 ElementSet* pSelected = GetSelectedElements();
115 switch (event)
117 case eNotify_OnBeginGameMode:
118 case eNotify_OnBeginBindViewport:
119 gDesignerSettings.bExclusiveMode = false;
120 gExclusiveModeSettings.EnableExclusiveMode(gDesignerSettings.bExclusiveMode);
121 pSelected->Clear();
122 gDesignerSettings.Update(true);
123 signalDesignerEvent(eDesignerNotify_SettingsChanged, nullptr);
124 break;
126 case eNotify_OnBeginLoad:
127 case eNotify_OnBeginNewScene:
128 case eNotify_OnBeginSceneOpen:
129 // make sure we clear the cache here
130 ClearCache();
131 // fallthrough
132 case eNotify_OnBeginSceneSave:
133 bExclusiveModeBeforeSave = gDesignerSettings.bExclusiveMode;
134 if (gDesignerSettings.bExclusiveMode)
136 gDesignerSettings.bExclusiveMode = false;
137 gExclusiveModeSettings.EnableExclusiveMode(gDesignerSettings.bExclusiveMode);
139 break;
141 case eNotify_OnEndSceneSave:
142 if (bExclusiveModeBeforeSave)
144 gDesignerSettings.bExclusiveMode = true;
145 gExclusiveModeSettings.EnableExclusiveMode(gDesignerSettings.bExclusiveMode);
146 bExclusiveModeBeforeSave = false;
148 break;
149 case eNotify_OnSelectionChange:
151 const CSelectionGroup* sel = GetIEditor()->GetObjectManager()->GetSelection();
152 const int count = sel->GetCount();
153 bool startSession = count > 0;
154 for (int i = 0; i < count; i++)
156 CBaseObject* obj = sel->GetObject(i);
157 if (!Designer::CanDesignerEditObject(obj))
158 startSession = false;
159 /*else if(obj->IsKindOf(RUNTIME_CLASS(AreaSolidObject))
161 //this was on the area solid BeginEditParams(), not sure where to put this now...
162 Designer::GetModel(obj)->SetFlag(GetModel()->GetFlag() | eModelFlag_DisplayBackFace);
163 ApplyPostProcess(MainContext(this, GetCompiler(), GetModel()), ePostProcess_Mesh);
167 if (startSession)
168 BeginSession();
169 else
170 EndSession();
176 void DesignerSession::SetCurrentSubMatID(int idx)
178 //move to session
179 m_currentMaterialIntex = idx;
180 MaterialChangeEvent evt = { idx };
181 signalDesignerEvent(eDesignerNotify_SubMaterialSelectionChanged, &evt);
184 void DesignerSession::ClearCache()
186 m_pBaseObject = nullptr;
187 m_currentMaterialIntex = 0;
189 m_pExcludedEdgeManager.Clear();
190 m_pSelectedElements.Clear();
192 m_pSelectionMesh = nullptr;
195 void DesignerSession::OnDataBaseItemEvent(
196 IDataBaseItem* pItem,
197 EDataBaseItemEvent event)
199 DatabaseEvent evt;
200 evt.evt = event;
201 evt.pItem = pItem;
203 signalDesignerEvent(eDesignerNotify_SubMaterialSelectionChanged, &evt);
205 auto pObject = GetBaseObject();
206 if (pObject)
208 if (pObject->GetMaterial() == (IEditorMaterial*)pItem || pObject->GetRenderMaterial() == (IEditorMaterial*)pItem)
209 signalDesignerEvent(eDesignerNotify_RefreshSubMaterialList, nullptr);
213 int DesignerSession::GetCurrentSubMatID() const
215 return m_currentMaterialIntex;
218 ElementSet* DesignerSession::GetSelectedElements()
220 return &m_pSelectedElements;
223 void DesignerSession::ClearPolygonSelections()
225 m_pSelectionMesh = nullptr;
228 _smart_ptr<PolygonMesh> DesignerSession::GetSelectionMesh()
230 return m_pSelectionMesh;
233 void DesignerSession::UpdateSelectionMeshFromSelectedElements(MainContext& mc)
235 if (!mc.pModel || !mc.pCompiler)
236 return;
238 std::vector<PolygonPtr> polygonlist;
240 ElementSet* pSelectedElement = DesignerSession::GetInstance()->GetSelectedElements();
242 for (int k = 0, iElementSize(pSelectedElement->GetCount()); k < iElementSize; ++k)
244 if (pSelectedElement->Get(k).IsPolygon())
245 polygonlist.push_back(pSelectedElement->Get(k).m_pPolygon);
248 if (m_pSelectionMesh == NULL)
249 m_pSelectionMesh = new PolygonMesh;
251 int renderFlag = mc.pCompiler->GetRenderFlags();
252 int viewDist = mc.pCompiler->GetViewDistRatio();
253 uint32 minSpec = mc.pObject->GetMinSpec();
254 uint32 materialLayerMask = mc.pObject->GetMaterialLayersMask();
255 BrushMatrix34 worldTM = mc.pObject->GetWorldTM();
257 m_pSelectionMesh->SetPolygons(polygonlist, false, worldTM, renderFlag, viewDist, minSpec, materialLayerMask);
260 void DesignerSession::UpdateSelectionMesh(
261 PolygonPtr pPolygon,
262 ModelCompiler* pCompiler,
263 CBaseObject* pObj,
264 bool bForce)
266 std::vector<PolygonPtr> polygons;
267 if (pPolygon)
268 polygons.push_back(pPolygon);
269 UpdateSelectionMesh(polygons, pCompiler, pObj, bForce);
272 void DesignerSession::UpdateSelectionMesh(
273 std::vector<PolygonPtr> polygons,
274 ModelCompiler* pCompiler,
275 CBaseObject* pObj,
276 bool bForce)
278 if (m_pSelectionMesh == NULL)
279 m_pSelectionMesh = new PolygonMesh;
281 int renderFlag = pCompiler->GetRenderFlags();
282 int viewDist = pCompiler->GetViewDistRatio();
283 uint32 minSpec = pObj->GetMinSpec();
284 uint32 materialLayerMask = pObj->GetMaterialLayersMask();
285 BrushMatrix34 worldTM = pObj->GetWorldTM();
287 if (!polygons.empty())
288 m_pSelectionMesh->SetPolygons(polygons, bForce, worldTM, renderFlag, viewDist, minSpec, materialLayerMask);
289 else
290 m_pSelectionMesh->SetPolygon(NULL, bForce, worldTM, renderFlag, viewDist, minSpec, materialLayerMask);
293 void DesignerSession::ReleaseSelectionMesh()
295 if (m_pSelectionMesh)
297 m_pSelectionMesh->ReleaseResources();
298 m_pSelectionMesh = nullptr;
302 void DesignerSession::BeginSession()
304 // This will clear selection caches every time a new object is selected, which
305 // is not what we usually want, but will suffice until we rip selection state
306 // into the Model itself, rather than the session
307 ClearCache();
309 const CSelectionGroup* pSelection = GetIEditor()->GetObjectManager()->GetSelection();
310 SetBaseObject(pSelection->GetObject(0));
312 if (!m_bActiveSession)
314 Model* model;
315 model = GetModel();
316 model->SetShelf(eShelf_Base);
318 if (gDesignerSettings.bExclusiveMode)
320 if (model && model->IsEmpty())
322 gDesignerSettings.bExclusiveMode = false;
323 gDesignerSettings.Update(true);
325 else
327 gExclusiveModeSettings.EnableExclusiveMode(true);
331 signalDesignerEvent(eDesignerNotify_BeginDesignerSession, nullptr);
333 m_bActiveSession = true;
337 ExcludedEdgeManager* DesignerSession::GetExcludedEdgeManager()
339 return &m_pExcludedEdgeManager;
342 std::vector<EDesignerTool> DesignerSession::GetIncompatibleSubtools()
344 if (!m_pBaseObject)
345 return std::vector<EDesignerTool>();
347 if (m_pBaseObject->IsKindOf(RUNTIME_CLASS(DesignerObject)))
349 DesignerObject* pModelObj = static_cast<DesignerObject*>(m_pBaseObject.get());
350 return pModelObj->GetIncompatibleSubtools();
352 else if (m_pBaseObject->IsKindOf(RUNTIME_CLASS(AreaSolidObject)))
354 AreaSolidObject* pArea = static_cast<AreaSolidObject*>(m_pBaseObject.get());
355 return pArea->GetIncompatibleSubtools();
357 else if (m_pBaseObject->IsKindOf(RUNTIME_CLASS(ClipVolumeObject)))
359 ClipVolumeObject* pVolume = static_cast<ClipVolumeObject*>(m_pBaseObject.get());
360 return pVolume->GetIncompatibleSubtools();
363 // should never happen but...
364 return std::vector<EDesignerTool>();
367 void DesignerSession::EndSession()
369 RECURSION_GUARD(m_bSessionFinished);
370 if (m_bActiveSession)
372 // disable at once, this saves us from recursive calls when destroying empty designer objects on tool exit
373 m_bActiveSession = false;
375 // quit any designer tools if we still have one.
376 // usually session ends when we select another object type, so we usually are in
377 // object mode tool already but it can also happen when we undo out of the session.
378 // In that case, designer won't have data to work with so we need to ensure the tool has quit.
379 if (GetDesigner())
381 GetIEditor()->SetEditTool(nullptr);
384 gExclusiveModeSettings.EnableExclusiveMode(false);
385 signalDesignerEvent(eDesignerNotify_EndDesignerSession, nullptr);
386 ClearCache();
390 bool DesignerSession::GetIsActive()
392 return m_bActiveSession;