void OnMouseDown(UINT button, int x, int y) { XOrientation camOrient; cameraEntity->GetOrientation(&camOrient); if (button == 0) cameraControl = true; //shoot a cube else if (button == 1) { Entity* pCube = g_pScene->CreateEntity(); g_pSelectedEntity = pCube; pCube->SetPosition(cameraEntity->GetPosition() + camOrient.z); pCube->SetVelocity(0.1f * camOrient.z); //pCube->SetMaxLifeTime(5.0f); MeshComponent* pMesh = new MeshComponent(pCube); pMesh->SetMeshResource("cube.nfm"); BodyComponent* pBody = new BodyComponent(pCube); pBody->SetMass(10.0f); pBody->EnablePhysics((CollisionShape*)EngineGetResource(ResourceType::COLLISION_SHAPE, "shape_box")); OmniLightDesc lightDesc; lightDesc.radius = 4.0f; lightDesc.shadowFadeStart = 20.0; lightDesc.shadowFadeEnd = 30.0; Entity* pLightEntity = g_pScene->CreateEntity(); pCube->Attach(pLightEntity); //pLightEntity->SetLocalPosition(Vector(0.0f, 1.0f, 0.0f)); LightComponent* pLight = new LightComponent(pLightEntity); pLight->SetOmniLight(&lightDesc); pLight->SetColor(Float3(1.0f, 1.0f, 10.0f)); pLight->SetShadowMap(0); } else { Entity* pBarrel = g_pScene->CreateEntity(); g_pSelectedEntity = pBarrel; pBarrel->SetPosition(cameraEntity->GetPosition() + camOrient.z); pBarrel->SetVelocity(30.0f * camOrient.z); MeshComponent* pMesh = new MeshComponent(pBarrel); pMesh->SetMeshResource("barrel.nfm"); BodyComponent* pBody = new BodyComponent(pBarrel); pBody->SetMass(20.0f); pBody->EnablePhysics((CollisionShape*)EngineGetResource(ResourceType::COLLISION_SHAPE, "shape_barrel")); } }
/// Create an entity in this world. /// /// @param[in] pLayer Layer in which to create the entity. /// @param[in] pType Entity type. /// @param[in] rPosition Entity position. /// @param[in] rRotation Entity rotation. /// @param[in] rScale Entity scale. /// @param[in] pTemplate Template from which to create the entity. /// @param[in] name GameObject name to assign to the entity, or a null name to automatically generate a /// name based on the entity type. /// @param[in] bAssignInstanceIndex True to assign an instance index to the entity, false to not include an /// instance index. /// /// @return Pointer to the entity instance if created successfully, null if not. /// /// @see DestroyEntity() Entity* World::CreateEntity( Layer* pLayer, const GameObjectType* pType, const Simd::Vector3& rPosition, const Simd::Quat& rRotation, const Simd::Vector3& rScale, Entity* pTemplate, Name name, bool bAssignInstanceIndex ) { // Make sure the destination layer is valid. HELIUM_ASSERT( pLayer ); if( !pLayer ) { HELIUM_TRACE( TRACE_ERROR, TXT( "World::CreateEntity(): Missing entity layer.\n" ) ); return NULL; } World* pLayerWorld = pLayer->GetWorld(); HELIUM_ASSERT( pLayerWorld == this ); if( pLayerWorld != this ) { HELIUM_TRACE( TRACE_ERROR, TXT( "World::CreateEntity(): Layer \"%s\" is not bound to world \"%s\".\n" ), *pLayer->GetPath().ToString(), *GetPath().ToString() ); return NULL; } // Attempt to create the entity. Entity* pEntity = pLayer->CreateEntity( pType, rPosition, rRotation, rScale, pTemplate, name, bAssignInstanceIndex ); if( !pEntity ) { HELIUM_TRACE( TRACE_ERROR, TXT( "World::CreateEntity(): Failed to create entity in world \"%s\", layer \"%s\".\n" ), *GetPath().ToString(), *pLayer->GetPath().ToString() ); return NULL; } // Attach the entity to the world. pEntity->Attach(); return pEntity; }
/// Add a layer to this world. /// /// @param[in] pLayer Layer to add. /// /// @return True if the layer was added successfully, false if not. /// /// @see RemoveLayer() bool World::AddLayer( Layer* pLayer ) { // Make sure a valid layer not already attached to a world was specified. HELIUM_ASSERT( pLayer ); if( !pLayer ) { HELIUM_TRACE( TRACE_ERROR, TXT( "World::AddLayer(): Null layer specified.\n" ) ); return false; } World* pExistingWorld = pLayer->GetWorld(); HELIUM_ASSERT( !pExistingWorld ); if( pExistingWorld ) { HELIUM_TRACE( TRACE_ERROR, TXT( "World::AddLayer(): Layer \"%s\" is already bound to world \"%s\".\n" ), *pLayer->GetPath().ToString(), *pExistingWorld->GetPath().ToString() ); return false; } // Add the layer to our layer list and set it referencing back to this world. size_t layerIndex = m_layers.Push( LayerPtr( pLayer ) ); HELIUM_ASSERT( IsValid( layerIndex ) ); pLayer->SetWorldInfo( this, layerIndex ); // Attach all entities in the layer. size_t entityCount = pLayer->GetEntityCount(); for( size_t entityIndex = 0; entityIndex < entityCount; ++entityIndex ) { Entity* pEntity = pLayer->GetEntity( entityIndex ); HELIUM_ASSERT( pEntity ); pEntity->Attach(); } return true; }
/// Update all worlds for the current frame. void WorldManager::Update() { // Update the world time. UpdateTime(); // Perform the entity pre-update. m_updatePhase = UPDATE_PHASE_PRE; { JobContext::Spawner< 1 > entityUpdateSpawner; JobContext* pContext = entityUpdateSpawner.Allocate(); HELIUM_ASSERT( pContext ); WorldManagerUpdate< EntityPreUpdate >* pJob = pContext->Create< WorldManagerUpdate< EntityPreUpdate > >(); HELIUM_ASSERT( pJob ); WorldManagerUpdate< EntityPreUpdate >::Parameters& rParameters = pJob->GetParameters(); rParameters.pspWorlds = m_worlds.GetData(); rParameters.worldCount = m_worlds.GetSize(); } // Perform the entity post-update. m_updatePhase = UPDATE_PHASE_POST; { JobContext::Spawner< 1 > entityUpdateSpawner; JobContext* pContext = entityUpdateSpawner.Allocate(); HELIUM_ASSERT( pContext ); WorldManagerUpdate< EntityPostUpdate >* pJob = pContext->Create< WorldManagerUpdate< EntityPostUpdate > >(); HELIUM_ASSERT( pJob ); WorldManagerUpdate< EntityPostUpdate >::Parameters& rParameters = pJob->GetParameters(); rParameters.pspWorlds = m_worlds.GetData(); rParameters.worldCount = m_worlds.GetSize(); } // Perform the entity synchronous update. m_updatePhase = UPDATE_PHASE_SYNCHRONOUS; size_t worldCount = m_worlds.GetSize(); for( size_t worldIndex = 0; worldIndex < worldCount; ++worldIndex ) { World* pWorld = m_worlds[ worldIndex ]; HELIUM_ASSERT( pWorld ); size_t layerCount = pWorld->GetLayerCount(); for( size_t layerIndex = 0; layerIndex < layerCount; ++layerIndex ) { Layer* pLayer = pWorld->GetLayer( layerIndex ); HELIUM_ASSERT( pLayer ); size_t entityCount = pLayer->GetEntityCount(); for( size_t entityIndex = 0; entityIndex < entityCount; ++entityIndex ) { Entity* pEntity = pLayer->GetEntity( entityIndex ); HELIUM_ASSERT( pEntity ); bool bNeedsSynchronousUpdate = pEntity->NeedsSynchronousUpdate(); uint32_t deferredWorkFlags = pEntity->GetDeferredWorkFlags(); if( !bNeedsSynchronousUpdate && !deferredWorkFlags ) { continue; } if( deferredWorkFlags & Entity::DEFERRED_WORK_FLAG_DESTROY ) { pLayer->DestroyEntity( pEntity ); --entityIndex; // Only the current entity should be destroyed; entity destruction should not trigger the // immediate creation or destruction of other entities. --entityCount; HELIUM_ASSERT( pLayer->GetEntityCount() == entityCount ); continue; } // Entity::NeedsSynchronousUpdate() also checks the deferred work flags. if( bNeedsSynchronousUpdate /*deferredWorkFlags & Entity::DEFERRED_WORK_FLAG_UPDATE*/ ) { pEntity->SynchronousUpdate( m_frameDeltaSeconds ); // Update the entity count in case a new entity was created during the synchronous update. entityCount = pLayer->GetEntityCount(); HELIUM_ASSERT( entityIndex < entityCount ); // Update the deferred work flags and reassess entity destruction after the synchronous update. deferredWorkFlags = pEntity->GetDeferredWorkFlags(); if( deferredWorkFlags & Entity::DEFERRED_WORK_FLAG_DESTROY ) { pLayer->DestroyEntity( pEntity ); --entityIndex; // Only the current entity should be destroyed; entity destruction should not trigger the // immediate creation or destruction of other entities. --entityCount; HELIUM_ASSERT( pLayer->GetEntityCount() == entityCount ); continue; } } if( deferredWorkFlags & Entity::DEFERRED_WORK_FLAG_REATTACH ) { pEntity->Detach(); pEntity->Attach(); // Entities should only be spawned during the synchronous update call, so the count should not // have changed as a result of reattachment. HELIUM_ASSERT( pLayer->GetEntityCount() == entityCount ); } pEntity->ClearDeferredWorkFlags(); } } } m_updatePhase = UPDATE_PHASE_INVALID; // Update the graphics scene for each world. for( size_t worldIndex = 0; worldIndex < worldCount; ++worldIndex ) { World* pWorld = m_worlds[ worldIndex ]; HELIUM_ASSERT( pWorld ); pWorld->UpdateGraphicsScene(); } }