bool EC_Mesh::AttachMeshToBone(QObject* targetMesh, const QString& boneName) { if (!entity_) return false; // First make sure that the target mesh is valid, and the bone can be found EC_Mesh* targetMeshPtr = dynamic_cast<EC_Mesh*>(targetMesh); if (!targetMeshPtr) return false; Ogre::Entity* targetEntity = targetMeshPtr->GetEntity(); if (!targetEntity) return false; std::string boneNameStd = boneName.toStdString(); Ogre::SkeletonInstance* skeleton = targetEntity->getSkeleton(); if (!skeleton) return false; if (!skeleton->hasBone(boneNameStd)) return false; // We are ready to go. Detach the entity from its normal scene node first DetachMeshFromBone(); DetachEntity(); bone_tagpoint_ = targetEntity->attachObjectToBone(boneNameStd, entity_); bone_parent_mesh_ = targetMeshPtr; bone_parent_mesh_->bone_attached_mesh_ = this; attached_to_bone_ = true; // Force the adjustment for the tagpoint now OnAttributeUpdated(&nodeTransformation); return true; }
void EC_MediaPlayer::OnFrameUpdate(QImage frame) { // Don't do anything if rendering is not enabled if (!ViewEnabled() || GetFramework()->IsHeadless()) return; if (!componentPrepared_) return; if (!getenabled()) return; // Get needed components, something is fatally wrong if these are not present but componentPrepared_ is true. EC_Mesh *mesh = GetMeshComponent(); EC_WidgetCanvas *sceneCanvas = GetSceneCanvasComponent(); if (!mesh || !sceneCanvas) { // In the case someone destroyed EC_WidgetCanvas or EC_Mesh from our entity // lets stop our running timer (if its running), so we don't unnecessarily poll here. componentPrepared_ = false; return; } // Validate submesh index from EC_Mesh uint submeshIndex = (uint)getrenderSubmeshIndex(); if (submeshIndex >= mesh->GetNumSubMeshes()) { /// \note ResetSubmeshIndex() is called with a small delay here, or the ec editor UI wont react to it. Resetting the index back to 0 will call Render() again. LogWarning("Render submesh index " + QString::number(submeshIndex).toStdString() + " is illegal, restoring default value."); QTimer::singleShot(1, this, SLOT(ResetSubmeshIndex())); return; } // Set submesh to EC_WidgetCanvas if different from current if (!sceneCanvas->GetSubMeshes().contains(submeshIndex)) sceneCanvas->SetSubmesh(submeshIndex); sceneCanvas->Update(frame); }
void EC_Placeable::AttachNode() { if (world_.expired()) { LogError("EC_Placeable::AttachNode: No OgreWorld available to call this function!"); return; } OgreWorldPtr world = world_.lock(); try { // If already attached, detach first if (attached_) DetachNode(); Ogre::SceneManager* sceneMgr = world->GetSceneManager(); Ogre::SceneNode* root_node = sceneMgr->getRootSceneNode(); // Three possible cases // 1) attach to scene root node // 2) attach to another EC_Placeable's scene node // 3) attach to a bone on a skeletal mesh // Disconnect from the EntityCreated & ParentMeshChanged signals, as responding to them might not be needed anymore. // We will reconnect signals as necessary disconnect(this, SLOT(CheckParentEntityCreated(Entity*, AttributeChange::Type))); disconnect(this, SLOT(OnParentMeshChanged())); disconnect(this, SLOT(OnComponentAdded(IComponent*, AttributeChange::Type))); // Try to attach to another entity if the parent ref is non-empty // Make sure we're not trying to attach to ourselves as the parent const EntityReference& parent = parentRef.Get(); if (!parent.IsEmpty()) { Entity* ownEntity = ParentEntity(); if (!ownEntity) return; Scene* scene = ownEntity->ParentScene(); if (!scene) return; Entity* parentEntity = parent.Lookup(scene).get(); if (parentEntity == ownEntity) { // If we refer to self, attach to the root root_node->addChild(sceneNode_); attached_ = true; return; } if (parentEntity) { // Note: if we don't find the correct bone, we attach to the root QString boneName = parentBone.Get(); if (!boneName.isEmpty()) { EC_Mesh* parentMesh = parentEntity->GetComponent<EC_Mesh>().get(); if (parentMesh) { Ogre::Bone* bone = parentMesh->GetBone(boneName); if (bone) { // Create the node for bone attachment if it did not exist already if (!boneAttachmentNode_) { boneAttachmentNode_ = sceneMgr->createSceneNode(world->GetUniqueObjectName("EC_Placeable_BoneAttachmentNode")); root_node->addChild(boneAttachmentNode_); } // Setup manual bone tracking, as Ogre does not allow to attach scene nodes to bones attachmentListener.AddAttachment(parentMesh->GetEntity(), bone, this); boneAttachmentNode_->addChild(sceneNode_); parentBone_ = bone; parentMesh_ = parentMesh; connect(parentMesh, SIGNAL(MeshAboutToBeDestroyed()), this, SLOT(OnParentMeshDestroyed()), Qt::UniqueConnection); attached_ = true; return; } else { // Could not find the bone. Connect to the parent mesh MeshChanged signal to wait for the proper mesh to be assigned. connect(parentMesh, SIGNAL(MeshChanged()), this, SLOT(OnParentMeshChanged()), Qt::UniqueConnection); return; } } else { // If can't find the mesh component yet, wait for it to be created connect(parentEntity, SIGNAL(ComponentAdded(IComponent*, AttributeChange::Type)), this, SLOT(OnComponentAdded(IComponent*, AttributeChange::Type)), Qt::UniqueConnection); return; } } parentPlaceable_ = parentEntity->GetComponent<EC_Placeable>().get(); if (parentPlaceable_) { parentPlaceable_->GetSceneNode()->addChild(sceneNode_); // Connect to destruction of the placeable to be able to detach gracefully connect(parentPlaceable_, SIGNAL(AboutToBeDestroyed()), this, SLOT(OnParentPlaceableDestroyed()), Qt::UniqueConnection); attached_ = true; return; } else { // If can't find the placeable component yet, wait for it to be created connect(parentEntity, SIGNAL(ComponentAdded(IComponent*, AttributeChange::Type)), this, SLOT(OnComponentAdded(IComponent*, AttributeChange::Type)), Qt::UniqueConnection); return; } } else { // Could not find parent entity. Check for it later, when new entities are created into the scene connect(scene, SIGNAL(EntityCreated(Entity*, AttributeChange::Type)), this, SLOT(CheckParentEntityCreated(Entity*, AttributeChange::Type)), Qt::UniqueConnection); return; } }
void EC_MediaPlayer::PrepareComponent() { // Don't do anything if rendering is not enabled if (!ViewEnabled() || GetFramework()->IsHeadless()) return; // Some security checks if (componentPrepared_) { LogWarning("EC_MediaPlayer: Preparations seem to be done already, you might not want to do this multiple times."); } if (!mediaPlayer_) { LogError("EC_MediaPlayer: Cannot start preparing, webview object is null. This should never happen!"); return; } // Get parent and connect to the component removed signal. Entity *parent = ParentEntity(); if (parent) connect(parent, SIGNAL(ComponentRemoved(IComponent*, AttributeChange::Type)), SLOT(ComponentRemoved(IComponent*, AttributeChange::Type)), Qt::UniqueConnection); else { LogError("EC_MediaPlayer: Could not get parent entity pointer!"); return; } // Get EC_Mesh component EC_Mesh *mesh = GetMeshComponent(); if (!mesh) { // Wait for EC_Mesh to be added. connect(parent, SIGNAL(ComponentAdded(IComponent*, AttributeChange::Type)), SLOT(ComponentAdded(IComponent*, AttributeChange::Type)), Qt::UniqueConnection); return; } else { // Inspect if this mesh is ready for rendering. EC_Mesh being present != being loaded into Ogre and ready for rendering. if (!mesh->GetEntity()) { connect(mesh, SIGNAL(MeshChanged()), SLOT(TargetMeshReady()), Qt::UniqueConnection); return; } else connect(mesh, SIGNAL(MaterialChanged(uint, const QString&)), SLOT(TargetMeshMaterialChanged(uint, const QString&)), Qt::UniqueConnection); } if (sceneCanvasName_.isEmpty()) sceneCanvasName_ = "VlcMediaPlayerCanvas-" + QUuid::createUuid().toString().replace("{", "").replace("}", ""); // Get or create local EC_WidgetCanvas component ComponentPtr iComponent = parent->GetOrCreateComponent(EC_WidgetCanvas::TypeNameStatic(), sceneCanvasName_, AttributeChange::LocalOnly, false); EC_WidgetCanvas *sceneCanvas = dynamic_cast<EC_WidgetCanvas*>(iComponent.get()); if (!sceneCanvas) { LogError("EC_MediaPlayer: Could not get or create EC_WidgetCanvas component!"); return; } sceneCanvas->SetTemporary(true); sceneCanvas->SetSelfIllumination(getilluminating()); // All the needed components are present, mark prepared as true. componentPrepared_ = true; // We are now prepared, check enabled state and restore possible materials now if (!getenabled()) sceneCanvas->RestoreOriginalMeshMaterials(); // Show downloading info icon or if not downloading, // ask for a image update from the player if (pendingMediaDownload_) OnFrameUpdate(downloadingLogo_); else mediaPlayer_->ForceUpdateImage(); }