// ---------------------------------------------------------------------------- void IKSolver::HandleComponentRemoved(StringHash eventType, VariantMap& eventData) { using namespace ComponentRemoved; if (solver_->tree == NULL) return; // If an effector was removed, the tree will have to be rebuilt. Component* component = static_cast<Component*>(eventData[P_COMPONENT].GetPtr()); if (component->GetType() == IKEffector::GetTypeStatic()) { IKEffector* effector = static_cast<IKEffector*>(component); Node* node = static_cast<Node*>(eventData[P_NODE].GetPtr()); ik_node_t* ikNode = ik_node_find_child(solver_->tree, node->GetID()); assert(ikNode != NULL); ik_node_destroy_effector(ikNode); effector->SetIKEffector(NULL); effectorList_.RemoveSwap(effector); ResetToInitialPose(); MarkSolverTreeDirty(); } // Remove the ikNode* reference the IKConstraint was holding if (component->GetType() == IKConstraint::GetTypeStatic()) { IKConstraint* constraint = static_cast<IKConstraint*>(component); constraint->SetIKNode(NULL); // NOTE: Should restore default settings to the node } }
// ---------------------------------------------------------------------------- void IKSolver::HandleNodeRemoved(StringHash eventType, VariantMap& eventData) { using namespace NodeRemoved; if (solver_->tree == NULL) return; Node* node = static_cast<Node*>(eventData[P_NODE].GetPtr()); // Remove cached IKEffectors from our list PODVector<Node*> nodes; node->GetChildrenWithComponent<IKEffector>(nodes, true); for (PODVector<Node*>::ConstIterator it = nodes.Begin(); it != nodes.End(); ++it) { IKEffector* effector = (*it)->GetComponent<IKEffector>(); effector->SetIKEffector(NULL); effectorList_.RemoveSwap(effector); } // Special case, if the node being destroyed is the root node, destroy the // solver's tree instead of destroying the single node. Calling // ik_node_destroy() on the solver's root node will cause segfaults. ik_node_t* ikNode = ik_node_find_child(solver_->tree, node->GetID()); if (ikNode != NULL) { if (ikNode == solver_->tree) ik_solver_destroy_tree(solver_); else ik_node_destroy(ikNode); MarkSolverTreeDirty(); } }
// ---------------------------------------------------------------------------- void IKSolver::BuildTreeToEffector(const Node* node) { // Check if the component that was added is an IK effector. If not, then it // does not concern us. IKEffector* effector = static_cast<IKEffector*>(node->GetComponent<IKEffector>()); if (effector == NULL || effector->GetType() != IKEffector::GetTypeStatic()) return; // May need to build tree up to the node where this effector was added. Do // this by following the chain of parent nodes until we hit a node that // exists in the solver's tree. Then iterate backwards again and add each // missing node to the solver's tree. PODVector<const Node*> missingNodes; const Node* iterNode = node; ik_node_t* ikNode = ik_node_find_child(solver_->tree, node->GetID()); while (ikNode == NULL) { missingNodes.Push(iterNode); iterNode = iterNode->GetParent(); ikNode = ik_node_find_child(solver_->tree, iterNode->GetID()); } while (missingNodes.Size() > 0) { iterNode = missingNodes.Back(); missingNodes.Pop(); ik_node_t* ikChildNode = CreateIKNode(iterNode); ik_node_add_child(ikNode, ikChildNode); ikNode = ikChildNode; } // The tip of the tree is the effector. The solver library has ownership of // the effector object, but our IKEffector object also needs to know about // it. ik_effector_t* ikEffector = ik_effector_create(); ik_node_attach_effector(ikNode, ikEffector); // ownership of effector effector->SetIKEffector(ikEffector); // "weak" reference to effector effector->SetIKSolver(this); effectorList_.Push(effector); MarkSolverTreeDirty(); }