void ezPipeChannel_win::OnIOCompleted(IOContext* pContext, DWORD uiBytesTransfered, DWORD uiError) { EZ_ASSERT_DEBUG(m_ThreadId == ezThreadUtils::GetCurrentThreadID(), "Function must be called from worker thread!"); bool bRes = true; if (pContext == &m_InputState.Context) { if (!m_Connected) { if (!ProcessConnection()) return; bool bHasOutput = false; { EZ_LOCK(m_OutputQueueMutex); bHasOutput = !m_OutputQueue.IsEmpty(); } if (bHasOutput && m_OutputState.IsPending == 0) ProcessOutgoingMessages(0); if (m_InputState.IsPending) return; } bRes = ProcessIncomingMessages(uiBytesTransfered); } else { EZ_ASSERT_DEBUG(pContext == &m_OutputState.Context, ""); bRes = ProcessOutgoingMessages(uiBytesTransfered); } if (!bRes && m_PipeHandle != INVALID_HANDLE_VALUE) { InternalDisconnect(); } }
bool ezPipeChannel_win::ProcessOutgoingMessages(DWORD uiBytesWritten) { EZ_ASSERT_DEBUG(m_Connected, "Must be connected to process outgoing messages."); EZ_ASSERT_DEBUG(m_ThreadId == ezThreadUtils::GetCurrentThreadID(), "Function must be called from worker thread!"); if (m_OutputState.IsPending) { if (uiBytesWritten == 0) { // Don't reset isPending right away as we want to use it to decide // whether we need to wake up the worker thread again. ezLog::Error("pipe error: {0}", ezArgErrorCode(GetLastError())); m_OutputState.IsPending = false; return false; } EZ_LOCK(m_OutputQueueMutex); //message was send m_OutputQueue.PopFront(); } if (m_PipeHandle == INVALID_HANDLE_VALUE) { m_OutputState.IsPending = false; return false; } const ezMemoryStreamStorage* storage = nullptr; { EZ_LOCK(m_OutputQueueMutex); if (m_OutputQueue.IsEmpty()) { m_OutputState.IsPending = false; return true; } storage = &m_OutputQueue.PeekFront(); } BOOL res = WriteFile(m_PipeHandle, storage->GetData(), storage->GetStorageSize(), &uiBytesWritten, &m_OutputState.Context.Overlapped); if (!res) { ezUInt32 error = GetLastError(); if (error == ERROR_IO_PENDING) { m_OutputState.IsPending = true; return true; } ezLog::Error("Write to pipe failed: {0}", ezArgErrorCode(error)); return false; } m_OutputState.IsPending = true; return true; }
VertexDataStream* Mesh::AddDataStream(ezGALVertexAttributeSemantic::Enum semantic, ezUInt32 uiNumElementsPerVertex, VertexElementType elementType) { // A few checks for meaningful element count. // These are necessary to keep the implementation of preprocessing functions like // MergeSubMeshesWithSameMaterials/ComputeNormals/ComputeTangents sane. switch (semantic) { case ezGALVertexAttributeSemantic::Position: EZ_ASSERT_DEBUG(uiNumElementsPerVertex == 3 && elementType == VertexElementType::FLOAT, "Position vertex streams should always have exactly 3 float elements."); break; case ezGALVertexAttributeSemantic::Normal: EZ_ASSERT_DEBUG(uiNumElementsPerVertex == 3 && elementType == VertexElementType::FLOAT, "Normal vertex streams should always have exactly 3 float elements."); break; case ezGALVertexAttributeSemantic::Tangent: EZ_ASSERT_DEBUG(uiNumElementsPerVertex == 3 && elementType == VertexElementType::FLOAT, "Tangent vertex streams should always have exactly 3 float elements."); break; case ezGALVertexAttributeSemantic::BiTangent: EZ_ASSERT_DEBUG((uiNumElementsPerVertex == 3 || uiNumElementsPerVertex == 1) && elementType == VertexElementType::FLOAT, "BiTangent vertex streams should have either 3 float elements (vector) or 1 float element (sign)."); break; case ezGALVertexAttributeSemantic::BoneIndices0: case ezGALVertexAttributeSemantic::BoneIndices1: case ezGALVertexAttributeSemantic::BoneWeights0: case ezGALVertexAttributeSemantic::BoneWeights1: EZ_ASSERT_DEBUG(uiNumElementsPerVertex == 4 || uiNumElementsPerVertex == 1, "Bone weights and index streams should have 1 or 4 elements (single bone / standard skinning)."); break; } VertexDataStream* existingStream = nullptr; if (!m_VertexDataStreams.TryGetValue(static_cast<ezUInt32>(semantic), existingStream)) { m_VertexDataStreams.Insert(semantic, EZ_DEFAULT_NEW(VertexDataStream, uiNumElementsPerVertex, m_Triangles.GetCount(), elementType)); return m_VertexDataStreams[semantic]; } else { if (uiNumElementsPerVertex != existingStream->GetNumElementsPerVertex() || elementType != existingStream->GetElementType()) { return nullptr; } return existingStream; } }
bool ezPipeChannel_win::ProcessConnection() { EZ_ASSERT_DEBUG(m_ThreadId == ezThreadUtils::GetCurrentThreadID(), "Function must be called from worker thread!"); if (m_InputState.IsPending) m_InputState.IsPending = false; BOOL res = ConnectNamedPipe(m_PipeHandle, &m_InputState.Context.Overlapped); if (res) { //EZ_REPORT_FAILURE return false; } ezUInt32 error = GetLastError(); switch (error) { case ERROR_IO_PENDING: m_InputState.IsPending = true; break; case ERROR_PIPE_CONNECTED: m_Connected = true; break; case ERROR_NO_DATA: return false; default: ezLog::Error("Could not connect to pipe (Error code: {0})", ezArgErrorCode(error)); return false; } return true; }
void ezPipeChannel_win::InternalDisconnect() { #if EZ_ENABLED(EZ_COMPILE_FOR_DEBUG) if (m_ThreadId != 0) EZ_ASSERT_DEBUG(m_ThreadId == ezThreadUtils::GetCurrentThreadID(), "Function must be called from worker thread!"); #endif if (m_InputState.IsPending || m_OutputState.IsPending) { CancelIo(m_PipeHandle); } if (m_PipeHandle != INVALID_HANDLE_VALUE) { CloseHandle(m_PipeHandle); m_PipeHandle = INVALID_HANDLE_VALUE; } while (m_InputState.IsPending || m_OutputState.IsPending) { FlushPendingOperations(); } { EZ_LOCK(m_OutputQueueMutex); m_OutputQueue.Clear(); m_Connected = false; } m_Events.Broadcast(ezIpcChannelEvent(m_Mode == Mode::Client ? ezIpcChannelEvent::DisconnectedFromServer : ezIpcChannelEvent::DisconnectedFromClient, this)); // Raise in case another thread is waiting for new messages (as we would sleep forever otherwise). m_IncomingMessages.RaiseSignal(); }
void ezQtPin::AddConnection(ezQtConnection* pConnection) { EZ_ASSERT_DEBUG(!m_Connections.Contains(pConnection), "Connection already present!"); m_Connections.PushBack(pConnection); ConnectedStateChanged(true); UpdateConnections(); }
void ezQtPropertyWidget::PrepareToDie() { EZ_ASSERT_DEBUG(!m_bUndead, "Object has already been marked for cleanup"); m_bUndead = true; DoPrepareToDie(); }
bool ezPipeChannel_win::ProcessIncomingMessages(DWORD uiBytesRead) { EZ_ASSERT_DEBUG(m_ThreadId == ezThreadUtils::GetCurrentThreadID(), "Function must be called from worker thread!"); if (m_InputState.IsPending) { m_InputState.IsPending = false; if (uiBytesRead == 0) return false; } while (true) { if (uiBytesRead == 0) { if (m_PipeHandle == INVALID_HANDLE_VALUE) return false; BOOL res = ReadFile(m_PipeHandle, m_InputBuffer, BUFFER_SIZE, &uiBytesRead, &m_InputState.Context.Overlapped); if (!res) { ezUInt32 error = GetLastError(); if (error == ERROR_IO_PENDING) { m_InputState.IsPending = true; return true; } if (m_Mode == Mode::Server) { // only log when in server mode, otherwise this can result in an endless recursion ezLog::Error("Read from pipe failed: {0}", ezArgErrorCode(error)); } return false; } m_InputState.IsPending = true; return true; } EZ_ASSERT_DEBUG(uiBytesRead != 0, "We really should have data at this point."); ReceiveMessageData(ezArrayPtr<ezUInt8>(m_InputBuffer, uiBytesRead)); uiBytesRead = 0; } return true; }
ezStatus Importer::ImportSkeleton(ezEditableSkeleton& out_Skeleton, const ezSharedPtr<Scene>& scene) { const float fScale = 1.0f; const ezMat3 mTransformation = ezMat3::IdentityMatrix(); const ezMat3 mTransformRotations = ezMat3::IdentityMatrix(); const ezUInt32 numJoints = scene->m_Skeleton.GetJointCount(); ezDynamicArray<ezEditableSkeletonJoint*> allJoints; allJoints.SetCountUninitialized(numJoints); ezSet<ezString> jointNames; ezStringBuilder tmp; for (ezUInt32 b = 0; b < numJoints; ++b) { const ezTransform mJointTransform = scene->m_Skeleton.GetJointByIndex(b).GetBindPoseLocalTransform(); allJoints[b] = EZ_DEFAULT_NEW(ezEditableSkeletonJoint); allJoints[b]->m_sName = scene->m_Skeleton.GetJointByIndex(b).GetName(); allJoints[b]->m_Transform = mJointTransform; allJoints[b]->m_Transform.m_vScale.Set(1.0f); allJoints[b]->m_fLength = 0.1f; allJoints[b]->m_fThickness = 0.01f; allJoints[b]->m_fWidth = 0.01f; allJoints[b]->m_Geometry = ezSkeletonJointGeometryType::None; if (jointNames.Contains(allJoints[b]->m_sName)) { tmp = allJoints[b]->m_sName.GetData(); tmp.AppendFormat("_joint{0}", b); allJoints[b]->m_sName.Assign(tmp.GetData()); } jointNames.Insert(allJoints[b]->m_sName.GetString()); if (scene->m_Skeleton.GetJointByIndex(b).IsRootJoint()) { allJoints[b]->m_Transform.m_vPosition = mTransformation * allJoints[b]->m_Transform.m_vPosition; allJoints[b]->m_Transform.m_qRotation.SetFromMat3(mTransformRotations * allJoints[b]->m_Transform.m_qRotation.GetAsMat3()); out_Skeleton.m_Children.PushBack(allJoints[b]); } else { allJoints[b]->m_Transform.m_vPosition = fScale * allJoints[b]->m_Transform.m_vPosition; ezUInt32 parentIdx = scene->m_Skeleton.GetJointByIndex(b).GetParentIndex(); EZ_ASSERT_DEBUG(parentIdx < b, "Invalid parent joint index"); allJoints[parentIdx]->m_Children.PushBack(allJoints[b]); } } return ezStatus(EZ_SUCCESS); }
void ezQtPin::RemoveConnection(ezQtConnection* pConnection) { EZ_ASSERT_DEBUG(m_Connections.Contains(pConnection), "Connection not present!"); m_Connections.RemoveAndSwap(pConnection); if (m_Connections.IsEmpty()) ConnectedStateChanged(false); UpdateConnections(); }
void ezTypelessResourceHandle::operator=(const ezTypelessResourceHandle& rhs) { EZ_ASSERT_DEBUG(this != &rhs, "Cannot assign a resource handle to itself! This would invalidate the handle."); Invalidate(); m_pResource = rhs.m_pResource; if (m_pResource) IncreaseResourceRefCount(reinterpret_cast<ezResource*>(m_pResource)); }
void ezPipeChannel_win::AddToMessageLoop(ezMessageLoop* pMsgLoop) { if (m_PipeHandle != INVALID_HANDLE_VALUE) { ezMessageLoop_win* pMsgLoopWin = static_cast<ezMessageLoop_win*>(pMsgLoop); ULONG_PTR key = reinterpret_cast<ULONG_PTR>(this); HANDLE port = CreateIoCompletionPort(m_PipeHandle, pMsgLoopWin->GetPort(), key, 1); EZ_ASSERT_DEBUG(pMsgLoopWin->GetPort() == port, "Failed to CreateIoCompletionPort: {0}", ezArgErrorCode(GetLastError())); } }
void ezSceneViewContext::PickObjectAt(ezUInt16 x, ezUInt16 y) { // remote processes do not support picking, just ignore this if (ezEditorEngineProcessApp::GetSingleton()->IsRemoteMode()) return; ezViewPickingResultMsgToEditor res; ezView* pView = nullptr; if (ezRenderWorld::TryGetView(m_hView, pView) && pView->IsRenderPassReadBackPropertyExisting("EditorPickingPass", "PickingMatrix")) { pView->SetRenderPassProperty("EditorPickingPass", "PickingPosition", ezVec2(x, y)); ezVariant varMat = pView->GetRenderPassReadBackProperty("EditorPickingPass", "PickingMatrix"); if (varMat.IsA<ezMat4>()) { const ezUInt32 uiPickingID = pView->GetRenderPassReadBackProperty("EditorPickingPass", "PickingID").ConvertTo<ezUInt32>(); // const float fPickingDepth = pView->GetRenderPassReadBackProperty("EditorPickingPass", "PickingDepth").ConvertTo<float>(); res.m_vPickedNormal = pView->GetRenderPassReadBackProperty("EditorPickingPass", "PickingNormal").ConvertTo<ezVec3>(); res.m_vPickingRayStartPosition = pView->GetRenderPassReadBackProperty("EditorPickingPass", "PickingRayStartPosition").ConvertTo<ezVec3>(); res.m_vPickedPosition = pView->GetRenderPassReadBackProperty("EditorPickingPass", "PickingPosition").ConvertTo<ezVec3>(); EZ_ASSERT_DEBUG(!res.m_vPickedPosition.IsNaN(), ""); const ezUInt32 uiComponentID = (uiPickingID & 0x00FFFFFF); const ezUInt32 uiPartIndex = (uiPickingID >> 24) & 0x7F; // highest bit indicates whether the object is dynamic, ignore this res.m_ComponentGuid = GetDocumentContext()->m_Context.m_ComponentPickingMap.GetGuid(uiComponentID); res.m_OtherGuid = GetDocumentContext()->m_Context.m_OtherPickingMap.GetGuid(uiComponentID); if (res.m_ComponentGuid.IsValid()) { ezComponentHandle hComponent = GetDocumentContext()->m_Context.m_ComponentMap.GetHandle(res.m_ComponentGuid); ezEngineProcessDocumentContext* pDocumentContext = GetDocumentContext(); // check whether the component is still valid ezComponent* pComponent = nullptr; if (pDocumentContext->GetWorld()->TryGetComponent<ezComponent>(hComponent, pComponent)) { // if yes, fill out the parent game object guid res.m_ObjectGuid = GetDocumentContext()->m_Context.m_GameObjectMap.GetGuid(pComponent->GetOwner()->GetHandle()); res.m_uiPartIndex = uiPartIndex; } else { res.m_ComponentGuid = ezUuid(); } } } }
void ezQtPropertyWidget::Init(ezQtPropertyGridWidget* pGrid, ezObjectAccessorBase* pObjectAccessor, const ezRTTI* pType, const ezAbstractProperty* pProp) { m_pGrid = pGrid; m_pObjectAccessor = pObjectAccessor; m_pType = pType; m_pProp = pProp; EZ_ASSERT_DEBUG(m_pGrid && m_pObjectAccessor && m_pType && m_pProp, ""); if (pProp->GetAttributeByType<ezReadOnlyAttribute>() != nullptr || pProp->GetFlags().IsSet(ezPropertyFlags::ReadOnly)) setEnabled(false); OnInit(); }
void ezSphereVisualizerAdapter::Update() { m_Gizmo.SetVisible(m_bVisualizerIsVisible); ezObjectAccessorBase* pObjectAccessor = GetObjectAccessor(); const ezSphereVisualizerAttribute* pAttr = static_cast<const ezSphereVisualizerAttribute*>(m_pVisualizerAttr); m_Scale = 1.0f; if (!pAttr->GetRadiusProperty().IsEmpty()) { ezVariant value; pObjectAccessor->GetValue(m_pObject, GetProperty(pAttr->GetRadiusProperty()), value); EZ_ASSERT_DEBUG(value.IsValid() && value.CanConvertTo<float>(), "Invalid property bound to ezSphereVisualizerAttribute 'radius'"); m_Scale = value.ConvertTo<float>(); } if (!pAttr->GetColorProperty().IsEmpty()) { ezVariant value; pObjectAccessor->GetValue(m_pObject, GetProperty(pAttr->GetColorProperty()), value); EZ_ASSERT_DEBUG(value.IsValid() && value.CanConvertTo<ezColor>(), "Invalid property bound to ezSphereVisualizerAttribute 'color'"); m_Gizmo.SetColor(value.ConvertTo<ezColor>()); } m_vPositionOffset = pAttr->m_vOffset; if (!pAttr->GetOffsetProperty().IsEmpty()) { ezVariant value; pObjectAccessor->GetValue(m_pObject, GetProperty(pAttr->GetOffsetProperty()), value); EZ_ASSERT_DEBUG(value.IsValid() && value.CanConvertTo<ezVec3>(), "Invalid property bound to ezSphereVisualizerAttribute 'offset'"); m_vPositionOffset += value.ConvertTo<ezVec3>(); } }
void ezSimdQuat::SetSlerp(const ezSimdQuat& qFrom, const ezSimdQuat& qTo, const ezSimdFloat& t) { EZ_ASSERT_DEBUG((t >= 0.0f) && (t <= 1.0f), "Invalid lerp factor."); const ezSimdFloat one = 1.0f; const ezSimdFloat qdelta = 1.0f - 0.001f; const ezSimdFloat fDot = qFrom.m_v.Dot<4>(qTo.m_v); ezSimdFloat cosTheta = fDot; bool bFlipSign = false; if (cosTheta < 0.0f) { bFlipSign = true; cosTheta = -cosTheta; } ezSimdFloat t0, t1; if (cosTheta < qdelta) { ezAngle theta = ezMath::ACos(cosTheta); // use sqrtInv(1+c^2) instead of 1.0/sin(theta) const ezSimdFloat iSinTheta = (one - (cosTheta * cosTheta)).GetInvSqrt(); const ezAngle tTheta = (float)t * theta; ezSimdFloat s0 = ezMath::Sin(theta - tTheta); ezSimdFloat s1 = ezMath::Sin(tTheta); t0 = s0 * iSinTheta; t1 = s1 * iSinTheta; } else { // If q0 is nearly the same as q1 we just linearly interpolate t0 = one - t; t1 = t; } if (bFlipSign) t1 = -t1; m_v = qFrom.m_v * t0 + qTo.m_v * t1; Normalize(); }
void ezGameObjectGizmoEditTool::SelectionManagerEventHandler(const ezSelectionManagerEvent& e) { switch (e.m_Type) { case ezSelectionManagerEvent::Type::SelectionCleared: m_GizmoSelection.Clear(); UpdateGizmoVisibleState(); break; case ezSelectionManagerEvent::Type::SelectionSet: case ezSelectionManagerEvent::Type::ObjectAdded: EZ_ASSERT_DEBUG(m_GizmoSelection.IsEmpty(), "This array should have been cleared when the gizmo lost focus"); UpdateGizmoVisibleState(); break; } }
void ezDirectionVisualizerAdapter::Update() { m_Gizmo.SetVisible(m_bVisualizerIsVisible); const ezDirectionVisualizerAttribute* pAttr = static_cast<const ezDirectionVisualizerAttribute*>(m_pVisualizerAttr); if (!pAttr->GetColorProperty().IsEmpty()) { ezObjectAccessorBase* pObjectAccessor = GetObjectAccessor(); ezVariant value; pObjectAccessor->GetValue(m_pObject, GetProperty(pAttr->GetColorProperty()), value); EZ_ASSERT_DEBUG(value.IsValid() && value.CanConvertTo<ezColor>(), "Invalid property bound to ezDirectionVisualizerAttribute 'color'"); m_Gizmo.SetColor(value.ConvertTo<ezColor>()); } }
bool ezRTTI::DispatchMessage(const void* pInstance, ezMessage& msg) const { EZ_ASSERT_DEBUG(m_bGatheredDynamicMessageHandlers, "Message handler table should have been gathered at this point"); const ezUInt32 uiIndex = msg.GetId() - m_uiMsgIdOffset; // m_DynamicMessageHandlers contains all message handlers of this type and all base types if (uiIndex < m_DynamicMessageHandlers.GetCount()) { ezAbstractMessageHandler* pHandler = m_DynamicMessageHandlers[uiIndex]; if (pHandler != nullptr && pHandler->IsConst()) { (*pHandler)(pInstance, msg); return true; } } return false; }
ezQtTypeWidget::ezQtTypeWidget(QWidget* pParent, ezQtPropertyGridWidget* pGrid, ezObjectAccessorBase* pObjectAccessor, const ezRTTI* pType, const char* szIncludeProperties, const char* szExcludeProperties) : QWidget(pParent) , m_pGrid(pGrid) , m_pObjectAccessor(pObjectAccessor) , m_pType(pType) { EZ_ASSERT_DEBUG(m_pGrid && m_pObjectAccessor && m_pType, ""); m_pLayout = new QGridLayout(this); m_pLayout->setColumnStretch(0, 1); m_pLayout->setColumnStretch(1, 0); m_pLayout->setColumnMinimumWidth(1, 5); m_pLayout->setColumnStretch(2, 2); m_pLayout->setMargin(0); m_pLayout->setSpacing(0); setLayout(m_pLayout); m_pGrid->GetObjectManager()->m_PropertyEvents.AddEventHandler(ezMakeDelegate(&ezQtTypeWidget::PropertyEventHandler, this)); m_pGrid->GetCommandHistory()->m_Events.AddEventHandler(ezMakeDelegate(&ezQtTypeWidget::CommandHistoryEventHandler, this)); ezManipulatorManager::GetSingleton()->m_Events.AddEventHandler(ezMakeDelegate(&ezQtTypeWidget::ManipulatorManagerEventHandler, this)); BuildUI(pType, szIncludeProperties, szExcludeProperties); }
void ezWorld::PatchHierarchyData(ezGameObject* pObject, ezGameObject::TransformPreservation preserve) { ezGameObject* pParent = pObject->GetParent(); RecreateHierarchyData(pObject, pObject->IsDynamic()); pObject->m_pTransformationData->m_pParentData = pParent != nullptr ? pParent->m_pTransformationData : nullptr; if (preserve == ezGameObject::TransformPreservation::PreserveGlobal) { pObject->SetGlobalTransform(pObject->m_pTransformationData->m_globalTransform); } else { pObject->UpdateGlobalTransform(); } for (auto it = pObject->GetChildren(); it.IsValid(); ++it) { PatchHierarchyData(it, preserve); } EZ_ASSERT_DEBUG(pObject->m_pTransformationData != pObject->m_pTransformationData->m_pParentData, "Hierarchy corrupted!"); }
void ValidateSceneGraph(Scene* scene) { if (!scene) return; ezHashSet<const Node*> visitedNodes; ezDynamicArray<const Node*> queue; for (const HierarchyObject* object : scene->GetRootObjects()) { // EZ_ASSERT_DEBUG(!object->GetParent().IsValid(), "Root object has a parent!"); const Node* currentNode = object->Cast<Node>(); if (currentNode) { visitedNodes.Clear(); queue.Clear(); queue.PushBack(currentNode); while (!queue.IsEmpty()) { currentNode = queue.PeekBack(); queue.PopBack(); EZ_ASSERT_DEBUG(visitedNodes.Insert(currentNode) == false, "Imported scene contains cycles in its graph."); for (ObjectHandle child : currentNode->m_Children) { // EZ_ASSERT_DEBUG(scene->GetObject(object->GetParent()) == currentNode, "Child's parent pointer is incorrect!"); const Node* childNode = object->Cast<Node>(); if (childNode) queue.PushBack(childNode); } } } } }
void ezWorld::LinkToParent(ezGameObject* pObject) { EZ_ASSERT_DEBUG(pObject->m_NextSiblingIndex == 0 && pObject->m_PrevSiblingIndex == 0, "Object is either still linked to another parent or data was not cleared."); if (ezGameObject* pParentObject = pObject->GetParent()) { const ezUInt32 uiIndex = pObject->m_InternalId.m_InstanceIndex; if (pParentObject->m_FirstChildIndex != 0) { pObject->m_PrevSiblingIndex = pParentObject->m_LastChildIndex; GetObjectUnchecked(pParentObject->m_LastChildIndex)->m_NextSiblingIndex = uiIndex; } else { pParentObject->m_FirstChildIndex = uiIndex; } pParentObject->m_LastChildIndex = uiIndex; pParentObject->m_ChildCount++; pObject->m_pTransformationData->m_pParentData = pParentObject->m_pTransformationData; } }
void ezDirectionVisualizerAdapter::UpdateGizmoTransform() { const ezDirectionVisualizerAttribute* pAttr = static_cast<const ezDirectionVisualizerAttribute*>(m_pVisualizerAttr); float fScale = pAttr->m_fScale; if (!pAttr->GetLengthProperty().IsEmpty()) { ezObjectAccessorBase* pObjectAccessor = GetObjectAccessor(); ezVariant value; pObjectAccessor->GetValue(m_pObject, GetProperty(pAttr->GetLengthProperty()), value); EZ_ASSERT_DEBUG(value.IsValid() && value.CanConvertTo<float>(), "Invalid property bound to ezDirectionVisualizerAttribute 'length'"); fScale *= value.ConvertTo<float>(); } const ezQuat axisRotation = GetBasisRotation(ezBasisAxis::PositiveX, pAttr->m_Axis); ezTransform t; t.m_qRotation = axisRotation; t.m_vScale = ezVec3(fScale); t.m_vPosition = axisRotation * ezVec3(fScale, 0, 0); m_Gizmo.SetTransformation(GetObjectTransform() * t); }
void Mesh::AddData(const Mesh& mesh, const ezTransform& transform) { ezMat4 transformMat = transform.GetAsMat4(); ezMat4 normalTransformMat = transformMat.GetInverse(0.0f).GetTranspose(); // Create new triangles. ezUInt32 oldTriangleCount = GetNumTriangles(); AddTriangles(mesh.GetNumTriangles()); ezArrayPtr<const Mesh::Triangle> sourceTriangles = mesh.GetTriangles(); ezArrayPtr<const Mesh::Triangle> targetTriangles = GetTriangles().GetSubArray(oldTriangleCount); EZ_ASSERT_DEBUG(sourceTriangles.GetCount() == targetTriangles.GetCount(), "Something is wrong with triangle allocation!"); for (auto it = mesh.m_VertexDataStreams.GetIterator(); it.IsValid(); ++it) { const VertexDataStream* sourceStream = it.Value(); VertexDataStream* targetStream = AddDataStream(static_cast<ezGALVertexAttributeSemantic::Enum>(it.Key()), sourceStream->GetNumElementsPerVertex(), sourceStream->GetElementType()); if (!targetStream) { ezLog::SeriousWarning("Cannot merge mesh {0} properly since it has a vertex data stream with semantic {1} that uses {2} elements " "instead of 'unkown' which is used by the merge target. Skipping this data stream.", mesh.m_Name, it.Key(), sourceStream->GetNumElementsPerVertex()); continue; } // Copy data. ezUInt32 targetBaseDataIndex = targetStream->m_Data.GetCount(); targetStream->m_Data.PushBackRange(sourceStream->m_Data); // Transform data. if (!transform.IsIdentical(ezTransform::IdentityTransform())) { const ezUInt32 attributeSize = targetStream->GetAttributeSize(); // Positions if (it.Key() == ezGALVertexAttributeSemantic::Position) { for (ezUInt32 i = targetBaseDataIndex; i < targetStream->m_Data.GetCount(); i += attributeSize) { ezVec3& pos = *reinterpret_cast<ezVec3*>(&targetStream->m_Data[i]); pos = transformMat.TransformPosition(pos); } } // Directions else if (it.Key() == ezGALVertexAttributeSemantic::Normal || it.Key() == ezGALVertexAttributeSemantic::Tangent || it.Key() == ezGALVertexAttributeSemantic::BiTangent) { for (ezUInt32 i = targetBaseDataIndex; i < targetStream->m_Data.GetCount(); i += attributeSize) { ezVec3& dir = *reinterpret_cast<ezVec3*>(&targetStream->m_Data[i]); dir = normalTransformMat.TransformDirection(dir); } } } // Set mapping for (ezUInt32 tri = 0; tri < sourceTriangles.GetCount(); ++tri) { for (int v = 0; v < 3; ++v) { VertexDataIndex sourceDataIndex = sourceStream->GetDataIndex(sourceTriangles[tri].m_Vertices[v]); if (sourceDataIndex.IsValid()) targetStream->SetDataIndex(targetTriangles[tri].m_Vertices[v], targetBaseDataIndex + sourceDataIndex.GetValue()); } } } // Add submeshes. ezUInt32 oldSubMeshCount = m_SubMeshes.GetCount(); m_SubMeshes.PushBackRange(mesh.m_SubMeshes); for (ezUInt32 i = oldSubMeshCount; i < m_SubMeshes.GetCount(); ++i) { m_SubMeshes[i].m_uiFirstTriangle += oldTriangleCount; } // Add skeleton if existent // TODO: What if multiple, incompatible skeletons are found(?) // For now: Remove skeleton and import unskinned // if (mesh.m_pSkeleton) //{ // if (m_pSkeleton) // { // if (!m_pSkeleton->IsCompatibleWith(mesh.m_pSkeleton.Borrow())) // { // ezLog::Warning("Found incompatible skeletons during mesh merging in mesh '{0}', import will be without skeletons!", // m_Name.GetData()); m_pSkeleton.Reset(); // } // } // else // { // m_pSkeleton = EZ_DEFAULT_NEW(ezSkeleton, *mesh.m_pSkeleton); // } //} }
void ezRTTI::SanityCheckType(ezRTTI* pType) { EZ_ASSERT_DEV(pType->GetTypeFlags().IsSet(ezTypeFlags::StandardType) + pType->GetTypeFlags().IsSet(ezTypeFlags::IsEnum) + pType->GetTypeFlags().IsSet(ezTypeFlags::Bitflags) + pType->GetTypeFlags().IsSet(ezTypeFlags::Class) == 1, "Types are mutually exclusive!"); for (auto pProp : pType->m_Properties) { const ezRTTI* pSpecificType = pProp->GetSpecificType(); EZ_ASSERT_DEBUG(IsValidIdentifierName(pProp->GetPropertyName()), "Property name is invalid: '{0}'", pProp->GetPropertyName()); // if (!IsValidIdentifierName(pProp->GetPropertyName())) //{ // ezStringBuilder s; // s.Format("RTTI: {0}\n", pProp->GetPropertyName()); // OutputDebugStringA(s.GetData()); //} if (pProp->GetCategory() != ezPropertyCategory::Function) { EZ_ASSERT_DEV(pProp->GetFlags().IsSet(ezPropertyFlags::StandardType) + pProp->GetFlags().IsSet(ezPropertyFlags::IsEnum) + pProp->GetFlags().IsSet(ezPropertyFlags::Bitflags) + pProp->GetFlags().IsSet(ezPropertyFlags::Class) <= 1, "Types are mutually exclusive!"); } switch (pProp->GetCategory()) { case ezPropertyCategory::Constant: { EZ_ASSERT_DEV(pSpecificType->GetTypeFlags().IsSet(ezTypeFlags::StandardType), "Only standard type constants are supported!"); } break; case ezPropertyCategory::Member: { EZ_ASSERT_DEV(pProp->GetFlags().IsSet(ezPropertyFlags::StandardType) == pSpecificType->GetTypeFlags().IsSet(ezTypeFlags::StandardType), "Property-Type missmatch!"); EZ_ASSERT_DEV(pProp->GetFlags().IsSet(ezPropertyFlags::IsEnum) == pSpecificType->GetTypeFlags().IsSet(ezTypeFlags::IsEnum), "Property-Type missmatch! Use EZ_BEGIN_STATIC_REFLECTED_ENUM for type and EZ_ENUM_MEMBER_PROPERTY / " "EZ_ENUM_ACCESSOR_PROPERTY for property."); EZ_ASSERT_DEV(pProp->GetFlags().IsSet(ezPropertyFlags::Bitflags) == pSpecificType->GetTypeFlags().IsSet(ezTypeFlags::Bitflags), "Property-Type missmatch! Use EZ_BEGIN_STATIC_REFLECTED_ENUM for type and EZ_BITFLAGS_MEMBER_PROPERTY / " "EZ_BITFLAGS_ACCESSOR_PROPERTY for property."); EZ_ASSERT_DEV(pProp->GetFlags().IsSet(ezPropertyFlags::Class) == pSpecificType->GetTypeFlags().IsSet(ezTypeFlags::Class), "If ezPropertyFlags::Class is set, the property type must be ezTypeFlags::Class and vise versa."); } break; case ezPropertyCategory::Array: case ezPropertyCategory::Set: case ezPropertyCategory::Map: { EZ_ASSERT_DEV(pProp->GetFlags().IsSet(ezPropertyFlags::StandardType) == pSpecificType->GetTypeFlags().IsSet(ezTypeFlags::StandardType), "Property-Type missmatch!"); EZ_ASSERT_DEV(pProp->GetFlags().IsSet(ezPropertyFlags::Class) == pSpecificType->GetTypeFlags().IsSet(ezTypeFlags::Class), "If ezPropertyFlags::Class is set, the property type must be ezTypeFlags::Class and vise versa."); } break; case ezPropertyCategory::Function: EZ_REPORT_FAILURE("Functions need to be put into the EZ_BEGIN_FUNCTIONS / EZ_END_FUNCTIONS; block."); break; } } }
void Object::AddMesh(ezUniquePtr<Mesh> mesh) { EZ_ASSERT_DEBUG(m_MeshesHandles.IsEmpty(), "Can't add meshes to Pbrt::Object after it was initialized once."); m_MeshesData.PushBack(std::move(mesh)); }
void ezCameraVisualizerAdapter::Update() { const ezCameraVisualizerAttribute* pAttr = static_cast<const ezCameraVisualizerAttribute*>(m_pVisualizerAttr); ezObjectAccessorBase* pObjectAccessor = GetObjectAccessor(); float fNearPlane = 1.0f; float fFarPlane = 10.0f; ezInt32 iMode = 0; if (!pAttr->GetModeProperty().IsEmpty()) { ezVariant value; pObjectAccessor->GetValue(m_pObject, GetProperty(pAttr->GetModeProperty()), value); EZ_ASSERT_DEBUG(value.IsValid() && value.CanConvertTo<ezInt32>(), "Invalid property bound to ezCameraVisualizerAttribute 'mode'"); iMode = value.ConvertTo<ezInt32>(); } if (!pAttr->GetNearPlaneProperty().IsEmpty()) { ezVariant value; pObjectAccessor->GetValue(m_pObject, GetProperty(pAttr->GetNearPlaneProperty()), value); EZ_ASSERT_DEBUG(value.IsValid() && value.CanConvertTo<float>(), "Invalid property bound to ezCameraVisualizerAttribute 'near plane'"); fNearPlane = value.ConvertTo<float>(); } if (!pAttr->GetFarPlaneProperty().IsEmpty()) { ezVariant value; pObjectAccessor->GetValue(m_pObject, GetProperty(pAttr->GetFarPlaneProperty()), value); EZ_ASSERT_DEBUG(value.IsValid() && value.CanConvertTo<float>(), "Invalid property bound to ezCameraVisualizerAttribute 'far plane'"); fFarPlane = value.ConvertTo<float>(); } if (iMode == ezCameraMode::OrthoFixedHeight || iMode == ezCameraMode::OrthoFixedWidth) { float fDimensions = 1.0f; if (!pAttr->GetOrthoDimProperty().IsEmpty()) { ezVariant value; pObjectAccessor->GetValue(m_pObject, GetProperty(pAttr->GetOrthoDimProperty()), value); EZ_ASSERT_DEBUG(value.IsValid() && value.CanConvertTo<float>(), "Invalid property bound to ezCameraVisualizerAttribute 'ortho dim'"); fDimensions = value.ConvertTo<float>(); } { const float fRange = fFarPlane - fNearPlane; m_LocalTransformFrustum.m_qRotation.SetIdentity(); m_LocalTransformFrustum.m_vScale.Set(fRange, fDimensions, fDimensions); m_LocalTransformFrustum.m_vPosition.Set(fNearPlane + fRange * 0.5f, 0, 0); } m_BoxGizmo.SetVisible(m_bVisualizerIsVisible); m_FrustumGizmo.SetVisible(false); m_NearPlaneGizmo.SetVisible(false); m_FarPlaneGizmo.SetVisible(false); m_LocalTransformNearPlane.SetIdentity(); m_LocalTransformFarPlane.SetIdentity(); } else { float fFOV = 45.0f; if (!pAttr->GetFovProperty().IsEmpty()) { ezVariant value; pObjectAccessor->GetValue(m_pObject, GetProperty(pAttr->GetFovProperty()), value); EZ_ASSERT_DEBUG(value.IsValid() && value.CanConvertTo<float>(), "Invalid property bound to ezCameraVisualizerAttribute 'fov'"); fFOV = value.ConvertTo<float>(); } { const float fAngleScale = ezMath::Tan(ezAngle::Degree(fFOV) * 0.5f); const float fFrustumScale = ezMath::Min(fFarPlane, 10.0f); const float fFarPlaneScale = ezMath::Min(fFarPlane, 9.0f); ; // indicate whether the shown far plane is the actual distance, or just the maximum visualization distance m_FarPlaneGizmo.SetColor(fFarPlane > 9.0f ? ezColor::DodgerBlue : ezColor::PaleVioletRed); m_LocalTransformFrustum.m_qRotation.SetIdentity(); m_LocalTransformFrustum.m_vScale.Set(fFrustumScale, fAngleScale * fFrustumScale, fAngleScale * fFrustumScale); m_LocalTransformFrustum.m_vPosition.Set(0, 0, 0); m_LocalTransformNearPlane.m_qRotation.SetFromAxisAndAngle(ezVec3(0, 1, 0), ezAngle::Degree(90)); m_LocalTransformNearPlane.m_vScale.Set(fAngleScale * fNearPlane, fAngleScale * fNearPlane, 1); m_LocalTransformNearPlane.m_vPosition.Set(fNearPlane, 0, 0); m_LocalTransformFarPlane.m_qRotation.SetFromAxisAndAngle(ezVec3(0, 1, 0), ezAngle::Degree(90)); m_LocalTransformFarPlane.m_vScale.Set(fAngleScale * fFarPlaneScale, fAngleScale * fFarPlaneScale, 1); m_LocalTransformFarPlane.m_vPosition.Set(fFarPlaneScale, 0, 0); } m_BoxGizmo.SetVisible(false); m_FrustumGizmo.SetVisible(m_bVisualizerIsVisible); m_NearPlaneGizmo.SetVisible(m_bVisualizerIsVisible); m_FarPlaneGizmo.SetVisible(m_bVisualizerIsVisible); } }
ezBitflags<ezAssetDocumentFlags> ezPropertyAnimAssetDocumentManager::GetAssetDocumentTypeFlags(const ezDocumentTypeDescriptor* pDescriptor) const { EZ_ASSERT_DEBUG(pDescriptor->m_pManager == this, "Given type descriptor is not part of this document manager!"); return ezAssetDocumentFlags::AutoTransformOnSave; }
void ezImageConversionBase::RebuildConversionTable() { s_conversionTable.SetCount(ezImageFormat::NUM_FORMATS * ezImageFormat::NUM_FORMATS); s_subConversionTable.SetCount(ezImageFormat::NUM_FORMATS * ezImageFormat::NUM_FORMATS); s_costTable.SetCount(ezImageFormat::NUM_FORMATS * ezImageFormat::NUM_FORMATS); for (ezUInt32 tableIdx = 0; tableIdx < s_conversionTable.GetCount(); tableIdx++) { s_conversionTable[tableIdx] = nullptr; s_costTable[tableIdx] = ezMath::BasicType<float>::GetInfinity(); } // Prime conversion table with known conversions for (ezImageConversionBase* pConversion = ezImageConversionBase::GetFirstInstance(); pConversion; pConversion = pConversion->GetNextInstance()) { for (ezUInt32 uiSubConversion = 0; uiSubConversion < pConversion->m_subConversions.GetCount(); uiSubConversion++) { const SubConversion& subConversion = pConversion->m_subConversions[uiSubConversion]; if (subConversion.m_flags.IsSet(ezImageConversionFlags::InPlace)) { EZ_ASSERT_DEBUG(ezImageFormat::GetBitsPerPixel(subConversion.m_sourceFormat) == ezImageFormat::GetBitsPerPixel(subConversion.m_targetFormat), "In-place conversions are only allowed between formats of the same number of bits per pixel"); EZ_ASSERT_DEBUG(ezImageFormat::GetType(subConversion.m_sourceFormat) == ezImageFormat::GetType(subConversion.m_targetFormat), "In-place conversions are only allowed between formats of the same type"); } ezUInt32 uiTableIndex = GetTableIndex(subConversion.m_sourceFormat, subConversion.m_targetFormat); // Use the cheapest known conversion for each combination in case there are multiple ones if (s_costTable[uiTableIndex] > GetConversionCost(subConversion.m_flags)) { s_conversionTable[uiTableIndex] = pConversion; s_subConversionTable[uiTableIndex] = uiSubConversion; s_costTable[uiTableIndex] = GetConversionCost(subConversion.m_flags); } } } for (ezUInt32 i = 0; i < ezImageFormat::NUM_FORMATS; i++) { // Add copy-conversion (from and to same format) s_costTable[GetTableIndex(i, i)] = GetConversionCost(ezImageConversionFlags::InPlace); } // Straight from http://en.wikipedia.org/wiki/Floyd-Warshall_algorithm for (ezUInt32 k = 0; k < ezImageFormat::NUM_FORMATS; k++) { for (ezUInt32 i = 0; i < ezImageFormat::NUM_FORMATS; i++) { ezUInt32 uiTableIndexIK = GetTableIndex(i, k); for (ezUInt32 j = 0; j < ezImageFormat::NUM_FORMATS; j++) { ezUInt32 uiTableIndexIJ = GetTableIndex(i, j); ezUInt32 uiTableIndexKJ = GetTableIndex(k, j); if (s_costTable[uiTableIndexIK] + s_costTable[uiTableIndexKJ] < s_costTable[uiTableIndexIJ]) { s_costTable[uiTableIndexIJ] = s_costTable[uiTableIndexIK] + s_costTable[uiTableIndexKJ]; const ezImageConversionBase* pConversion = s_conversionTable[uiTableIndexIK]; // To convert from format I to format J, first convert from I to K s_conversionTable[uiTableIndexIJ] = pConversion; s_subConversionTable[uiTableIndexIJ] = s_subConversionTable[uiTableIndexIK]; } } } } s_bConversionTableValid = true; }