void ParticleDemo::RegisterParticleGroup(const Ndk::EntityHandle& entity) { NazaraAssert(entity->HasComponent<Ndk::ParticleGroupComponent>(), "Must have particle group component"); m_particleGroups.emplace_back(entity); }
void World::Update() { // Gestion des entités tuées depuis le dernier appel for (unsigned int i = m_killedEntities.FindFirst(); i != m_killedEntities.npos; i = m_killedEntities.FindNext(i)) { EntityBlock& block = m_entities[i]; Entity& entity = block.entity; NazaraAssert(entity.IsValid(), "Entity must be valid"); // Remise en file d'attente de l'identifiant d'entité m_freeIdList.push_back(entity.GetId()); // Destruction de l'entité (invalidation du handle par la même occasion) entity.Destroy(); // Nous allons sortir le handle de la liste des entités vivantes // en swappant le handle avec le dernier handle, avant de pop NazaraAssert(block.aliveIndex < m_aliveEntities.size(), "Alive index out of range"); if (block.aliveIndex < m_aliveEntities.size()-1) // S'il ne s'agit pas du dernier handle { EntityHandle& lastHandle = m_aliveEntities.back(); EntityHandle& myHandle = m_aliveEntities[block.aliveIndex]; myHandle = std::move(lastHandle); // On n'oublie pas de corriger l'indice associé à l'entité m_entities[myHandle->GetId()].aliveIndex = block.aliveIndex; } m_aliveEntities.pop_back(); } m_killedEntities.Reset(); // Gestion des entités nécessitant une mise à jour de leurs systèmes for (unsigned int i = m_dirtyEntities.FindFirst(); i != m_dirtyEntities.npos; i = m_dirtyEntities.FindNext(i)) { NazaraAssert(i < m_entities.size(), "Entity index out of range"); Entity* entity = &m_entities[i].entity; // Check entity validity (as it could have been reported as dirty and killed during the same iteration) if (!entity->IsValid()) continue; for (auto& system : m_systems) { // Ignore non-existent systems if (!system) continue; // Is our entity already part of this system? bool partOfSystem = system->HasEntity(entity); // Should it be part of it? if (entity->IsEnabled() && system->Filters(entity)) { // Yes it should, add it to the system if not already done and validate it (again) if (!partOfSystem) system->AddEntity(entity); system->ValidateEntity(entity, !partOfSystem); } else { // No, it shouldn't, remove it if it's part of the system if (partOfSystem) system->RemoveEntity(entity); } } } m_dirtyEntities.Reset(); }
/*! * \brief Gets the rates of sample in the music * \return Rate of sample in Hertz (Hz) * * \remark Music must be valid when calling this function */ UInt32 Music::GetSampleRate() const { NazaraAssert(m_impl, "Music not created"); return m_impl->sampleRate; }
/*! * \brief Pauses the music * * \remark Music must be valid when calling this function */ void Music::Pause() { NazaraAssert(m_source != InvalidSource, "Invalid sound emitter"); alSourcePause(m_source); }
/*! * \brief Enables the looping of the music * * \param loop Should music loop * * \remark Music must be valid when calling this function */ void Music::EnableLooping(bool loop) { NazaraAssert(m_impl, "Music not created"); m_impl->loop = loop; }
/*! * \brief Gets the format of the music * \return Enumeration of type AudioFormat (mono, stereo, ...) * * \remark Music must be valid when calling this function */ AudioFormat Music::GetFormat() const { NazaraAssert(m_impl, "Music not created"); return m_impl->stream->GetFormat(); }
/*! * \brief Sets the maximum send buffer size * * \param size The new maximum send buffer size in bytes */ void AbstractSocket::SetSendBufferSize(std::size_t size) { NazaraAssert(m_handle != SocketImpl::InvalidHandle, "Socket must be created first"); SocketImpl::SetSendBufferSize(m_handle, size); }
std::vector<HostnameInfo> IpAddress::ResolveHostname(NetProtocol protocol, const String& hostname, const String& service, ResolveError* error) { NazaraAssert(protocol != NetProtocol_Unknown, "Invalid protocol"); return IpAddressImpl::ResolveHostname(protocol, hostname, service, error); }
void TextSprite::Update(const AbstractTextDrawer& drawer) { CallOnExit clearOnFail([this]() { Clear(); }); // Mark every atlas as unused... for (auto& pair : m_atlases) pair.second.used = false; // ... until they are marked as used by the drawer std::size_t fontCount = drawer.GetFontCount(); for (std::size_t i = 0; i < fontCount; ++i) { Font* font = drawer.GetFont(i); const AbstractAtlas* atlas = font->GetAtlas().get(); NazaraAssert(atlas->GetStorage() & DataStorage_Hardware, "Font uses a non-hardware atlas which cannot be used by text sprites"); auto it = m_atlases.find(atlas); if (it == m_atlases.end()) { it = m_atlases.insert(std::make_pair(atlas, AtlasSlots())).first; AtlasSlots& atlasSlots = it->second; atlasSlots.clearSlot.Connect(atlas->OnAtlasCleared, this, &TextSprite::OnAtlasInvalidated); atlasSlots.layerChangeSlot.Connect(atlas->OnAtlasLayerChange, this, &TextSprite::OnAtlasLayerChange); atlasSlots.releaseSlot.Connect(atlas->OnAtlasRelease, this, &TextSprite::OnAtlasInvalidated); } it->second.used = true; } // Remove unused atlas slots auto atlasIt = m_atlases.begin(); while (atlasIt != m_atlases.end()) { if (!atlasIt->second.used) m_atlases.erase(atlasIt++); else ++atlasIt; } std::size_t glyphCount = drawer.GetGlyphCount(); m_localVertices.resize(glyphCount * 4); // Reset glyph count for every texture to zero for (auto& pair : m_renderInfos) pair.second.count = 0; // Count glyph count for each texture Texture* lastTexture = nullptr; unsigned int* count = nullptr; for (std::size_t i = 0; i < glyphCount; ++i) { const AbstractTextDrawer::Glyph& glyph = drawer.GetGlyph(i); Texture* texture = static_cast<Texture*>(glyph.atlas); if (lastTexture != texture) { auto it = m_renderInfos.find(texture); if (it == m_renderInfos.end()) it = m_renderInfos.insert(std::make_pair(texture, RenderIndices{0U, 0U})).first; count = &it->second.count; lastTexture = texture; } (*count)++; } // Attributes indices and reinitialize glyph count to zero to use it as a counter in the next loop // This is because the 1st glyph can use texture A, the 2nd glyph can use texture B and the 3th glyph C can use texture A again // so we need a counter to know where to write informations // also remove unused render infos unsigned int index = 0; auto infoIt = m_renderInfos.begin(); while (infoIt != m_renderInfos.end()) { RenderIndices& indices = infoIt->second; if (indices.count == 0) m_renderInfos.erase(infoIt++); //< No glyph uses this texture, remove from indices else { indices.first = index; index += indices.count; indices.count = 0; ++infoIt; } } lastTexture = nullptr; RenderIndices* indices = nullptr; for (unsigned int i = 0; i < glyphCount; ++i) { const AbstractTextDrawer::Glyph& glyph = drawer.GetGlyph(i); Texture* texture = static_cast<Texture*>(glyph.atlas); if (lastTexture != texture) { indices = &m_renderInfos[texture]; //< We changed texture, adjust the pointer lastTexture = texture; } // First, compute the uv coordinates from our atlas rect Vector2ui size(texture->GetSize()); float invWidth = 1.f / size.x; float invHeight = 1.f / size.y; Rectf uvRect(glyph.atlasRect); uvRect.x *= invWidth; uvRect.y *= invHeight; uvRect.width *= invWidth; uvRect.height *= invHeight; // Our glyph may be flipped in the atlas, to render it correctly we need to change the uv coordinates accordingly const RectCorner normalCorners[4] = {RectCorner_LeftTop, RectCorner_RightTop, RectCorner_LeftBottom, RectCorner_RightBottom}; const RectCorner flippedCorners[4] = {RectCorner_LeftBottom, RectCorner_LeftTop, RectCorner_RightBottom, RectCorner_RightTop}; // Set the position, color and UV of our vertices for (unsigned int j = 0; j < 4; ++j) { // Remember that indices->count is a counter here, not a count value m_localVertices[indices->count * 4 + j].color = glyph.color; m_localVertices[indices->count * 4 + j].position.Set(glyph.corners[j]); m_localVertices[indices->count * 4 + j].uv.Set(uvRect.GetCorner((glyph.flipped) ? flippedCorners[j] : normalCorners[j])); } // Increment the counter, go to next glyph indices->count++; } m_localBounds = drawer.GetBounds(); InvalidateBoundingVolume(); InvalidateInstanceData(0); clearOnFail.Reset(); }
/*! * \brief Queries the maximum socket send buffer size * \return The size of the send buffer in bytes. */ std::size_t AbstractSocket::QuerySendBufferSize() const { NazaraAssert(m_handle != SocketImpl::InvalidHandle, "Socket must be created first"); return SocketImpl::QuerySendBufferSize(m_handle); }
void ParticleGroup::AddController(ParticleControllerRef controller) { NazaraAssert(controller, "Invalid particle controller"); m_controllers.emplace_back(std::move(controller)); }
void ParticleGroup::AddGenerator(ParticleGeneratorRef generator) { NazaraAssert(generator, "Invalid particle generator"); m_generators.emplace_back(std::move(generator)); }
bool TcpClient::ReceivePacket(NetPacket* packet) { //TODO: Every packet requires at least two Receive call, using an internal buffer of a fixed size would prevent this NazaraAssert(packet, "Invalid packet"); if (!m_pendingPacket.headerReceived) { m_pendingPacket.data.Resize(NetPacket::HeaderSize); std::size_t received; if (!Receive(&m_pendingPacket.data[m_pendingPacket.received], NetPacket::HeaderSize - m_pendingPacket.received, &received)) return false; m_pendingPacket.received += received; //TODO: Should never happen in production ! NazaraAssert(m_pendingPacket.received <= NetPacket::HeaderSize, "Received more data than header size"); if (m_pendingPacket.received >= NetPacket::HeaderSize) { UInt16 size; if (!NetPacket::DecodeHeader(m_pendingPacket.data.GetConstBuffer(), &size, &m_pendingPacket.netcode)) { m_lastError = SocketError_Packet; NazaraWarning("Invalid header data"); return false; } m_pendingPacket.data.Resize(size - NetPacket::HeaderSize); m_pendingPacket.headerReceived = true; m_pendingPacket.received = 0; } } // We may have just received the header now if (m_pendingPacket.headerReceived) { UInt16 packetSize = static_cast<UInt16>(m_pendingPacket.data.GetSize()); //< Total packet size if (packetSize == 0) { // Special case: our packet carry no data packet->Reset(m_pendingPacket.netcode); // And reset every state m_pendingPacket.data.Clear(); m_pendingPacket.headerReceived = false; m_pendingPacket.received = 0; return true; } std::size_t received; if (!Receive(&m_pendingPacket.data[m_pendingPacket.received], packetSize - m_pendingPacket.received, &received)) return false; m_pendingPacket.received += received; //TODO: Should never happen in production ! NazaraAssert(m_pendingPacket.received <= packetSize, "Received more data than packet size"); if (m_pendingPacket.received >= packetSize) { // Okay we received the whole packet, copy it packet->Reset(m_pendingPacket.netcode, m_pendingPacket.data.GetConstBuffer(), m_pendingPacket.data.GetSize()); // And reset every state m_pendingPacket.data.Clear(); m_pendingPacket.headerReceived = false; m_pendingPacket.received = 0; return true; } } return false; }
const Primitive& PrimitiveList::GetPrimitive(std::size_t i) const { NazaraAssert(i < m_primitives.size(), "Primitive index out of range"); return m_primitives[i]; }
void ConditionVariable::Wait(Mutex* mutex) { NazaraAssert(mutex != nullptr, "Mutex must be valid"); m_impl->Wait(mutex->m_impl); }
String IpAddress::ToString() const { StringStream stream; if (m_isValid) { NazaraAssert(m_protocol <= NetProtocol_Max, "Protocol has value out of enum"); switch (m_protocol) { case NetProtocol_Any: case NetProtocol_Unknown: break; case NetProtocol_IPv4: for (unsigned int i = 0; i < 4; ++i) { stream << int(m_ipv4[i]); if (i != 3) stream << '.'; } break; case NetProtocol_IPv6: // Canonical representation of an IPv6 // https://tools.ietf.org/html/rfc5952 // Find the longest zero sequence unsigned int f0 = std::numeric_limits<unsigned int>::max(); unsigned int l0 = std::numeric_limits<unsigned int>::max(); for (unsigned int i = 0; i < 8; ++i) { if (m_ipv6[i] == 0) { unsigned int j; for (j = i + 1; j < 8; ++j) { if (m_ipv6[j] != 0) break; } if (j - i > std::max<unsigned int>(l0 - f0, 1)) { f0 = i; l0 = j; } } } // We need brackets around our IPv6 address if we have a port if (m_port != 0) stream << '['; for (unsigned int i = 0; i < 8; ++i) { if (i == f0) { stream << "::"; i = l0; if (i >= 8) break; } else if (i != 0) stream << ':'; stream << String::Number(m_ipv6[i], 16).ToLower(); } if (m_port != 0) stream << ']'; break; } if (m_port != 0) stream << ':' << m_port; } return stream; }
bool ConditionVariable::Wait(Mutex* mutex, UInt32 timeout) { NazaraAssert(mutex != nullptr, "Mutex must be valid"); return m_impl->Wait(mutex->m_impl, timeout); }
std::size_t UdpSocket::QueryMaxDatagramSize() { NazaraAssert(m_handle != SocketImpl::InvalidHandle, "Socket hasn't been created"); return SocketImpl::QueryMaxDatagramSize(m_handle, &m_lastError); }
bool DeferredPhongLightingPass::Process(const SceneData& sceneData, unsigned int firstWorkTexture, unsigned secondWorkTexture) const { NazaraAssert(sceneData.viewer, "Invalid viewer"); NazaraUnused(secondWorkTexture); m_workRTT->SetColorTarget(firstWorkTexture); Renderer::SetTarget(m_workRTT); Renderer::SetViewport(Recti(0, 0, m_dimensions.x, m_dimensions.y)); Renderer::SetTexture(0, m_GBuffer[0]); Renderer::SetTextureSampler(0, m_pointSampler); Renderer::SetTexture(1, m_GBuffer[1]); Renderer::SetTextureSampler(1, m_pointSampler); Renderer::SetTexture(2, m_GBuffer[2]); Renderer::SetTextureSampler(2, m_pointSampler); Renderer::SetClearColor(Color::Black); Renderer::Clear(RendererBuffer_Color); RenderStates lightStates; lightStates.dstBlend = BlendFunc_One; lightStates.srcBlend = BlendFunc_One; lightStates.parameters[RendererParameter_Blend] = true; lightStates.parameters[RendererParameter_DepthBuffer] = false; lightStates.parameters[RendererParameter_DepthWrite] = false; // Directional lights if (!m_renderQueue->directionalLights.empty()) { Renderer::SetRenderStates(lightStates); Renderer::SetShader(m_directionalLightShader); m_directionalLightShader->SendColor(m_directionalLightShaderSceneAmbientLocation, sceneData.ambientColor); m_directionalLightShader->SendVector(m_directionalLightShaderEyePositionLocation, sceneData.viewer->GetEyePosition()); for (auto& light : m_renderQueue->directionalLights) { m_directionalLightShader->SendColor(m_directionalLightUniforms.locations.color, light.color); m_directionalLightShader->SendVector(m_directionalLightUniforms.locations.factors, Vector2f(light.ambientFactor, light.diffuseFactor)); m_directionalLightShader->SendVector(m_directionalLightUniforms.locations.parameters1, Vector4f(light.direction)); Renderer::DrawFullscreenQuad(); } } // Point lights/Spot lights if (!m_renderQueue->pointLights.empty() || !m_renderQueue->spotLights.empty()) { // http://www.altdevblogaday.com/2011/08/08/stencil-buffer-optimisation-for-deferred-lights/ lightStates.parameters[RendererParameter_StencilTest] = true; lightStates.faceCulling = FaceSide_Front; lightStates.backFace.stencilMask = 0xFF; lightStates.backFace.stencilReference = 0; lightStates.backFace.stencilFail = StencilOperation_Keep; lightStates.backFace.stencilPass = StencilOperation_Keep; lightStates.backFace.stencilZFail = StencilOperation_Invert; lightStates.frontFace.stencilMask = 0xFF; lightStates.frontFace.stencilReference = 0; lightStates.frontFace.stencilFail = StencilOperation_Keep; lightStates.frontFace.stencilPass = StencilOperation_Keep; lightStates.frontFace.stencilZFail = StencilOperation_Invert; Renderer::SetRenderStates(lightStates); Renderer::SetShader(m_pointSpotLightShader); m_pointSpotLightShader->SendColor(m_pointSpotLightShaderSceneAmbientLocation, sceneData.ambientColor); m_pointSpotLightShader->SendVector(m_pointSpotLightShaderEyePositionLocation, sceneData.viewer->GetEyePosition()); Matrix4f lightMatrix; lightMatrix.MakeIdentity(); if (!m_renderQueue->pointLights.empty()) { const IndexBuffer* indexBuffer = m_sphereMesh->GetIndexBuffer(); Renderer::SetIndexBuffer(indexBuffer); Renderer::SetVertexBuffer(m_sphereMesh->GetVertexBuffer()); m_pointSpotLightShader->SendInteger(m_pointSpotLightUniforms.locations.type, LightType_Point); for (const auto& light : m_renderQueue->pointLights) { m_pointSpotLightShader->SendColor(m_pointSpotLightUniforms.locations.color, light.color); m_pointSpotLightShader->SendVector(m_pointSpotLightUniforms.locations.factors, Vector2f(light.ambientFactor, light.diffuseFactor)); m_pointSpotLightShader->SendVector(m_pointSpotLightUniforms.locations.parameters1, Vector4f(light.position, light.attenuation)); m_pointSpotLightShader->SendVector(m_pointSpotLightUniforms.locations.parameters2, Vector4f(0.f, 0.f, 0.f, light.invRadius)); lightMatrix.SetScale(Vector3f(light.radius * 1.1f)); // Pour corriger les imperfections liées à la sphère lightMatrix.SetTranslation(light.position); Renderer::SetMatrix(MatrixType_World, lightMatrix); // Rendu de la sphère dans le stencil buffer Renderer::Enable(RendererParameter_ColorWrite, false); Renderer::Enable(RendererParameter_DepthBuffer, true); Renderer::Enable(RendererParameter_FaceCulling, false); Renderer::SetStencilCompareFunction(RendererComparison_Always); m_pointSpotLightShader->SendBoolean(m_pointSpotLightShaderDiscardLocation, true); Renderer::DrawIndexedPrimitives(PrimitiveMode_TriangleList, 0, indexBuffer->GetIndexCount()); // Rendu de la sphère comme zone d'effet Renderer::Enable(RendererParameter_ColorWrite, true); Renderer::Enable(RendererParameter_DepthBuffer, false); Renderer::Enable(RendererParameter_FaceCulling, true); Renderer::SetStencilCompareFunction(RendererComparison_NotEqual, FaceSide_Back); Renderer::SetStencilPassOperation(StencilOperation_Zero, FaceSide_Back); m_pointSpotLightShader->SendBoolean(m_pointSpotLightShaderDiscardLocation, false); Renderer::DrawIndexedPrimitives(PrimitiveMode_TriangleList, 0, indexBuffer->GetIndexCount()); } if (m_lightMeshesDrawing) { Renderer::Enable(RendererParameter_DepthBuffer, true); Renderer::Enable(RendererParameter_DepthWrite, true); Renderer::Enable(RendererParameter_FaceCulling, false); Renderer::Enable(RendererParameter_StencilTest, false); Renderer::SetFaceFilling(FaceFilling_Line); const Shader* shader = ShaderLibrary::Get("DebugSimple"); static int colorLocation = shader->GetUniformLocation("Color"); Renderer::SetShader(shader); for (const auto& light : m_renderQueue->pointLights) { lightMatrix.SetScale(Vector3f(light.radius * 1.1f)); // Pour corriger les imperfections liées à la sphère lightMatrix.SetTranslation(light.position); Renderer::SetMatrix(MatrixType_World, lightMatrix); shader->SendColor(colorLocation, light.color); Renderer::DrawIndexedPrimitives(PrimitiveMode_TriangleList, 0, indexBuffer->GetIndexCount()); } Renderer::Enable(RendererParameter_DepthBuffer, false); Renderer::Enable(RendererParameter_DepthWrite, false); Renderer::Enable(RendererParameter_FaceCulling, true); Renderer::Enable(RendererParameter_StencilTest, true); Renderer::SetFaceFilling(FaceFilling_Fill); } } if (!m_renderQueue->spotLights.empty()) { const IndexBuffer* indexBuffer = m_coneMesh->GetIndexBuffer(); Renderer::SetIndexBuffer(indexBuffer); Renderer::SetVertexBuffer(m_coneMesh->GetVertexBuffer()); m_pointSpotLightShader->SendInteger(m_pointSpotLightUniforms.locations.type, LightType_Spot); for (const auto& light : m_renderQueue->spotLights) { m_pointSpotLightShader->SendColor(m_pointSpotLightUniforms.locations.color, light.color); m_pointSpotLightShader->SendVector(m_pointSpotLightUniforms.locations.factors, Vector2f(light.ambientFactor, light.diffuseFactor)); m_pointSpotLightShader->SendVector(m_pointSpotLightUniforms.locations.parameters1, Vector4f(light.position, light.attenuation)); m_pointSpotLightShader->SendVector(m_pointSpotLightUniforms.locations.parameters2, Vector4f(light.direction, light.invRadius)); m_pointSpotLightShader->SendVector(m_pointSpotLightUniforms.locations.parameters3, Vector2f(light.innerAngleCosine, light.outerAngleCosine)); float baseRadius = light.radius * light.outerAngleTangent * 1.1f; lightMatrix.MakeTransform(light.position, Quaternionf::RotationBetween(Vector3f::Forward(), light.direction), Vector3f(baseRadius, baseRadius, light.radius)); Renderer::SetMatrix(MatrixType_World, lightMatrix); // Rendu de la sphère dans le stencil buffer Renderer::Enable(RendererParameter_ColorWrite, false); Renderer::Enable(RendererParameter_DepthBuffer, true); Renderer::Enable(RendererParameter_FaceCulling, false); Renderer::SetStencilCompareFunction(RendererComparison_Always); m_pointSpotLightShader->SendBoolean(m_pointSpotLightShaderDiscardLocation, true); Renderer::DrawIndexedPrimitives(PrimitiveMode_TriangleList, 0, indexBuffer->GetIndexCount()); // Rendu de la sphère comme zone d'effet Renderer::Enable(RendererParameter_ColorWrite, true); Renderer::Enable(RendererParameter_DepthBuffer, false); Renderer::Enable(RendererParameter_FaceCulling, true); Renderer::SetFaceCulling(FaceSide_Front); Renderer::SetStencilCompareFunction(RendererComparison_NotEqual, FaceSide_Back); Renderer::SetStencilPassOperation(StencilOperation_Zero, FaceSide_Back); m_pointSpotLightShader->SendBoolean(m_pointSpotLightShaderDiscardLocation, false); Renderer::DrawIndexedPrimitives(PrimitiveMode_TriangleList, 0, indexBuffer->GetIndexCount()); } if (m_lightMeshesDrawing) { Renderer::Enable(RendererParameter_DepthBuffer, true); Renderer::Enable(RendererParameter_DepthWrite, true); Renderer::Enable(RendererParameter_FaceCulling, false); Renderer::Enable(RendererParameter_StencilTest, false); Renderer::SetFaceFilling(FaceFilling_Line); const Shader* shader = ShaderLibrary::Get("DebugSimple"); static int colorLocation = shader->GetUniformLocation("Color"); Renderer::SetShader(shader); for (const auto& light : m_renderQueue->spotLights) { float baseRadius = light.radius * light.outerAngleTangent * 1.1f; lightMatrix.MakeTransform(light.position, Quaternionf::RotationBetween(Vector3f::Forward(), light.direction), Vector3f(baseRadius, baseRadius, light.radius)); Renderer::SetMatrix(MatrixType_World, lightMatrix); shader->SendColor(colorLocation, light.color); Renderer::DrawIndexedPrimitives(PrimitiveMode_TriangleList, 0, indexBuffer->GetIndexCount()); } Renderer::Enable(RendererParameter_DepthBuffer, false); Renderer::Enable(RendererParameter_DepthWrite, false); Renderer::Enable(RendererParameter_FaceCulling, true); Renderer::Enable(RendererParameter_StencilTest, true); Renderer::SetFaceFilling(FaceFilling_Fill); } } Renderer::Enable(RendererParameter_StencilTest, false); } return true; }
/*! * \brief Gets the duration of the music * \return Duration of the music in milliseconds * * \remark Music must be valid when calling this function */ UInt32 Music::GetDuration() const { NazaraAssert(m_impl, "Music not created"); return m_impl->stream->GetDuration(); }
/*! * \brief Plays the music * * \remark Produces a NazaraError if the sound is not playable with NAZARA_AUDIO_SAFE defined */ void Sound::Play() { NazaraAssert(IsPlayable(), "Music is not playable"); alSourcePlay(m_source); }
/*! * \brief Gets the number of samples in the music * \return Count of samples (number of seconds * sample rate * channel count) * * \remark Music must be valid when calling this function */ UInt64 Music::GetSampleCount() const { NazaraAssert(m_impl, "Music not created"); return m_impl->stream->GetSampleCount(); }
/*! * \brief Gets the duration of the sound * \return Duration of the music in milliseconds * * \remark Produces a NazaraError if there is no buffer */ UInt32 Sound::GetDuration() const { NazaraAssert(m_buffer, "Invalid sound buffer"); return m_buffer->GetDuration(); }
/*! * \brief Checks whether the music is looping * \return true if it is the case * * \remark Music must be valid when calling this function */ bool Music::IsLooping() const { NazaraAssert(m_impl, "Music not created"); return m_impl->loop; }
/*! * \brief Changes the debugging name associated to the calling thread * * Changes the debugging name associated with the calling thread, and may helps with debugging tools. * * \param name The new name associated with this thread * * \remark Due to system limitations, thread name cannot exceed 15 characters (excluding null-terminator) * * \see SetName */ void Thread::SetCurrentThreadName(const String& name) { NazaraAssert(name.GetSize() < 16, "Thread name is too long"); ThreadImpl::SetCurrentName(name); }
void DepthRenderQueue::AddPointLight(const PointLight& light) { NazaraAssert(false, "Depth render queue doesn't handle lights"); NazaraUnused(light); }
void PhysicsSystem3D::CreatePhysWorld() const { NazaraAssert(!m_world, "Physics world should not be created twice"); m_world = std::make_unique<Nz::PhysWorld3D>(); }