1 // Copyright 2001-2018 Crytek GmbH / Crytek Group. All rights reserved.
4 #include "DesignerSession.h"
6 #include "Util/DesignerSettings.h"
7 #include "Util/Converter.h"
8 #include "Core/Helper.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"
24 DesignerSession
* DesignerSession::s_session
= nullptr;
26 DesignerSession::DesignerSession()
27 : m_bActiveSession(false)
28 , m_bSessionFinished(false)
30 GetIEditor()->GetMaterialManager()->AddListener(this);
33 GetIEditor()->GetObjectManager()->RegisterTypeConverter(RUNTIME_CLASS(CBrushObject
), "Designer", [](CBaseObject
* pObject
)
36 if (!converter
.ConvertToDesignerObject())
37 CryWarning(VALIDATOR_MODULE_EDITOR
, VALIDATOR_ERROR
, "The selected object(s) can't be converted.");
41 GetIEditor()->GetObjectManager()->RegisterTypeConverter(RUNTIME_CLASS(CEntityObject
), "Designer", [](CBaseObject
* pObject
)
44 if (!converter
.ConvertToDesignerObject())
45 CryWarning(VALIDATOR_MODULE_EDITOR
, VALIDATOR_ERROR
, "The selected object(s) can't be converted.");
49 DesignerSession::~DesignerSession()
51 GetIEditor()->GetMaterialManager()->RemoveListener(this);
54 DesignerSession
* DesignerSession::GetInstance()
58 s_session
= new DesignerSession();
64 Model
* DesignerSession::GetModel() const
70 if (Designer::GetModel(m_pBaseObject
, pModel
))
77 CBaseObject
* DesignerSession::GetBaseObject() const
82 MainContext
DesignerSession::GetMainContext()
84 MainContext
mc(m_pBaseObject
, GetCompiler(), GetModel());
85 mc
.pSelected
= &m_pSelectedElements
;
89 ModelCompiler
* DesignerSession::GetCompiler() const
91 DESIGNER_ASSERT(m_pBaseObject
);
95 ModelCompiler
* pCompiler
;
96 if (Designer::GetCompiler(m_pBaseObject
, pCompiler
))
103 void DesignerSession::SetBaseObject(CBaseObject
* pBaseObject
)
105 if (m_pBaseObject
== pBaseObject
)
107 m_pBaseObject
= pBaseObject
;
108 signalDesignerEvent(eDesignerNotify_ObjectSelect
, 0);
111 void DesignerSession::OnEditorNotifyEvent(EEditorNotifyEvent event
)
113 bool bExclusiveModeBeforeSave
= false;
114 ElementSet
* pSelected
= GetSelectedElements();
117 case eNotify_OnBeginGameMode
:
118 case eNotify_OnBeginBindViewport
:
119 gDesignerSettings
.bExclusiveMode
= false;
120 gExclusiveModeSettings
.EnableExclusiveMode(gDesignerSettings
.bExclusiveMode
);
122 gDesignerSettings
.Update(true);
123 signalDesignerEvent(eDesignerNotify_SettingsChanged
, nullptr);
126 case eNotify_OnBeginLoad
:
127 case eNotify_OnBeginNewScene
:
128 case eNotify_OnBeginSceneOpen
:
129 // make sure we clear the cache here
132 case eNotify_OnBeginSceneSave
:
133 bExclusiveModeBeforeSave
= gDesignerSettings
.bExclusiveMode
;
134 if (gDesignerSettings
.bExclusiveMode
)
136 gDesignerSettings
.bExclusiveMode
= false;
137 gExclusiveModeSettings
.EnableExclusiveMode(gDesignerSettings
.bExclusiveMode
);
141 case eNotify_OnEndSceneSave
:
142 if (bExclusiveModeBeforeSave
)
144 gDesignerSettings
.bExclusiveMode
= true;
145 gExclusiveModeSettings
.EnableExclusiveMode(gDesignerSettings
.bExclusiveMode
);
146 bExclusiveModeBeforeSave
= false;
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);
176 void DesignerSession::SetCurrentSubMatID(int idx
)
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
)
203 signalDesignerEvent(eDesignerNotify_SubMaterialSelectionChanged
, &evt
);
205 auto pObject
= GetBaseObject();
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
)
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(
262 ModelCompiler
* pCompiler
,
266 std::vector
<PolygonPtr
> polygons
;
268 polygons
.push_back(pPolygon
);
269 UpdateSelectionMesh(polygons
, pCompiler
, pObj
, bForce
);
272 void DesignerSession::UpdateSelectionMesh(
273 std::vector
<PolygonPtr
> polygons
,
274 ModelCompiler
* pCompiler
,
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
);
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
309 const CSelectionGroup
* pSelection
= GetIEditor()->GetObjectManager()->GetSelection();
310 SetBaseObject(pSelection
->GetObject(0));
312 if (!m_bActiveSession
)
316 model
->SetShelf(eShelf_Base
);
318 if (gDesignerSettings
.bExclusiveMode
)
320 if (model
&& model
->IsEmpty())
322 gDesignerSettings
.bExclusiveMode
= false;
323 gDesignerSettings
.Update(true);
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()
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.
381 GetIEditor()->SetEditTool(nullptr);
384 gExclusiveModeSettings
.EnableExclusiveMode(false);
385 signalDesignerEvent(eDesignerNotify_EndDesignerSession
, nullptr);
390 bool DesignerSession::GetIsActive()
392 return m_bActiveSession
;