void AssetRefListListener::HandleChange(const AssetReferenceList &refs) { if (!assetAPI_) return; // Does a size check and compares each element with case-sensitive compare. if (refs == current_) return; AssetReferenceList prev = current_; // Set current internal refs current_ = refs; uint numRefs = current_.Size(); // Trim and resolve internal refs for (uint i=0; i<numRefs; ++i) { AssetReference &ref = current_[i]; ref.ref = ref.ref.Trimmed(); if (!ref.ref.Empty()) ref.ref = assetAPI_->ResolveAssetRef("", ref.ref); } // Changed Changed.Emit(current_); // Cleared for (uint i=0; i<numRefs; ++i) { const AssetReference &ref = current_[i]; const AssetReference &prevRef = (i < prev.Size() ? prev[i] : AssetReference()); if (ref.ref.Empty() && !prevRef.ref.Empty()) Cleared.Emit(i); } for(uint i = numRefs; i < prev.Size(); ++i) { if (!prev[i].ref.Empty()) Cleared.Emit(i); } // Request while(listeners_.Size() > numRefs) listeners_.Pop(); while(listeners_.Size() < numRefs) { // Connect to signals once on creation. AssetRefListeners // are reusable for multiple refs/requests. AssetRefListenerPtr listener(new AssetRefListener()); listener->TransferFailed.Connect(this, &AssetRefListListener::OnAssetFailed); listener->Loaded.Connect(this, &AssetRefListListener::OnAssetLoaded); listeners_.Push(listener); } for (uint i=0; i<numRefs; ++i) { const AssetReference &ref = current_[i]; if (!ref.ref.Empty()) listeners_[i]->HandleAssetRefChange(assetAPI_, ref.ref, ref.type); } }
void EC_Mesh::OnMaterialAssetLoaded(AssetPtr asset) { OgreMaterialAsset *ogreMaterial = dynamic_cast<OgreMaterialAsset*>(asset.get()); if (!ogreMaterial) { LogError("OnMaterialAssetLoaded: Material asset load finished for asset \"" + asset->Name().toStdString() + "\", but downloaded asset was not of type OgreMaterialAsset!"); return; } Ogre::MaterialPtr material = ogreMaterial->ogreMaterial; bool assetUsed = false; AssetReferenceList materialList = meshMaterial.Get(); for(int i = 0; i < materialList.Size(); ++i) if (materialList[i].ref == ogreMaterial->Name() || framework_->Asset()->LookupAssetRefToStorage(materialList[i].ref) == ogreMaterial->Name()) ///<///\todo The design of whether the LookupAssetRefToStorage should occur here, or internal to Asset API needs to be revisited. { SetMaterial(i, ogreMaterial->Name()); assetUsed = true; } if (!assetUsed) { LogWarning("OnMaterialAssetLoaded: Trying to apply material \"" + ogreMaterial->Name().toStdString() + "\" to mesh " + meshRef.Get().ref.toStdString() + ", but no submesh refers to the given material! The references are: "); for(int i = 0; i < materialList.Size(); ++i) LogWarning(QString::number(i).toStdString() + ": " + materialList[i].ref.toStdString()); } }
static duk_ret_t AssetReferenceList_Size(duk_context* ctx) { AssetReferenceList* thisObj = GetThisValueObject<AssetReferenceList>(ctx, AssetReferenceList_ID); uint ret = thisObj->Size(); duk_push_number(ctx, ret); return 1; }
template<> void TUNDRACORE_API Attribute<AssetReferenceList>::FromString(const std::string& str, AttributeChange::Type change) { AssetReferenceList value; QString strValue = QString::fromStdString(str); QStringList components = strValue.split(';'); for(int i = 0; i < components.size(); i++) value.Append(AssetReference(components[i])); if (value.Size() == 1 && value[0].ref.trimmed().isEmpty()) value.RemoveLast(); Set(value, change); }
void EC_Sky::OnAttributeUpdated(IAttribute* attribute) { if (!ViewEnabled()) return; if ((attribute->Name() == materialRef.Name() && materialRef.Get().ref != lastMaterial_ ) || (attribute->Name() == distance.Name() && distance.Get() != lastDistance_ ) || (attribute->Name() == drawFirst.Name() && drawFirst.Get() != lastDrawFirst_ )) { DisableSky(); CreateSky(); lastMaterial_ = materialRef.Get().ref; lastDistance_ = distance.Get(); lastDrawFirst_ = drawFirst.Get(); } else if (attribute->Name() == textureRefs.Name()) { AssetReferenceList textures = textureRefs.Get(); // Make sure that the asset ref list type stays intact. textures.type = "Texture"; textureRefs.Set(textures, AttributeChange::Disconnected); // Reallocate the number of texture asset reflisteners. while(textureAssets.size() > (size_t)textures.Size()) textureAssets.pop_back(); while(textureAssets.size() < (size_t)textures.Size()) textureAssets.push_back(boost::shared_ptr<AssetRefListener>(new AssetRefListener)); for(int i = 0; i < textures.Size(); ++i) { connect(textureAssets[i].get(), SIGNAL(Loaded(AssetPtr)), this, SLOT(OnTextureAssetLoaded(AssetPtr)), Qt::UniqueConnection); textureAssets[i]->HandleAssetRefChange(framework->Asset(), textures[i].ref); } //SetTextures(); } }
void EC_Mesh::ApplyMaterial() { AssetReferenceList materialList = meshMaterial.Get(); AssetAPI *assetAPI = framework_->Asset(); for(int i = 0; i < materialList.Size(); ++i) { if (!materialList[i].ref.isEmpty()) { // Only apply the material if it is loaded and has no dependencies QString assetFullName = assetAPI->LookupAssetRefToStorage(materialList[i].ref); AssetPtr asset = assetAPI->GetAsset(assetFullName); if ((asset) && (assetAPI->NumPendingDependencies(asset) == 0)) SetMaterial(i, assetFullName); } } }
bool EC_Mesh::HasMaterialsChanged() const { if(!entity_ || !meshMaterial.Get().Size()) return false; AssetReferenceList materials = meshMaterial.Get(); for(uint i = 0; i < entity_->getNumSubEntities(); i++) { // No point to continue if all materials are not set. if(i >= materials.Size()) break; if(entity_->getSubEntity(i)->getMaterial()->getName() != SanitateAssetIdForOgre(materials[i].ref.toStdString())) return true; } return false; }
bool EC_Mesh::SetMaterial(uint index, const QString& material_name, AttributeChange::Type change) { if (!entity_) return false; if (index >= entity_->getNumSubEntities()) { LogError("EC_Mesh::SetMaterial: Could not set material " + material_name + ": illegal submesh index " + QString::number(index) + ". Mesh \"" + meshRef.Get().ref + "\" has only " + QString::number(entity_->getNumSubEntities()) + " submeshes!"); return false; } try { entity_->getSubEntity(index)->setMaterialName(AssetAPI::SanitateAssetRef(material_name.toStdString())); if (pendingFailedMaterials_.contains(index)) pendingFailedMaterials_.removeAll(index); // Update the EC_Mesh material attribute list so that users can call EC_Mesh::SetMaterial as a replacement for setting // meshMaterial attribute. Only apply the change if the value really changed. AssetReferenceList materials = meshMaterial.Get(); while(materials.Size() <= (int)index) materials.Append(AssetReference()); if (material_name.compare(materials[index].ref, Qt::CaseSensitive) != 0) { materials.Set(index, AssetReference(material_name)); meshMaterial.Set(materials, change); // Potentially signal the change of attribute, if requested so. } // To retain compatibility with old behavior, always fire the EC_Mesh -specific change signal independent of the value of 'change'. emit MaterialChanged(index, material_name); } catch(Ogre::Exception& e) { LogError("EC_Mesh::SetMaterial: Could not set material " + material_name + ": " + e.what()); return false; } return true; }
void EC_SkyBox::SetTextures() { if (!ViewEnabled()) return; AssetReferenceList lst = textureRefs.Get(); std::vector<std::string> texture_names; texture_names.reserve(6); for(int i = 0; i < lst.Size() && i <= 6; ++i) texture_names.push_back(lst[i].ref.toStdString()); Ogre::MaterialPtr materialPtr = Ogre::MaterialManager::getSingleton().getByName(materialRef.Get().ref.toStdString().c_str()); if (!materialPtr.isNull() && texture_names.size() == 6) materialPtr->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setCubicTextureName(&texture_names[0], false); //skyMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureScale(1, -1); else if(!materialPtr.isNull() ) for(int i = 0; i < texture_names.size(); ++i) materialPtr->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setFrameTextureName(Ogre::String(texture_names[i].c_str()), i); DisableSky(); CreateSky(); }
void EC_Mesh::AttributesChanged() { if (drawDistance.ValueChanged()) { if(entity_) entity_->setRenderingDistance(drawDistance.Get()); } if (castShadows.ValueChanged()) { if(entity_) { if (entity_) entity_->setCastShadows(castShadows.Get()); /// \todo might want to disable shadows for some attachments for(uint i = 0; i < attachment_entities_.size(); ++i) { if (attachment_entities_[i]) attachment_entities_[i]->setCastShadows(castShadows.Get()); } } } if (nodeTransformation.ValueChanged()) { Transform newTransform = nodeTransformation.Get(); adjustment_node_->setPosition(newTransform.pos); adjustment_node_->setOrientation(newTransform.Orientation()); // Prevent Ogre exception from zero scale newTransform.scale = Max(newTransform.scale, float3::FromScalar(0.0000001f)); adjustment_node_->setScale(newTransform.scale); } if (meshRef.ValueChanged()) { if (!ViewEnabled()) return; if (meshRef.Get().ref.trimmed().isEmpty()) LogDebug("Warning: Mesh \"" + this->parentEntity->Name() + "\" mesh ref was set to an empty reference!"); meshAsset->HandleAssetRefChange(&meshRef); } if (meshMaterial.ValueChanged()) { if (!ViewEnabled()) return; AssetReferenceList materials = meshMaterial.Get(); // Reset all the materials from the submeshes which now have an empty material asset reference set. for(uint i = 0; i < GetNumMaterials(); ++i) { if ((int)i >= materials.Size() || materials[i].ref.trimmed().isEmpty()) { if (entity_ && entity_->getSubEntity(i)) entity_->getSubEntity(i)->setMaterialName(""); } } // Reallocate the number of material asset ref listeners. while(materialAssets.size() > (size_t)materials.Size()) materialAssets.pop_back(); while(materialAssets.size() < (size_t)materials.Size()) materialAssets.push_back(shared_ptr<AssetRefListener>(new AssetRefListener)); for(int i = 0; i < materials.Size(); ++i) { // Don't request empty refs. HandleAssetRefChange will just do unnecessary work and the below connections are for nothing. if (!materials[i].ref.trimmed().isEmpty()) { connect(materialAssets[i].get(), SIGNAL(Loaded(AssetPtr)), this, SLOT(OnMaterialAssetLoaded(AssetPtr)), Qt::UniqueConnection); connect(materialAssets[i].get(), SIGNAL(TransferFailed(IAssetTransfer*, QString)), this, SLOT(OnMaterialAssetFailed(IAssetTransfer*, QString)), Qt::UniqueConnection); materialAssets[i]->HandleAssetRefChange(framework->Asset(), materials[i].ref); } } }
void EC_Mesh::OnAttributeUpdated(IAttribute *attribute) { if (attribute == &drawDistance) { if(entity_) entity_->setRenderingDistance(drawDistance.Get()); } else if (attribute == &castShadows) { if(entity_) { if (entity_) entity_->setCastShadows(castShadows.Get()); /// \todo might want to disable shadows for some attachments for(uint i = 0; i < attachment_entities_.size(); ++i) { if (attachment_entities_[i]) attachment_entities_[i]->setCastShadows(castShadows.Get()); } } } else if (attribute == &nodeTransformation) { Transform newTransform = nodeTransformation.Get(); adjustment_node_->setPosition(newTransform.pos); adjustment_node_->setOrientation(newTransform.Orientation()); // Prevent Ogre exception from zero scale if (newTransform.scale.x < 0.0000001f) newTransform.scale.x = 0.0000001f; if (newTransform.scale.y < 0.0000001f) newTransform.scale.y = 0.0000001f; if (newTransform.scale.z < 0.0000001f) newTransform.scale.z = 0.0000001f; adjustment_node_->setScale(newTransform.scale); } else if (attribute == &meshRef) { if (!ViewEnabled()) return; //Ensure that mesh is requested only when it's has actually changed. // if(entity_) // if(QString::fromStdString(entity_->getMesh()->getName()) == meshRef.Get().ref/*meshResourceId.Get()*/) // return; /* AssetTransferPtr transfer = GetFramework()->Asset()->RequestAsset(meshRef.Get()); if (transfer) { connect(transfer.get(), SIGNAL(Succeeded(AssetPtr)), SLOT(OnMeshAssetLoaded()), Qt::UniqueConnection); } else { RemoveMesh(); } */ if (meshRef.Get().ref.trimmed().isEmpty()) LogDebug("Warning: Mesh \"" + this->parentEntity->Name().toStdString() + "\" mesh ref was set to an empty reference!"); meshAsset->HandleAssetRefChange(&meshRef); } else if (attribute == &meshMaterial) { if (!ViewEnabled()) return; // We won't request materials until we are sure that mesh has been loaded and it's safe to apply materials into it. // This logic shouldn't be necessary anymore. -jj. // if(!HasMaterialsChanged()) // return; AssetReferenceList materials = meshMaterial.Get(); // Make sure that the asset ref list type stays intact. materials.type = "OgreMaterial"; meshMaterial.Set(materials, AttributeChange::Disconnected); // Reallocate the number of material asset reflisteners. while(materialAssets.size() > (size_t)materials.Size()) materialAssets.pop_back(); while(materialAssets.size() < (size_t)materials.Size()) materialAssets.push_back(boost::shared_ptr<AssetRefListener>(new AssetRefListener)); for(int i = 0; i < materials.Size(); ++i) { connect(materialAssets[i].get(), SIGNAL(Loaded(AssetPtr)), this, SLOT(OnMaterialAssetLoaded(AssetPtr)), Qt::UniqueConnection); connect(materialAssets[i].get(), SIGNAL(TransferFailed(IAssetTransfer*, QString)), this, SLOT(OnMaterialAssetFailed(IAssetTransfer*, QString)), Qt::UniqueConnection); materialAssets[i]->HandleAssetRefChange(framework->Asset(), materials[i].ref); } } else if((attribute == &skeletonRef) && (!skeletonRef.Get().ref.isEmpty()))
void EC_Mesh::OnAttributeUpdated(IAttribute *attribute) { if (attribute == &drawDistance) { if(entity_) entity_->setRenderingDistance(drawDistance.Get()); } else if (attribute == &castShadows) { if(entity_) { if (entity_) entity_->setCastShadows(castShadows.Get()); //! \todo might want to disable shadows for some attachments for (uint i = 0; i < attachment_entities_.size(); ++i) { if (attachment_entities_[i]) attachment_entities_[i]->setCastShadows(castShadows.Get()); } } } else if (attribute == &nodeTransformation) { Ogre::Node* adjustmentTarget = adjustment_node_; if (bone_tagpoint_) adjustmentTarget = bone_tagpoint_; if (adjustmentTarget) { Transform newTransform = nodeTransformation.Get(); adjustmentTarget->setPosition(newTransform.position.x, newTransform.position.y, newTransform.position.z); Quaternion adjust(DEGTORAD * newTransform.rotation.x, DEGTORAD * newTransform.rotation.y, DEGTORAD * newTransform.rotation.z); // Let's not assume the needed haxor adjustment here, but let user specify it as necessary //adjust = Quaternion(PI/2, 0, PI) * adjust; adjustmentTarget->setOrientation(Ogre::Quaternion(adjust.w, adjust.x, adjust.y, adjust.z)); // Prevent Ogre exception from zero scale if (newTransform.scale.x < 0.0000001f) newTransform.scale.x = 0.0000001f; if (newTransform.scale.y < 0.0000001f) newTransform.scale.y = 0.0000001f; if (newTransform.scale.z < 0.0000001f) newTransform.scale.z = 0.0000001f; adjustmentTarget->setScale(newTransform.scale.x, newTransform.scale.y, newTransform.scale.z); } } else if (attribute == &meshRef) { if (!ViewEnabled()) return; //Ensure that mesh is requested only when it's has actually changed. // if(entity_) // if(QString::fromStdString(entity_->getMesh()->getName()) == meshRef.Get().ref/*meshResourceId.Get()*/) // return; /* AssetTransferPtr transfer = GetFramework()->Asset()->RequestAsset(meshRef.Get()); if (transfer) { connect(transfer.get(), SIGNAL(Loaded(AssetPtr)), SLOT(OnMeshAssetLoaded()), Qt::UniqueConnection); } else { RemoveMesh(); } */ if (meshRef.Get().ref.trimmed().isEmpty()) LogDebug("Warning: Mesh \"" + this->parent_entity_->GetName().toStdString() + "\" mesh ref was set to an empty reference!"); meshAsset->HandleAssetRefChange(&meshRef); } else if (attribute == &meshMaterial) { if (!ViewEnabled()) return; // We won't request materials until we are sure that mesh has been loaded and it's safe to apply materials into it. // This logic shouldn't be necessary anymore. -jj. // if(!HasMaterialsChanged()) // return; AssetReferenceList materials = meshMaterial.Get(); // Reallocate the number of material asset reflisteners. while(materialAssets.size() > materials.Size()) materialAssets.pop_back(); while(materialAssets.size() < materials.Size()) materialAssets.push_back(boost::shared_ptr<AssetRefListener>(new AssetRefListener)); for(int i = 0; i < materials.Size(); ++i) { connect(materialAssets[i].get(), SIGNAL(Loaded(AssetPtr)), this, SLOT(OnMaterialAssetLoaded(AssetPtr)), Qt::UniqueConnection); materialAssets[i]->HandleAssetRefChange(framework_->Asset(), materials[i].ref); } } else if((attribute == &skeletonRef) && (!skeletonRef.Get().ref.isEmpty())) { if (!ViewEnabled()) return; // If same name skeleton already set no point to do it again. // if (entity_ && entity_->getSkeleton() && entity_->getSkeleton()->getName() == skeletonRef.Get().ref/*skeletonId.Get()*/.toStdString()) // return; // AssetTransferPtr transfer = GetFramework()->Asset()->RequestAsset(skeletonRef.Get().ref); // if (transfer) // connect(transfer.get(), SIGNAL(Loaded(AssetPtr)), SLOT(OnSkeletonAssetLoaded(AssetPtr)), Qt::UniqueConnection); skeletonAsset->HandleAssetRefChange(&skeletonRef); } }