void DynamicNavigationMesh::SetNavigationDataAttr(const ea::vector<unsigned char>& value) { ReleaseNavigationMesh(); if (value.empty()) return; MemoryBuffer buffer(value); boundingBox_ = buffer.ReadBoundingBox(); numTilesX_ = buffer.ReadInt(); numTilesZ_ = buffer.ReadInt(); dtNavMeshParams params; // NOLINT(hicpp-member-init) buffer.Read(¶ms, sizeof(dtNavMeshParams)); navMesh_ = dtAllocNavMesh(); if (!navMesh_) { URHO3D_LOGERROR("Could not allocate navigation mesh"); return; } if (dtStatusFailed(navMesh_->init(¶ms))) { URHO3D_LOGERROR("Could not initialize navigation mesh"); ReleaseNavigationMesh(); return; } dtTileCacheParams tcParams; // NOLINT(hicpp-member-init) buffer.Read(&tcParams, sizeof(tcParams)); tileCache_ = dtAllocTileCache(); if (!tileCache_) { URHO3D_LOGERROR("Could not allocate tile cache"); ReleaseNavigationMesh(); return; } if (dtStatusFailed(tileCache_->init(&tcParams, allocator_.get(), compressor_.get(), meshProcessor_.get()))) { URHO3D_LOGERROR("Could not initialize tile cache"); ReleaseNavigationMesh(); return; } ReadTiles(buffer, true); // \todo Shall we send E_NAVIGATION_MESH_REBUILT here? }
bool Gizmo::Manipulate(const Camera* camera, const ea::vector<WeakPtr<Node>>& nodes) { if (nodes.empty()) return false; ImGuizmo::SetOrthographic(camera->IsOrthographic()); if (!IsActive()) { if (nodes.size() > 1) { // Find center point of all nodes // It is not clear what should be rotation and scale of center point for multiselection, therefore we limit // multiselection operations to world space (see above). Vector3 center = Vector3::ZERO; auto count = 0; for (const auto& node: nodes) { if (node.Expired() || node->GetType() == Scene::GetTypeStatic()) continue; center += node->GetWorldPosition(); count++; } if (count == 0) return false; center /= count; currentOrigin_.SetTranslation(center); } else if (!nodes.front().Expired()) currentOrigin_ = nodes.front()->GetTransform().ToMatrix4(); } // Enums are compatible. auto operation = static_cast<ImGuizmo::OPERATION>(operation_); ImGuizmo::MODE mode = ImGuizmo::WORLD; // Scaling only works in local space. Multiselections only work in world space. if (transformSpace_ == TS_LOCAL) mode = ImGuizmo::LOCAL; else if (transformSpace_ == TS_WORLD) mode = ImGuizmo::WORLD; // Scaling is always done in local space even for multiselections. if (operation_ == GIZMOOP_SCALE) mode = ImGuizmo::LOCAL; // Any other operations on multiselections are done in world space. else if (nodes.size() > 1) mode = ImGuizmo::WORLD; Matrix4 view = camera->GetView().ToMatrix4().Transpose(); Matrix4 proj = camera->GetProjection().Transpose(); Matrix4 tran = currentOrigin_.Transpose(); Matrix4 delta; ImGuiIO& io = ImGui::GetIO(); auto pos = displayPos_; auto size = displaySize_; if (size.x == 0 && size.y == 0) size = io.DisplaySize; ImGuizmo::SetRect(pos.x, pos.y, size.x, size.y); ImGuizmo::Manipulate(&view.m00_, &proj.m00_, operation, mode, &tran.m00_, &delta.m00_, nullptr); if (IsActive()) { if (!wasActive_) { // Just started modifying nodes. for (const auto& node: nodes) initialTransforms_[node] = node->GetTransform(); } wasActive_ = true; tran = tran.Transpose(); delta = delta.Transpose(); currentOrigin_ = Matrix4(tran); for (const auto& node: nodes) { if (node == nullptr) { URHO3D_LOGERROR("Gizmo received null pointer of node."); continue; } if (operation_ == GIZMOOP_SCALE) { // A workaround for ImGuizmo bug where delta matrix returns absolute scale value. if (!nodeScaleStart_.contains(node)) nodeScaleStart_[node] = node->GetScale(); node->SetScale(nodeScaleStart_[node] * delta.Scale()); } else { // Delta matrix is always in world-space. if (operation_ == GIZMOOP_ROTATE) node->RotateAround(currentOrigin_.Translation(), -delta.Rotation(), TS_WORLD); else node->Translate(delta.Translation(), TS_WORLD); } } return true; } else { if (wasActive_) { // Just finished modifying nodes. using namespace GizmoNodeModified; for (const auto& node: nodes) { if (node.Expired()) { URHO3D_LOGWARNINGF("Node expired while manipulating it with gizmo."); continue; } auto it = initialTransforms_.find(node.Get()); if (it == initialTransforms_.end()) { URHO3D_LOGWARNINGF("Gizmo has no record of initial node transform. List of transformed nodes " "changed mid-manipulation?"); continue; } SendEvent(E_GIZMONODEMODIFIED, P_NODE, node.Get(), P_OLDTRANSFORM, it->second, P_NEWTRANSFORM, node->GetTransform()); } } wasActive_ = false; initialTransforms_.clear(); if (operation_ == GIZMOOP_SCALE && !nodeScaleStart_.empty()) nodeScaleStart_.clear(); } return false; }