!B (Sandbox) (CE-21795) Importing models with multisubmaterials via fbx switches...
[CRYENGINE.git] / Code / CryEngine / CrySchematyc2 / BaseEnv / Components / BaseEnv_EntityDetectionVolumeComponent.cpp
blob4302a07b84c6f584d06338c1cd6924352d5b70a1
1 // Copyright 2001-2019 Crytek GmbH / Crytek Group. All rights reserved.
3 #include "StdAfx.h"
4 #include "BaseEnv/Components/BaseEnv_EntityDetectionVolumeComponent.h"
6 #include <CryAnimation/ICryAnimation.h>
7 #include <CryRenderer/IRenderer.h>
8 #include <CryRenderer/IRenderAuxGeom.h>
10 #include "BaseEnv/BaseEnv_AutoRegistrar.h"
11 #include "BaseEnv/BaseEnv_BaseEnv.h"
12 #include "BaseEnv/Components/BaseEnv_EntityGeomComponent.h"
14 namespace SchematycBaseEnv
16 namespace EntityDetectionVolumeComponentUtils
18 struct SPreviewProperties : public Schematyc2::IComponentPreviewProperties
20 SPreviewProperties()
21 : gizmoLength(1.0f)
22 , bShowGizmos(false)
23 , bShowVolumes(false)
26 // Schematyc2::IComponentPreviewProperties
28 virtual void Serialize(Serialization::IArchive& archive) override
30 archive(bShowGizmos, "bShowGizmos", "Show Gizmos");
31 archive(gizmoLength, "gizmoLength", "Gizmo Length");
32 archive(bShowVolumes, "bShowVolumes", "Show Volumes");
35 // ~Schematyc2::IComponentPreviewProperties
37 float gizmoLength;
38 bool bShowGizmos;
39 bool bShowVolumes;
43 const Schematyc2::SGUID CEntityDetectionVolumeComponent::s_componentGUID = "5F0322C0-2EB0-46C7-B3E3-56AB5F200E74";
44 const Schematyc2::SGUID CEntityDetectionVolumeComponent::s_enterSignalGUID = "FBCA030D-7122-41B0-A3AE-BD9EA9E8965E";
45 const Schematyc2::SGUID CEntityDetectionVolumeComponent::s_leaveSignalGUID = "8F2FFE6D-8E74-4B82-B045-051230027AA9";
47 CEntityDetectionVolumeComponent::SVolumeProperties::SVolumeProperties()
48 : size(1.0f)
49 , radius(1.0f)
50 , shape(ESpatialVolumeShape::Box)
53 void CEntityDetectionVolumeComponent::SVolumeProperties::Serialize(Serialization::IArchive& archive)
55 archive(shape, "shape", "Shape");
56 archive.doc("Shape");
58 switch(shape)
60 case ESpatialVolumeShape::Box:
62 archive(size, "size", "Size");
63 archive.doc("Size");
64 break;
66 case ESpatialVolumeShape::Sphere:
68 archive(radius, "radius", "Radius");
69 archive.doc("Radius");
70 break;
74 archive(tags, "tags", "+Tags");
75 archive.doc("Tags");
76 archive(monitorTags, "monitorTags", "+Monitor Tags");
77 archive.doc("Signals will be sent when volumes with one or more of these tags set enter/leave this volume.");
80 CEntityDetectionVolumeComponent::SProperties::SProperties()
81 : bEnabled(true)
84 void CEntityDetectionVolumeComponent::SProperties::Serialize(Serialization::IArchive& archive)
86 archive(TransformDecorator<ETransformComponent::PositionAndRotation>(transform), "transform", "Transform");
87 archive.doc("Transform");
88 archive(volume, "volume", "Volume");
89 archive.doc("Volumes");
92 Schematyc2::SEnvFunctionResult CEntityDetectionVolumeComponent::SProperties::SetTransform(const Schematyc2::SEnvFunctionContext& context, const STransform& _transform)
94 transform = _transform;
95 return Schematyc2::SEnvFunctionResult();
98 CEntityDetectionVolumeComponent::SVolume::SVolume()
99 : rot(IDENTITY)
100 , pos(ZERO)
101 , size(ZERO)
102 , radius(.0f)
103 , shape(ESpatialVolumeShape::None)
106 CEntityDetectionVolumeComponent::CEntityDetectionVolumeComponent()
107 : m_pProperties(nullptr)
108 , m_bEnabled(false)
111 bool CEntityDetectionVolumeComponent::Init(const Schematyc2::SComponentParams& params)
113 if(CEntityTransformComponentBase::Init(params))
115 m_pProperties = params.properties.ToPtr<SProperties>();
116 m_bEnabled = m_pProperties->bEnabled;
118 const EntityId entityId = CEntityComponentBase::GetEntityId();
119 const Matrix34 worldTM = CEntityComponentBase::GetEntity().GetWorldTM();
121 CSpatialIndex& spatialIndex = CBaseEnv::GetInstance().GetSpatialIndex();
122 const SVolumeProperties& volumeProperties = m_pProperties->volume;
124 m_volume.shape = m_pProperties->volume.shape;
125 m_volume.rot = Matrix33::CreateRotationXYZ(m_pProperties->transform.rot);
126 m_volume.size = volumeProperties.size;
127 m_volume.pos = m_pProperties->transform.pos;
128 m_volume.radius = volumeProperties.radius;
130 SSpatialVolumeParams volumeParams;
131 volumeParams.tags = spatialIndex.CreateTags(volumeProperties.tags);
132 volumeParams.monitorTags = spatialIndex.CreateTags(volumeProperties.monitorTags);
133 volumeParams.entityId = entityId;
135 switch(m_volume.shape)
137 case ESpatialVolumeShape::Box:
139 volumeParams.bounds = CSpatialVolumeBounds::CreateOBB(worldTM, m_volume.pos, m_volume.size, m_volume.rot);
140 break;
142 case ESpatialVolumeShape::Sphere:
144 volumeParams.bounds = CSpatialVolumeBounds::CreateSphere(worldTM, m_volume.pos, m_volume.radius);
145 break;
147 case ESpatialVolumeShape::Point:
149 volumeParams.bounds = CSpatialVolumeBounds::CreatePoint(worldTM, m_volume.pos);
150 break;
154 m_volume.volumeId = spatialIndex.CreateVolume(volumeParams, SpatialIndexEventCallback::FromMemberFunction<CEntityDetectionVolumeComponent, &CEntityDetectionVolumeComponent::VolumeEventCallback>(*this));
155 return true;
157 return false;
160 void CEntityDetectionVolumeComponent::Run(Schematyc2::ESimulationMode simulationMode)
162 switch(simulationMode)
164 case Schematyc2::ESimulationMode::Game:
166 gEnv->pSchematyc2->GetUpdateScheduler().Connect(m_updateScope, Schematyc2::UpdateCallback::FromMemberFunction<CEntityDetectionVolumeComponent, &CEntityDetectionVolumeComponent::Update>(*this), Schematyc2::EUpdateFrequency::EveryFrame, Schematyc2::EUpdatePriority::Default, m_updateFilter.Init(&CEntityComponentBase::GetEntity()));
167 g_entityEventSignal.Select(CEntityComponentBase::GetEntityId()).Connect(EntityEventSignal::Delegate::FromMemberFunction<CEntityDetectionVolumeComponent, &CEntityDetectionVolumeComponent::OnEvent>(*this), m_connectionScope);
168 break;
172 if(m_pProperties->bEnabled)
174 Enable();
178 Schematyc2::IComponentPreviewPropertiesPtr CEntityDetectionVolumeComponent::GetPreviewProperties() const
180 static Schematyc2::IComponentPreviewPropertiesPtr previewProperties = std::make_shared<EntityDetectionVolumeComponentUtils::SPreviewProperties>();
181 return previewProperties;
184 void CEntityDetectionVolumeComponent::Preview(const SRendParams& params, const SRenderingPassInfo& passInfo, const Schematyc2::IComponentPreviewProperties& previewProperties) const
186 const EntityDetectionVolumeComponentUtils::SPreviewProperties& previewPropertiesImpl = static_cast<const EntityDetectionVolumeComponentUtils::SPreviewProperties&>(previewProperties);
188 if(previewPropertiesImpl.bShowGizmos)
190 if(CEntityTransformComponentBase::SlotIsValid())
192 IRenderAuxGeom& renderAuxGeom = *gEnv->pRenderer->GetIRenderAuxGeom();
193 const Matrix34 worldTM = CEntityTransformComponentBase::GetWorldTM();
194 const float lineThickness = 4.0f;
196 renderAuxGeom.DrawLine(worldTM.GetTranslation(), ColorB(255, 0, 0, 255), worldTM.GetTranslation() + (worldTM.GetColumn0().GetNormalized() * previewPropertiesImpl.gizmoLength), ColorB(255, 0, 0, 255), lineThickness);
197 renderAuxGeom.DrawLine(worldTM.GetTranslation(), ColorB(0, 255, 0, 255), worldTM.GetTranslation() + (worldTM.GetColumn1().GetNormalized() * previewPropertiesImpl.gizmoLength), ColorB(0, 255, 0, 255), lineThickness);
198 renderAuxGeom.DrawLine(worldTM.GetTranslation(), ColorB(0, 0, 255, 255), worldTM.GetTranslation() + (worldTM.GetColumn2().GetNormalized() * previewPropertiesImpl.gizmoLength), ColorB(0, 0, 255, 255), lineThickness);
202 if(previewPropertiesImpl.bShowVolumes)
204 IRenderAuxGeom& renderAuxGeom = *gEnv->pRenderer->GetIRenderAuxGeom();
205 IEntity& entity = CEntityComponentBase::GetEntity();
206 const Matrix34 worldTM = entity.GetWorldTM();
208 switch(m_volume.shape)
210 case ESpatialVolumeShape::Box:
212 const CSpatialVolumeBounds bounds = CSpatialVolumeBounds::CreateOBB(worldTM, m_volume.pos, m_volume.size, m_volume.rot);
213 renderAuxGeom.DrawOBB(bounds.AsBox(), Matrix34(IDENTITY), false, ColorB(0, 150, 0, 255), eBBD_Faceted);
214 break;
216 case ESpatialVolumeShape::Sphere:
218 SAuxGeomRenderFlags prevRenderFlags = renderAuxGeom.GetRenderFlags();
219 renderAuxGeom.SetRenderFlags(e_Mode3D | e_FillModeWireframe | e_CullModeNone | e_DepthWriteOff | e_DepthTestOn);
220 renderAuxGeom.DrawSphere(worldTM.TransformPoint(m_volume.pos), m_volume.radius, ColorB(0, 150, 0, 64), false);
221 renderAuxGeom.SetRenderFlags(prevRenderFlags);
222 break;
224 case ESpatialVolumeShape::Point:
226 renderAuxGeom.DrawSphere(worldTM.TransformPoint(m_volume.pos), 0.1f, ColorB(0, 150, 0, 64), false);
227 break;
233 void CEntityDetectionVolumeComponent::Shutdown()
235 CSpatialIndex& spatialIndex = CBaseEnv::GetInstance().GetSpatialIndex();
236 spatialIndex.DestroyVolume(m_volume.volumeId);
238 CEntityTransformComponentBase::Shutdown();
241 Schematyc2::INetworkSpawnParamsPtr CEntityDetectionVolumeComponent::GetNetworkSpawnParams() const
243 return Schematyc2::INetworkSpawnParamsPtr();
246 void CEntityDetectionVolumeComponent::Register()
248 Schematyc2::IEnvRegistry& envRegistry = gEnv->pSchematyc2->GetEnvRegistry();
251 Schematyc2::IComponentFactoryPtr pComponentFactory = SCHEMATYC2_MAKE_COMPONENT_FACTORY_SHARED(CEntityDetectionVolumeComponent, SProperties, CEntityDetectionVolumeComponent::s_componentGUID);
252 pComponentFactory->SetName("DetectionVolume");
253 pComponentFactory->SetNamespace("Base");
254 pComponentFactory->SetAuthor("Crytek");
255 pComponentFactory->SetDescription("Entity detection volume component");
256 pComponentFactory->SetFlags(Schematyc2::EComponentFlags::CreatePropertyGraph);
257 pComponentFactory->SetAttachmentType(Schematyc2::EComponentSocket::Parent, g_tranformAttachmentGUID);
258 pComponentFactory->SetAttachmentType(Schematyc2::EComponentSocket::Child, g_tranformAttachmentGUID);
259 envRegistry.RegisterComponentFactory(pComponentFactory);
262 // Functions
265 Schematyc2::CEnvFunctionDescriptorPtr pFunctionDescriptor = Schematyc2::MakeEnvFunctionDescriptorShared(&CEntityDetectionVolumeComponent::SProperties::SetTransform);
266 pFunctionDescriptor->SetGUID("D363B5BC-75BD-4582-8BD8-AA6EC1CD8DAE");
267 pFunctionDescriptor->SetName("SetTransform");
268 pFunctionDescriptor->BindInput(0, 0, "Transform", "");
269 envRegistry.RegisterFunction(pFunctionDescriptor);
273 Schematyc2::IComponentMemberFunctionPtr pFunction = SCHEMATYC2_MAKE_COMPONENT_MEMBER_FUNCTION_SHARED(CEntityDetectionVolumeComponent::SetVolumeSize, "C926DA55-97A2-4C97-A7E6-C1416DD6284A", CEntityDetectionVolumeComponent::s_componentGUID);
274 pFunction->SetAuthor("Crytek");
275 pFunction->SetDescription("Sets the size of the volume.");
276 pFunction->BindInput(0, "X", "Size X", .0f);
277 pFunction->BindInput(1, "Y", "Size Y", .0f);
278 pFunction->BindInput(2, "Z", "Size Z", .0f);
279 envRegistry.RegisterComponentMemberFunction(pFunction);
283 Schematyc2::IComponentMemberFunctionPtr pFunction = SCHEMATYC2_MAKE_COMPONENT_MEMBER_FUNCTION_SHARED(CEntityDetectionVolumeComponent::GetVolumeSize, "E8E87E86-C96B-4948-A298-0FE010E04F2E", CEntityDetectionVolumeComponent::s_componentGUID);
284 pFunction->SetAuthor("Crytek");
285 pFunction->SetDescription("Gets the size of the volume.");
286 pFunction->BindOutput(0, "X", "Size X");
287 pFunction->BindOutput(1, "Y", "Size Y");
288 pFunction->BindOutput(2, "Z", "Size Z");
289 envRegistry.RegisterComponentMemberFunction(pFunction);
293 Schematyc2::IComponentMemberFunctionPtr pFunction = SCHEMATYC2_MAKE_COMPONENT_MEMBER_FUNCTION_SHARED(CEntityDetectionVolumeComponent::SetVolumeRadius, "17FB678F-2256-4F7B-AB46-E8EAACD2497C", CEntityDetectionVolumeComponent::s_componentGUID);
294 pFunction->SetAuthor("Crytek");
295 pFunction->SetDescription("Sets the radius of the volume.");
296 pFunction->BindInput(0, "Radius", "Radius", .0f);
297 envRegistry.RegisterComponentMemberFunction(pFunction);
301 Schematyc2::IComponentMemberFunctionPtr pFunction = SCHEMATYC2_MAKE_COMPONENT_MEMBER_FUNCTION_SHARED(CEntityDetectionVolumeComponent::GetVolumeRadius, "3950621F-8D47-4BE7-836C-35F211B41FBB", CEntityDetectionVolumeComponent::s_componentGUID);
302 pFunction->SetAuthor("Crytek");
303 pFunction->SetDescription("Gets the radius of the volume.");
304 pFunction->BindOutput(0, "Radius", "Radius");
305 envRegistry.RegisterComponentMemberFunction(pFunction);
308 // Signals
311 Schematyc2::ISignalPtr pSignal = envRegistry.CreateSignal(CEntityDetectionVolumeComponent::s_enterSignalGUID);
312 pSignal->SetSenderGUID(CEntityDetectionVolumeComponent::s_componentGUID);
313 pSignal->SetName("EnterVolume");
314 pSignal->SetFileName(SCHEMATYC2_FILE_NAME, "Code");
315 pSignal->SetAuthor("Crytek");
316 pSignal->SetDescription("Sent when an entity enters the volume.");
317 pSignal->AddInput("Volume", "Name of the volume", Schematyc2::CPoolString());
318 pSignal->AddInput("Entity", "Entity entering volume", Schematyc2::ExplicitEntityId());
322 Schematyc2::ISignalPtr pSignal = envRegistry.CreateSignal(CEntityDetectionVolumeComponent::s_leaveSignalGUID);
323 pSignal->SetSenderGUID(CEntityDetectionVolumeComponent::s_componentGUID);
324 pSignal->SetName("LeaveVolume");
325 pSignal->SetFileName(SCHEMATYC2_FILE_NAME, "Code");
326 pSignal->SetAuthor("Crytek");
327 pSignal->SetDescription("Sent when an entity leaves the volume.");
328 pSignal->AddInput("Volume", "Name of the volume", Schematyc2::CPoolString());
329 pSignal->AddInput("Entity", "Entity leaving volume", Schematyc2::ExplicitEntityId());
333 void CEntityDetectionVolumeComponent::SetVolumeSize(float sizeX, float sizeY, float sizeZ)
335 if(m_volume.shape == ESpatialVolumeShape::Box)
337 m_volume.size.x = sizeX;
338 m_volume.size.y = sizeY;
339 m_volume.size.z = sizeZ;
343 void CEntityDetectionVolumeComponent::GetVolumeSize(float& sizeX, float& sizeY, float& sizeZ) const
345 if(m_volume.shape == ESpatialVolumeShape::Box)
347 sizeX = m_volume.size.x;
348 sizeY = m_volume.size.y;
349 sizeZ = m_volume.size.z;
351 else
353 sizeX = sizeY = sizeZ = .0f;
357 void CEntityDetectionVolumeComponent::SetVolumeRadius(float radius)
359 if(m_volume.shape == ESpatialVolumeShape::Sphere)
361 m_volume.radius = radius;
365 float CEntityDetectionVolumeComponent::GetVolumeRadius() const
367 if(m_volume.shape == ESpatialVolumeShape::Sphere)
369 return m_volume.radius;
371 return 0.0f;
374 void CEntityDetectionVolumeComponent::VolumeEventCallback(const SSpatialIndexEvent& event)
376 const SSpatialVolumeParams eventVolumeParams = CBaseEnv::GetInstance().GetSpatialIndex().GetVolumeParams(event.volumeIds[1]);
377 if(eventVolumeParams.entityId != CEntityComponentBase::GetEntityId())
379 const char* szVolumeName = GetVolumeName(event.volumeIds[0]);
380 if(szVolumeName)
382 switch(event.id)
384 case ESpatialIndexEventId::Entering:
386 const IEntity* pEntity = gEnv->pEntitySystem->GetEntity(eventVolumeParams.entityId);
387 CRY_ASSERT(pEntity);
388 if(pEntity)
390 EntityIds::iterator itEntityInArea = std::find(m_entityIds.begin(), m_entityIds.end(), eventVolumeParams.entityId);
391 if(itEntityInArea == m_entityIds.end())
393 m_entityIds.push_back(eventVolumeParams.entityId);
395 Schematyc2::CInPlaceStack stack;
396 Schematyc2::Push(stack, szVolumeName);
397 Schematyc2::Push(stack, Schematyc2::ExplicitEntityId(eventVolumeParams.entityId));
398 CEntityComponentBase::GetObject().ProcessSignal(s_enterSignalGUID, stack);
401 break;
403 case ESpatialIndexEventId::Leaving:
405 EntityIds::iterator itEntityInArea = std::find(m_entityIds.begin(), m_entityIds.end(), eventVolumeParams.entityId);
406 if(itEntityInArea != m_entityIds.end())
408 Schematyc2::CInPlaceStack stack;
409 Schematyc2::Push(stack, szVolumeName);
410 Schematyc2::Push(stack, Schematyc2::ExplicitEntityId(eventVolumeParams.entityId));
411 CEntityComponentBase::GetObject().ProcessSignal(s_leaveSignalGUID, stack);
413 m_entityIds.erase(itEntityInArea);
415 break;
422 void CEntityDetectionVolumeComponent::OnEvent(const SEntityEvent& event)
424 switch(event.event)
426 case ENTITY_EVENT_XFORM:
428 IEntity& entity = CEntityComponentBase::GetEntity();
429 const Matrix34 worldTM = entity.GetWorldTM();
431 CSpatialVolumeBounds bounds;
432 switch(m_volume.shape)
434 case ESpatialVolumeShape::Box:
436 bounds = CSpatialVolumeBounds::CreateOBB(worldTM, m_volume.pos, m_volume.size, m_volume.rot);
437 break;
439 case ESpatialVolumeShape::Sphere:
441 bounds = CSpatialVolumeBounds::CreateSphere(worldTM, m_volume.pos, m_volume.radius);
442 break;
444 case ESpatialVolumeShape::Point:
446 bounds = CSpatialVolumeBounds::CreatePoint(worldTM, m_volume.pos);
447 break;
451 CSpatialIndex& spatialIndex = CBaseEnv::GetInstance().GetSpatialIndex();
452 spatialIndex.UpdateVolumeBounds(m_volume.volumeId, bounds);
454 break;
458 void CEntityDetectionVolumeComponent::Update(const Schematyc2::SUpdateContext& updateContext)
460 CRY_PROFILE_FUNCTION_ARG(PROFILE_GAME, GetEntity().GetName());
462 IEntity& entity = CEntityComponentBase::GetEntity();
463 const Matrix34 worldTM = entity.GetWorldTM();
465 CSpatialVolumeBounds bounds;
466 switch(m_volume.shape)
468 case ESpatialVolumeShape::Box:
470 bounds = CSpatialVolumeBounds::CreateOBB(worldTM, m_volume.pos, m_volume.size, m_volume.rot);
471 break;
473 case ESpatialVolumeShape::Sphere:
475 bounds = CSpatialVolumeBounds::CreateSphere(worldTM, m_volume.pos, m_volume.radius);
476 break;
478 case ESpatialVolumeShape::Point:
480 bounds = CSpatialVolumeBounds::CreatePoint(worldTM, m_volume.pos);
481 break;
485 CSpatialIndex& spatialIndex = CBaseEnv::GetInstance().GetSpatialIndex();
486 spatialIndex.UpdateVolumeBounds(m_volume.volumeId, bounds);
489 const char* CEntityDetectionVolumeComponent::GetVolumeName(SpatialVolumeId volumeId) const
491 // TODO: Retrieve and return the name of the component instance.
492 return nullptr;
495 bool CEntityDetectionVolumeComponent::SetEnabled(bool bEnable)
497 if(bEnable != m_bEnabled)
499 if(bEnable)
501 Enable();
503 else
505 Disable();
508 return m_bEnabled;
511 void CEntityDetectionVolumeComponent::Enable()
513 m_bEnabled = true;
516 void CEntityDetectionVolumeComponent::Disable()
518 m_bEnabled = false;
522 SCHEMATYC2_GAME_ENV_AUTO_REGISTER(&SchematycBaseEnv::CEntityDetectionVolumeComponent::Register)