diff options
Diffstat (limited to 'NvBlast/tools/ArtistTools/source/BlastPlugin/Window/BlastSceneTree.cpp')
| -rw-r--r-- | NvBlast/tools/ArtistTools/source/BlastPlugin/Window/BlastSceneTree.cpp | 1804 |
1 files changed, 1804 insertions, 0 deletions
diff --git a/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/BlastSceneTree.cpp b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/BlastSceneTree.cpp new file mode 100644 index 0000000..64a7c2f --- /dev/null +++ b/NvBlast/tools/ArtistTools/source/BlastPlugin/Window/BlastSceneTree.cpp @@ -0,0 +1,1804 @@ +#include "BlastSceneTree.h" +#include <QtWidgets/QMessageBox> +#include <QtWidgets/QLineEdit> +#include <QtWidgets/QPushButton> +#include <QtWidgets/QCheckBox> +#include <QtWidgets/QMenu> +#include <QtCore/QFileInfo> +#include <assert.h> +#include "ProjectParams.h" +#include <SimpleScene.h> +#include <BlastController.h> +#include <SceneController.h> +#include <NvBlastExtPxAsset.h> +#include <NvBlastTkAsset.h> +#include <NvBlastAsset.h> +#include <BlastFamilyModelSimple.h> + +bool isChunkVisible(std::vector<BlastFamily*>& fs, uint32_t chunkIndex) +{ + int fsSize = fs.size(); + if (fsSize == 0) + { + return false; + } + + bool visible = false; + for (int i = 0; i < fsSize; i++) + { + if (fs[i]->isChunkVisible(chunkIndex)) + { + visible = true; + break; + } + } + return visible; +} + +void setChunkVisible(std::vector<BlastFamily*>& fs, uint32_t chunkIndex, bool visible) +{ + int fsSize = fs.size(); + if (fsSize == 0) + { + return; + } + + for (int i = 0; i < fsSize; i++) + { + fs[i]->setChunkVisible(chunkIndex, visible); + } +} + +void setChunkSelected(std::vector<BlastFamily*>& fs, uint32_t chunkIndex, bool selected) +{ + int fsSize = fs.size(); + if (fsSize == 0) + { + return; + } + + for (int i = 0; i < fsSize; i++) + { + fs[i]->setChunkSelected(chunkIndex, selected); + } +} + +void BlastChunkNode::setVisible(bool val) +{ + BPPChunk* pBPPChunk = (BPPChunk*)_data; + pBPPChunk->visible = val; + + BlastAsset* pBlastAsset = (BlastAsset*)_assetPtr; + + SampleManager& sampleManager = SimpleScene::Inst()->GetSampleManager(); + + std::map<BlastAsset*, std::vector<BlastFamily*>>& AssetFamiliesMap = sampleManager.getAssetFamiliesMap(); + std::vector<BlastFamily*>& fs = AssetFamiliesMap[pBlastAsset]; + + setChunkVisible(fs, pBPPChunk->ID, val); +} + +void BlastChunkNode::setSelected(bool val) +{ + BPPChunk* pBPPChunk = (BPPChunk*)_data; + pBPPChunk->visible = val; + + BlastAsset* pBlastAsset = (BlastAsset*)_assetPtr; + + SampleManager& sampleManager = SimpleScene::Inst()->GetSampleManager(); + + std::map<BlastAsset*, std::vector<BlastFamily*>>& AssetFamiliesMap = sampleManager.getAssetFamiliesMap(); + std::vector<BlastFamily*>& fs = AssetFamiliesMap[pBlastAsset]; + + setChunkSelected(fs, pBPPChunk->ID, val); +} + +void BlastAssetInstanceNode::setSelected(bool val) +{ + BPPAssetInstance* pBPPAssetInstance = (BPPAssetInstance*)_data; + std::string name = pBPPAssetInstance->name; + + std::string strAsset = name.substr(0, name.find_first_of("_")); + BlastAsset* pBlastAsset = nullptr; + SampleManager& sampleManager = SimpleScene::Inst()->GetSampleManager(); + std::map<BlastAsset*, AssetList::ModelAsset>& AssetDescMap = sampleManager.getAssetDescMap(); + std::map<BlastAsset*, AssetList::ModelAsset>::iterator itAssetDescMap; + for (itAssetDescMap = AssetDescMap.begin(); + itAssetDescMap != AssetDescMap.end(); itAssetDescMap++) + { + AssetList::ModelAsset& model = itAssetDescMap->second; + if (model.name == strAsset) + { + pBlastAsset = itAssetDescMap->first; + break; + } + } + + std::string strIndex = name.substr(name.find_last_of("_") + 1); + int nIndex = atoi(strIndex.c_str()); + + sampleManager.setCurrentSelectedInstance(pBlastAsset, nIndex); +} + +BlastTreeData& BlastTreeData::ins() +{ + static BlastTreeData _ins; + return _ins; +} + +bool BlastTreeData::isChild(BlastChunkNode* parent, BlastChunkNode* child) +{ + if (parent == nullptr || child == nullptr) + return false; + + BlastNode* curParent = child->getParent(); + while (eChunk == curParent->getType() && curParent != nullptr) + { + if (curParent == parent) + return true; + curParent = curParent->getParent(); + } + + return false; +} + +std::vector<BlastChunkNode*> BlastTreeData::getTopChunkNodes(std::vector<BlastChunkNode*>& nodes) +{ + std::vector<BlastChunkNode*> result; + + for (size_t i = 0; i < nodes.size(); ++i) + { + bool isCurNodeTop = true; + for (size_t j = 0; j < nodes.size(); ++j) + { + if (i != j && isChild(nodes[i], nodes[j])) + { + isCurNodeTop = false; + break; + } + } + + if (isCurNodeTop) + { + result.push_back(nodes[i]); + } + } + + return result; +} + +bool BlastTreeData::isRoot(BlastChunkNode* node) +{ + if (node == nullptr || node->getParent() == nullptr) + return false; + + return eAsset == node->getParent()->getType(); +} + +bool BlastTreeData::isLeaf(BlastChunkNode* node) +{ + if (node == nullptr) + return false; + + for (BlastNode* curNode : node->children) + { + if (eChunk == curNode->getType()) + return false; + } + + return true; +} + +void removeChunkNodeSupport(BlastChunkNode* node) +{ + if (node == nullptr) + return; + + BPPChunk* chunk = static_cast<BPPChunk*>(node->getData()); + chunk->support = false; + + for (BlastNode* curNode : node->children) + { + if (eChunk == curNode->getType()) + { + removeChunkNodeSupport((BlastChunkNode*)curNode); + } + } +} + +void BlastTreeData::makeSupport(BlastChunkNode* node) +{ + if (node == nullptr) + return; + BPPChunk* chunk = static_cast<BPPChunk*>(node->getData()); + chunk->staticFlag = false; + chunk->support = true; + + for (BlastNode* curNode : node->children) + { + if (eChunk == curNode->getType()) + { + removeChunkNodeSupport((BlastChunkNode*)curNode); + } + } +} + +void BlastTreeData::makeStaticSupport(BlastChunkNode* node) +{ + if (node == nullptr) + return; + BPPChunk* chunk = static_cast<BPPChunk*>(node->getData()); + chunk->staticFlag = true; + chunk->support = true; + + for (BlastNode* curNode : node->children) + { + if (eChunk == curNode->getType()) + { + removeChunkNodeSupport((BlastChunkNode*)curNode); + } + } +} + +void BlastTreeData::removeSupport(BlastChunkNode* node) +{ + if (node == nullptr) + return; + + if (isLeaf(node)) + return; + + BPPChunk* chunk = static_cast<BPPChunk*>(node->getData()); + chunk->support = false; + chunk->staticFlag = false; + + for (BlastNode* curNode : node->children) + { + if (eChunk == curNode->getType()) + { + BPPChunk* curChunk = static_cast<BPPChunk*>(curNode->getData()); + curChunk->support = true; + } + } +} + +BlastNode* BlastTreeData::getBlastNodeByProjectData(void* data) +{ + std::map<void*, BlastNode*>::iterator itr = _blastProjectDataToNodeMap.find(data); + if (itr != _blastProjectDataToNodeMap.end()) + return itr->second; + + return nullptr; +} + +struct ChunkSupport +{ + ChunkSupport() + { + m_bSupport = false; + } + + bool m_bSupport; +}; + +struct BondChunkIndices +{ + BondChunkIndices() + { + chunkIndices[0] = -1; + chunkIndices[1] = -1; + } + + void SetIndices(uint32_t chunkIndex0, uint32_t chunkIndex1) + { + if (chunkIndex0 < chunkIndex1) + { + chunkIndices[0] = chunkIndex0; + chunkIndices[1] = chunkIndex1; + } + else + { + chunkIndices[0] = chunkIndex1; + chunkIndices[1] = chunkIndex0; + } + } + + uint32_t chunkIndices[2]; +}; + +void BlastTreeData::update() +{ + _freeBlastNode(); + + BPPBlast& blast = BlastProject::ins().getParams().blast; + std::vector<BlastAsset*> BlastAssetVec; + { + SampleManager& sampleManager = SimpleScene::Inst()->GetSampleManager(); + + std::map<BlastAsset*, std::vector<BlastFamily*>>& AssetFamiliesMap = sampleManager.getAssetFamiliesMap(); + std::map<BlastAsset*, AssetList::ModelAsset>& AssetDescMap = sampleManager.getAssetDescMap(); + + BlastController& blastController = sampleManager.getBlastController(); + SceneController& sceneController = sampleManager.getSceneController(); + + std::vector<BlastFamilyPtr>& families = blastController.getFamilies(); + int familiesSize = families.size(); + + std::map<BlastAsset*, AssetList::ModelAsset>::iterator it; + for (it = AssetDescMap.begin(); it != AssetDescMap.end(); it++) + { + BlastAssetVec.push_back(it->first); + } + int modelAssetsSize = AssetDescMap.size(); + + std::vector<std::string> projectilesNames; + sceneController.GetProjectilesNames(projectilesNames); + + // compoistie + { + BPPComposite& composite = blast.composite; + composite.composite.buf = nullptr; + composite.visible = true; + + copy(composite.composite, "BlastComposite"); + + // asset instance array + { + BPPAssetInstanceArray& instanceArray = composite.blastAssetInstances; + instanceArray.arraySizes[0] = familiesSize; + if (familiesSize > 0) + { + instanceArray.buf = new BPPAssetInstance[familiesSize]; + int curInstanceIndex = 0; + char instancename[50]; + std::map<BlastAsset*, std::vector<BlastFamily*>>::iterator itAssetFamiliesMap; + for (itAssetFamiliesMap = AssetFamiliesMap.begin(); + itAssetFamiliesMap != AssetFamiliesMap.end(); itAssetFamiliesMap++) + { + BlastAsset* pBlastAsset = itAssetFamiliesMap->first; + std::vector<BlastFamily*>& fs = itAssetFamiliesMap->second; + int fsSize = fs.size(); + for (int i = 0; i < fsSize; i++) + { + BPPAssetInstance& instance = instanceArray.buf[curInstanceIndex]; + instance.name.buf = nullptr; + instance.source.buf = nullptr; + instance.visible = true; + + AssetList::ModelAsset desc = AssetDescMap[pBlastAsset]; + sprintf(instancename, "%s_Instance_%d", desc.name.c_str(), i); + copy(instance.name, instancename); + + std::string assetFilePath = SampleManager::ins()->getConfig().additionalResourcesDir.back() + "/models/" + desc.file + ".bpxa"; + sprintf(instancename, "%s", assetFilePath.c_str()); + copy(instance.source, instancename); + + PxVec3 p = desc.transform.p; + PxQuat q = desc.transform.q; + instanceArray.buf[curInstanceIndex].transform.position = nvidia::NvVec3(p.x, p.y, p.z); + instanceArray.buf[curInstanceIndex].transform.rotation = nvidia::NvVec4(q.x, q.y, q.z, q.w); + + curInstanceIndex++; + } + } + } + } + + // landmark array + if (0) + { + BPPLandmarkArray& landmarkArray = composite.landmarks; + landmarkArray.buf = new BPPLandmark[2]; + landmarkArray.arraySizes[0] = 2; + landmarkArray.buf[0].name.buf = nullptr; + landmarkArray.buf[1].name.buf = nullptr; + + copy(landmarkArray.buf[0].name, "Landmark_1"); + copy(landmarkArray.buf[1].name, "Landmark_2"); + } + } + + // asset array + { + BPPAssetArray& assetArray = blast.blastAssets; + assetArray.arraySizes[0] = modelAssetsSize; + if (modelAssetsSize > 0) + { + assetArray.buf = new BPPAsset[modelAssetsSize]; + int curAssetIndex = 0; + + blast.chunks.buf = nullptr; + blast.chunks.arraySizes[0] = 0; + blast.bonds.buf = nullptr; + blast.bonds.arraySizes[0] = 0; + + std::map<BlastAsset*, AssetList::ModelAsset>::iterator itAssetDescMap; + for (itAssetDescMap = AssetDescMap.begin(); + itAssetDescMap != AssetDescMap.end(); itAssetDescMap++) + { + BlastAsset* pBlastAsset = itAssetDescMap->first; + AssetList::ModelAsset& desc = itAssetDescMap->second; + std::vector<BlastFamily*>& fs = AssetFamiliesMap[pBlastAsset]; + + BPPAsset& asset = assetArray.buf[curAssetIndex]; + asset.path.buf = nullptr; + asset.activePreset.buf = nullptr; + std::string assetFilePath = SampleManager::ins()->getConfig().additionalResourcesDir.back() + "/models/" + desc.file + ".bpxa"; + copy(asset.path, assetFilePath.c_str()); + + const ExtPxAsset* pExtPxAsset = pBlastAsset->getPxAsset(); + const ExtPxChunk* pExtPxChunk = pExtPxAsset->getChunks(); + + const TkAsset& tkAsset = pExtPxAsset->getTkAsset(); + uint32_t chunkCount = tkAsset.getChunkCount(); + const NvBlastChunk* pNvBlastChunk = tkAsset.getChunks(); + uint32_t bondCount = tkAsset.getBondCount(); + const NvBlastBond* pNvBlastBond = tkAsset.getBonds(); + + const NvBlastSupportGraph supportGraph = tkAsset.getGraph(); + uint32_t* chunkIndices = supportGraph.chunkIndices; + uint32_t* adjacencyPartition = supportGraph.adjacencyPartition; + uint32_t* adjacentNodeIndices = supportGraph.adjacentNodeIndices; + uint32_t* adjacentBondIndices = supportGraph.adjacentBondIndices; + + ChunkSupport* pSupport = new ChunkSupport[chunkCount]; + BondChunkIndices* pBCIndices = new BondChunkIndices[bondCount]; + + for (uint32_t node0 = 0; node0 < supportGraph.nodeCount; ++node0) + { + const uint32_t chunkIndex0 = supportGraph.chunkIndices[node0]; + + pSupport[chunkIndex0].m_bSupport = true; + + for (uint32_t adjacencyIndex = adjacencyPartition[node0]; adjacencyIndex < adjacencyPartition[node0 + 1]; adjacencyIndex++) + { + uint32_t node1 = supportGraph.adjacentNodeIndices[adjacencyIndex]; + + // add this condition if you don't want to iterate all bonds twice + if (node0 > node1) + continue; + + const uint32_t chunkIndex1 = supportGraph.chunkIndices[node1]; + + uint32_t bondIndex = supportGraph.adjacentBondIndices[adjacencyIndex]; + + pBCIndices[bondIndex].SetIndices(chunkIndex0, chunkIndex1); + } + } + + // chunks + { + BPPChunkArray curArray; + curArray.buf = new BPPChunk[chunkCount]; + curArray.arraySizes[0] = chunkCount; + char chunkname[10]; + for (int cc = 0; cc < chunkCount; ++cc) + { + BPPChunk& chunk = curArray.buf[cc]; + chunk.name.buf = nullptr; + chunk.asset.buf = nullptr; + + std::vector<uint32_t> parentChunkIndexes; + parentChunkIndexes.push_back(cc); + uint32_t parentChunkIndex = cc; + while ((parentChunkIndex = pNvBlastChunk[parentChunkIndex].parentChunkIndex) != -1) + { + parentChunkIndexes.push_back(parentChunkIndex); + } + + std::string strChunkName = "Chunk"; + for (int pcIndex = parentChunkIndexes.size() - 1; pcIndex >= 0; pcIndex--) + { + sprintf(chunkname, "_%d", parentChunkIndexes[pcIndex]); + strChunkName += chunkname; + } + copy(chunk.name, strChunkName.c_str()); + + copy(chunk.asset, asset.path); + chunk.ID = cc; + chunk.parentID = pNvBlastChunk[cc].parentChunkIndex; + chunk.staticFlag = pExtPxChunk[cc].isStatic; + chunk.visible = isChunkVisible(fs, cc); + chunk.support = pSupport[cc].m_bSupport; + } + + merge(blast.chunks, curArray); + freeBlast(curArray); + } + + // bonds + { + BPPBondArray curArray; + curArray.buf = new BPPBond[bondCount]; + curArray.arraySizes[0] = bondCount; + char bondname[10]; + bool visible; + for (int bc = 0; bc < bondCount; ++bc) + { + BPPBond& bond = curArray.buf[bc]; + bond.name.buf = nullptr; + bond.asset.buf = nullptr; + + visible = isChunkVisible(fs, pBCIndices[bc].chunkIndices[0]) + || isChunkVisible(fs, pBCIndices[bc].chunkIndices[1]); + bond.visible = visible; + bond.support.healthMask.buf = nullptr; // ? + bond.fromChunk = pBCIndices[bc].chunkIndices[0]; + bond.toChunk = pBCIndices[bc].chunkIndices[1]; + + sprintf(bondname, "Bond_%d_%d", bond.fromChunk, bond.toChunk); + copy(bond.name, bondname); + copy(bond.asset, asset.path); + } + + merge(blast.bonds, curArray); + freeBlast(curArray); + } + + delete[] pSupport; + pSupport = nullptr; + delete[] pBCIndices; + pBCIndices = nullptr; + + curAssetIndex++; + } + } + } + + // projectile + { + BPPProjectileArray& projectileArray = blast.projectiles; + int BPPProjectileSize = projectilesNames.size(); + projectileArray.arraySizes[0] = BPPProjectileSize; + if (BPPProjectileSize > 0) + { + projectileArray.buf = new BPPProjectile[BPPProjectileSize]; + for (int i = 0; i < BPPProjectileSize; i++) + { + projectileArray.buf[i].name.buf = nullptr; + copy(projectileArray.buf[i].name, projectilesNames[i].c_str()); + projectileArray.buf[i].visible = true; + } + } + } + + // graphics meshes + if (0) + { + BPPGraphicsMeshArray& graphicsMeshArray = blast.graphicsMeshes; + graphicsMeshArray.buf = new BPPGraphicsMesh[3]; + graphicsMeshArray.arraySizes[0] = 3; + graphicsMeshArray.buf[0].name.buf = nullptr; + copy(graphicsMeshArray.buf[0].name, "SurfaceMesh1"); + graphicsMeshArray.buf[0].visible = true; + + graphicsMeshArray.buf[1].name.buf = nullptr; + copy(graphicsMeshArray.buf[1].name, "SurfaceMesh2"); + graphicsMeshArray.buf[1].visible = true; + + graphicsMeshArray.buf[2].name.buf = nullptr; + copy(graphicsMeshArray.buf[2].name, "DisplayMesh1"); + graphicsMeshArray.buf[2].visible = true; + } + } + + BPPAssetArray& assetArray = blast.blastAssets; + + int count = assetArray.arraySizes[0]; + for (int c = 0; c < count; ++c) + { + BPPAsset& asset = assetArray.buf[c]; + QFileInfo fileInfo(asset.path.buf); + BlastAssetNode* assetNode = new BlastAssetNode(fileInfo.baseName().toUtf8().data(), asset); + _assets.push_back(assetNode); + _blastProjectDataToNodeMap.insert(std::make_pair((void*)&asset, assetNode)); + + // get the firlst level chunks whose parentID is -1 + std::vector<BPPChunk*> childChunks = BlastProject::ins().getChildrenChunks(asset, -1); + + for (size_t i = 0; i < childChunks.size(); ++i) + { + BPPChunk& chunk = *(childChunks[i]); + BlastChunkNode* chunkNode = new BlastChunkNode(chunk.name.buf, chunk, BlastAssetVec[c]); + assetNode->children.push_back(chunkNode); + chunkNode->setParent(assetNode); + _blastProjectDataToNodeMap.insert(std::make_pair((void*)&chunk, chunkNode)); + _addChunkNode(chunk, asset, chunkNode, BlastAssetVec[c]); + } + } + + BPPComposite& composite = blast.composite; + _composite = new BlastCompositeNode(composite.composite.buf, composite); + _blastProjectDataToNodeMap.insert(std::make_pair((void*)&composite, _composite)); + BPPAssetInstanceArray& assetInstanceArray = composite.blastAssetInstances; + count = assetInstanceArray.arraySizes[0]; + for (int i = 0; i < count; ++i) + { + BPPAssetInstance& blastAssetInstance = composite.blastAssetInstances.buf[i]; + BlastAssetInstanceNode* blastAssetInstanceNode = new BlastAssetInstanceNode(blastAssetInstance.name.buf, blastAssetInstance); + _composite->children.push_back(blastAssetInstanceNode); + blastAssetInstanceNode->setParent(_composite); + _blastProjectDataToNodeMap.insert(std::make_pair((void*)&blastAssetInstance, blastAssetInstanceNode)); + } + + BPPLandmarkArray& landmarkArray = composite.landmarks; + count = landmarkArray.arraySizes[0]; + for (int i = 0; i < count; ++i) + { + BPPLandmark& landmark = composite.landmarks.buf[i]; + BlastLandmarkNode* landmarkNode = new BlastLandmarkNode(landmark.name.buf, landmark); + _composite->children.push_back(landmarkNode); + landmarkNode->setParent(_composite); + _blastProjectDataToNodeMap.insert(std::make_pair((void*)&landmark, landmarkNode)); + } + + BPPProjectileArray& projectileArray = blast.projectiles; + count = projectileArray.arraySizes[0]; + for (int i = 0; i < count; ++i) + { + BPPProjectile& projectile = projectileArray.buf[i]; + BlastProjectileNode* projectileNode = new BlastProjectileNode(projectile.name.buf, projectile); + _projectiles.push_back(projectileNode); + _blastProjectDataToNodeMap.insert(std::make_pair((void*)&projectile, projectileNode)); + } + + BPPGraphicsMeshArray& graphicsMeshArray = blast.graphicsMeshes; + count = graphicsMeshArray.arraySizes[0]; + for (int i = 0; i < count; ++i) + { + BPPGraphicsMesh& graphicsMesh = graphicsMeshArray.buf[i]; + BlastGraphicsMeshNode* projectileNode = new BlastGraphicsMeshNode(graphicsMesh.name.buf, graphicsMesh); + _graphicsMeshes.push_back(projectileNode); + } +} + +void BlastTreeData::updateVisible(uint32_t assetIndex, uint32_t chunkIndex, bool visible) +{ + BPPBlast& blast = BlastProject::ins().getParams().blast; + BPPAssetArray& assetArray = blast.blastAssets; + if (assetIndex < assetArray.arraySizes[0]) + { + BPPAsset& asset = assetArray.buf[assetIndex]; + + std::vector<BPPChunk*> childChunks = BlastProject::ins().getChildrenChunks(asset); + if (chunkIndex < childChunks.size()) + { + BPPChunk& chunk = *(childChunks[chunkIndex]); + chunk.visible = visible; + } + } +} + + +BlastChunkNode* findChunkNode(BlastChunkNode* chunkNode, uint32_t chunkIndex) +{ + if (chunkNode == nullptr) + return nullptr; + + if (((BPPChunk*)chunkNode->getData())->ID == chunkIndex) + return chunkNode; + + std::vector<BlastNode*>& children = chunkNode->children; + for (size_t i = 0; i < children.size(); ++i) + { + BlastNode* node = children[i]; + if (node->getType() == eChunk) + { + BlastChunkNode* chunkNode = findChunkNode(static_cast<BlastChunkNode*>(node), chunkIndex); + if (chunkNode) + { + return chunkNode; + } + else + continue; + } + + else + continue; + } + + return nullptr; +} + +std::vector<BlastChunkNode*> BlastTreeData::getChunkNodeByBlastChunk(const BlastAsset* asset, const std::vector<uint32_t>& chunkIndexes) +{ + std::vector<BlastChunkNode*> chunkNodes; + if (asset == nullptr || chunkIndexes.size() == 0) + { + return chunkNodes; + } + + BlastAssetNode* assetNode = _getAssetNode(asset); + if (assetNode) + { + std::vector<BlastNode*>& children = assetNode->children; + for (BlastNode* node : children) + { + if (node->getType() == eChunk) + { + for (uint32_t chunkId : chunkIndexes) + { + BlastChunkNode* chunkNode = findChunkNode(static_cast<BlastChunkNode*>(node), chunkId); + if (chunkNode) + { + chunkNodes.push_back(chunkNode); + } + } + } + } + } + + return chunkNodes; +} + +bool isCompleteSupport(BlastChunkNode* node) +{ + if (node == nullptr) + return false; + + if (node->isSupport()) + return true; + + const std::vector<BlastNode*>& children = node->children; + for (BlastNode* curNode : children) + { + if (eChunk == curNode->getType()) + { + BlastChunkNode* chunkNode = (BlastChunkNode*)curNode; + if (0 == chunkNode->children.size()) + { + if (!chunkNode->isSupport()) + return false; + } + + if (!isCompleteSupport(chunkNode)) + return false; + } + } + + return true; +} + +bool BlastTreeData::isCompleteSupportAsset(const BlastAsset* asset) +{ + BlastAssetNode* assetNode = _getAssetNode(asset); + return isCompleteSupportAsset(assetNode); +} + +bool BlastTreeData::isCompleteSupportAsset(const BlastAssetNode* node) +{ + if (node == nullptr) + return false; + + const std::vector<BlastNode*>& children = node->children; + for (BlastNode* curNode : children) + { + if (eChunk == curNode->getType()) + { + BlastChunkNode* chunkNode = (BlastChunkNode*)curNode; + if (!isCompleteSupport(chunkNode)) + return false; + } + } + + return true; +} + +bool BlastTreeData::isOverlapSupportAsset(const BlastAsset* asset) +{ + BlastAssetNode* assetNode = _getAssetNode(asset); + return isOverlapSupportAsset(assetNode); +} + +bool isOverlapSupport(BlastChunkNode* node) +{ + if (node == nullptr) + return false; + + bool isParentSupport = node->isSupport(); + + const std::vector<BlastNode*>& children = node->children; + for (BlastNode* curNode : children) + { + if (eChunk == curNode->getType()) + { + BlastChunkNode* chunkNode = (BlastChunkNode*)curNode; + if (0 == chunkNode->children.size()) + { + if (isParentSupport && chunkNode->isSupport()) + return true; + } + + if (isParentSupport && isOverlapSupport(chunkNode)) + return true; + } + } + + return false; +} + +bool BlastTreeData::isOverlapSupportAsset(const BlastAssetNode* node) +{ + if (node == nullptr) + return false; + + const std::vector<BlastNode*>& children = node->children; + for (BlastNode* curNode : children) + { + if (eChunk == curNode->getType()) + { + BlastChunkNode* chunkNode = (BlastChunkNode*)curNode; + if (isOverlapSupport(chunkNode)) + return true; + } + } + + return false; +} + +BlastTreeData::BlastTreeData() +{ + +} + +void BlastTreeData::_addChunkNode(const BPPChunk& parentData, BPPAsset& asset, BlastChunkNode* parentNode, void* assetPtr) +{ + if (parentNode != nullptr) + { + std::vector<BPPBond*> bonds = BlastProject::ins().getBondsByChunk(asset, parentData.ID); + for (size_t i = 0; i < bonds.size(); ++i) + { + BPPBond* bond = bonds[i]; + BlastBondNode* bondNode = new BlastBondNode(bond->name.buf, *bond); + parentNode->children.push_back(bondNode); + bondNode->setParent(parentNode); + _blastProjectDataToNodeMap.insert(std::make_pair((void*)bond, bondNode)); + } + + std::vector<BPPChunk*> childChunks = BlastProject::ins().getChildrenChunks(asset, parentData.ID); + + for (size_t i = 0; i < childChunks.size(); ++i) + { + BPPChunk& chunk = *(childChunks[i]); + BlastChunkNode* chunkNode = new BlastChunkNode(chunk.name.buf, chunk, assetPtr); + parentNode->children.push_back(chunkNode); + chunkNode->setParent(parentNode); + _blastProjectDataToNodeMap.insert(std::make_pair((void*)&chunk, chunkNode)); + _addChunkNode(chunk, asset, chunkNode, assetPtr); + } + } +} + +void freeChunkNode(BlastChunkNode* chunkNode) +{ + if (chunkNode == nullptr) + return; + + std::vector<BlastNode*>& children = chunkNode->children; + for (size_t i = 0; i < children.size(); ++i) + { + BlastNode* node = children[i]; + if (node->getType() == eChunk) + freeChunkNode(static_cast<BlastChunkNode*>(node)); + else + { + delete node; + node = nullptr; + } + } + + delete chunkNode; + chunkNode = nullptr; +} + +void BlastTreeData::_freeBlastNode() +{ + if (_composite) + { + size_t count = _composite->children.size(); + for (size_t i = 0; i < count; ++i) + { + delete _composite->children[i]; + } + delete _composite; + _composite = nullptr; + } + + size_t count = _assets.size(); + for (size_t i = 0; i < count; ++i) + { + std::vector<BlastNode*>& children = _assets[i]->children; + for (size_t j = 0; j < children.size(); ++j) + { + freeChunkNode(static_cast<BlastChunkNode*>(children[j])); + } + delete _assets[i]; + } + _assets.clear(); + + count = _projectiles.size(); + for (size_t i = 0; i < count; ++i) + { + delete _projectiles[i]; + } + _projectiles.clear(); + + count = _graphicsMeshes.size(); + for (size_t i = 0; i < count; ++i) + { + delete _graphicsMeshes[i]; + } + _graphicsMeshes.clear(); + + _blastProjectDataToNodeMap.clear(); +} + +BlastAssetNode* BlastTreeData::_getAssetNode(const BlastAsset* asset) +{ + std::map<BlastAsset*, AssetList::ModelAsset>& assetDescMap = SampleManager::ins()->getAssetDescMap(); + std::map<BlastAsset*, AssetList::ModelAsset>::iterator itrAssetDesc = assetDescMap.find(const_cast<BlastAsset*>(asset)); + + BlastAssetNode* foundAssetNode = nullptr; + for (BlastAssetNode* assetNode : _assets) + { + if (itrAssetDesc->second.name == assetNode->name) + { + foundAssetNode = assetNode; + break; + } + } + + return foundAssetNode; +} + +VisualButton::VisualButton(QWidget* parent, BlastNode* blastItem) + : QWidget(parent) + , _button(new QPushButton(parent)) + , _blastItem(blastItem) +{ + connect(_button, SIGNAL(toggled(bool)), this, SLOT(on_visualbility_toggled(bool))); + _button->setCheckable(true); + _button->setChecked(blastItem->getVisible()); + if (blastItem->getVisible()) + _button->setIcon(QIcon(":/AppMainWindow/images/visibilityToggle_visible.png")); + else + _button->setIcon(QIcon(":/AppMainWindow/images/visibilityToggle_notVisible.png")); + _button->setFixedSize(20, 20); + this->setLayoutDirection(Qt::RightToLeft); + this->setLayout(new QHBoxLayout); + this->layout()->setMargin(0); + this->layout()->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum)); + this->layout()->addWidget(_button); +} + +void VisualButton::on_visualbility_toggled(bool checked) +{ + if (checked) + { + _button->setIcon(QIcon(":/AppMainWindow/images/visibilityToggle_visible.png")); + } + else + { + _button->setIcon(QIcon(":/AppMainWindow/images/visibilityToggle_notVisible.png")); + } + + if (_blastItem) + { + _blastItem->setVisible(checked); + } +} + +void VisualButton::_updateBlast(bool visible) +{ + EBlastNodeType type = _blastItem->getType(); + + switch (type) + { + case eBond: + ((BPPBond*)_blastItem->getData())->visible = visible; + break; + case eChunk: + ((BPPChunk*)_blastItem->getData())->visible = visible; + break; + case eAsset: + ((BPPAsset*)_blastItem->getData())->visible = visible; + break; + case eProjectile: + ((BPPBond*)_blastItem->getData())->visible = visible; + break; + case eGraphicsMesh: + ((BPPGraphicsMesh*)_blastItem->getData())->visible = visible; + break; + case eAssetInstance: + ((BPPAssetInstance*)_blastItem->getData())->visible = visible; + break; + case eLandmark: + ((BPPLandmark*)_blastItem->getData())->visible = visible; + break; + case eComposite: + ((BPPComposite*)_blastItem->getData())->visible = visible; + break; + default: + break; + } +} + +static BlastSceneTree* sBlastSceneTree = nullptr; +BlastSceneTree* BlastSceneTree::ins() +{ + return sBlastSceneTree; +} + +BlastSceneTree::BlastSceneTree(QWidget *parent) + : QDockWidget(parent) +{ + ui.setupUi(this); + _updateData = true; + sBlastSceneTree = this; + + ui.blastSceneTree->setStyleSheet("QTreeWidget::item{height:24px}"); + ui.blastSceneTree->setColumnWidth(0, 260); + ui.blastSceneTree->setColumnWidth(1, 20); + + ui.blastSceneTree->setContextMenuPolicy(Qt::CustomContextMenu); + + _treeChunkContextMenu = new QMenu(this); + _makeSupportAction = new QAction(tr("Make Support"), this); + _treeChunkContextMenu->addAction(_makeSupportAction); + connect(_makeSupportAction, SIGNAL(triggered()), this, SLOT(onMakeSupportMenuItemClicked())); + + _makeStaticSupportAction = new QAction(tr("Make Static Support"), this); + _treeChunkContextMenu->addAction(_makeStaticSupportAction); + connect(_makeStaticSupportAction, SIGNAL(triggered()), this, SLOT(onMakeStaticSupportMenuItemClicked())); + + _removeSupportAction = new QAction(tr("Remove Support"), this); + _treeChunkContextMenu->addAction(_removeSupportAction); + connect(_removeSupportAction, SIGNAL(triggered()), this, SLOT(onRemoveSupportMenuItemClicked())); + + _treeBondContextMenu = new QMenu(this); + _bondChunksAction = new QAction(tr("Bond Chunks"), this); + _treeBondContextMenu->addAction(_bondChunksAction); + connect(_bondChunksAction, SIGNAL(triggered()), this, SLOT(onBondChunksMenuItemClicked())); + + _bondChunksWithJointsAction = new QAction(tr("Bond Chunks With Joints"), this); + _treeBondContextMenu->addAction(_bondChunksWithJointsAction); + connect(_bondChunksWithJointsAction, SIGNAL(triggered()), this, SLOT(onBondChunksWithJointsMenuItemClicked())); + + _removeAllBondsAction = new QAction(tr("Remove All Bonds"), this); + _treeBondContextMenu->addAction(_removeAllBondsAction); + connect(_removeAllBondsAction, SIGNAL(triggered()), this, SLOT(onRemoveAllBondsMenuItemClicked())); +} + +BlastSceneTree::~BlastSceneTree() +{ + +} + +void BlastSceneTree::updateValues(bool updataData) +{ + if (updataData) + { + BlastTreeData::ins().update(); + } + + _updateTreeUIs(); +} + +void BlastSceneTree::dataSelected(std::vector<BlastNode*> selections) +{ + for (size_t i = 0; i < selections.size(); ++i) + { + _selectTreeItem(selections[i]); + } +} + +void BlastSceneTree::addObserver(ISceneObserver* observer) +{ + std::vector<ISceneObserver*>::iterator itr = std::find(_observers.begin(), _observers.end(), observer); + if (itr == _observers.end()) + { + _observers.push_back(observer); + } +} + +void BlastSceneTree::removeObserver(ISceneObserver* observer) +{ + std::vector<ISceneObserver*>::iterator itr = std::find(_observers.begin(), _observers.end(), observer); + _observers.erase(itr); +} + +void BlastSceneTree::updateVisible(uint32_t assetIndex, uint32_t chunkIndex, bool visible) +{ + BlastTreeData::ins().updateVisible(assetIndex, chunkIndex, visible); +} + +void BlastSceneTree::updateChunkItemSelection() +{ + _updateData = false; + + ui.blastSceneTree->clearSelection(); + BlastTreeData& treeData = BlastTreeData::ins(); + std::vector<BlastChunkNode*> chunkNodes; + + std::map<BlastAsset*, std::vector<uint32_t>> selectedChunks = SampleManager::ins()->getSelectedChunks(); + std::map<BlastAsset*, std::vector<uint32_t>>::iterator itrAssetSelectedChunks = selectedChunks.begin(); + for (; itrAssetSelectedChunks != selectedChunks.end(); ++itrAssetSelectedChunks) + { + std::vector<BlastChunkNode*> aseetNodes = treeData.getChunkNodeByBlastChunk(itrAssetSelectedChunks->first, itrAssetSelectedChunks->second); + chunkNodes.insert(chunkNodes.end(), aseetNodes.begin(), aseetNodes.end()); + } + + for (BlastChunkNode* node : chunkNodes) + { + _selectTreeItem(node); + } + + _updateData = true; +} + +void BlastSceneTree::makeSupport() +{ + std::vector<BlastChunkNode*> selectedChunkNodes; + QList<QTreeWidgetItem*> selectedItems = ui.blastSceneTree->selectedItems(); + for (int i = 0; i < selectedItems.size(); ++i) + { + QMap<QTreeWidgetItem*, BlastNode*>::iterator itr = _treeItemDataMap.find(selectedItems.at(i)); + + if (eChunk == itr.value()->getType()) + { + selectedChunkNodes.push_back((BlastChunkNode*)itr.value()); + } + } + + std::vector<BlastChunkNode*> topChunkNodes = BlastTreeData::getTopChunkNodes(selectedChunkNodes); + for (size_t i = 0; i < topChunkNodes.size(); ++i) + { + BlastChunkNode* chunkNode = topChunkNodes[i]; + BlastTreeData::makeSupport(chunkNode); + } + + _updateChunkTreeItems(); +} + +void BlastSceneTree::makeStaticSupport() +{ + std::vector<BlastChunkNode*> selectedChunkNodes; + QList<QTreeWidgetItem*> selectedItems = ui.blastSceneTree->selectedItems(); + for (int i = 0; i < selectedItems.size(); ++i) + { + QMap<QTreeWidgetItem*, BlastNode*>::iterator itr = _treeItemDataMap.find(selectedItems.at(i)); + + if (eChunk == itr.value()->getType()) + { + selectedChunkNodes.push_back((BlastChunkNode*)itr.value()); + } + } + + std::vector<BlastChunkNode*> topChunkNodes = BlastTreeData::getTopChunkNodes(selectedChunkNodes); + for (size_t i = 0; i < topChunkNodes.size(); ++i) + { + BlastChunkNode* chunkNode = topChunkNodes[i]; + BlastTreeData::makeStaticSupport(chunkNode); + } + + _updateChunkTreeItems(); +} + +void BlastSceneTree::removeSupport() +{ + std::vector<BlastChunkNode*> selectedChunkNodes; + QList<QTreeWidgetItem*> selectedItems = ui.blastSceneTree->selectedItems(); + for (int i = 0; i < selectedItems.size(); ++i) + { + QMap<QTreeWidgetItem*, BlastNode*>::iterator itr = _treeItemDataMap.find(selectedItems.at(i)); + + if (eChunk == itr.value()->getType()) + { + selectedChunkNodes.push_back((BlastChunkNode*)itr.value()); + } + } + + std::vector<BlastChunkNode*> topChunkNodes = BlastTreeData::getTopChunkNodes(selectedChunkNodes); + for (size_t i = 0; i < topChunkNodes.size(); ++i) + { + BlastChunkNode* chunkNode = topChunkNodes[i]; + BlastTreeData::removeSupport(chunkNode); + } + + _updateChunkTreeItems(); +} + +void BlastSceneTree::bondChunks() +{ + +} + +void BlastSceneTree::bondChunksWithJoints() +{ + +} + +void BlastSceneTree::removeAllBonds() +{ + +} + +void BlastSceneTree::on_btnAsset_clicked() +{ + QMessageBox::information(NULL, "test", "on_btnAsset_clicked"); +} + +void BlastSceneTree::on_assetComposite_clicked() +{ + QMessageBox::information(NULL, "test", "on_assetComposite_clicked"); +} + +void BlastSceneTree::on_btnChunk_clicked() +{ + QMessageBox::information(NULL, "test", "on_btnChunk_clicked"); +} + +void BlastSceneTree::on_btnBond_clicked() +{ + QMessageBox::information(NULL, "test", "on_btnBond_clicked"); +} + +void BlastSceneTree::on_btnProjectile_clicked() +{ + QMessageBox::information(NULL, "test", "on_btnProjectile_clicked"); +} + +void BlastSceneTree::on_blastSceneTree_customContextMenuRequested(const QPoint &pos) +{ + QList<QTreeWidgetItem*> items = ui.blastSceneTree->selectedItems(); + + if (items.count() == 1) + { + QTreeWidgetItem* curItem = items.at(0); + + QMap<QTreeWidgetItem*, BlastNode*>::iterator itr = _treeItemDataMap.find(curItem); + if (itr != _treeItemDataMap.end()) + { + if (eChunk == itr.value()->getType() || eBond == itr.value()->getType()) + { + _treeChunkContextMenu->exec(QCursor::pos()); + } + } + } + else if (items.count() > 1) + { + bool allSupportChunk = true; + for (int i = 0; i < items.count(); ++i) + { + QMap<QTreeWidgetItem*, BlastNode*>::iterator itr = _treeItemDataMap.find(items.at(i)); + if (itr != _treeItemDataMap.end()) + { + if (eChunk != itr.value()->getType()) + { + allSupportChunk = false; + break; + } + } + } + + if (allSupportChunk) + { + _treeBondContextMenu->exec(QCursor::pos()); + } + } + +} + +void BlastSceneTree::on_blastSceneTree_itemSelectionChanged() +{ + if (!_updateData) + return; + + SampleManager::ins()->clearChunksSelected(); + + QList<QTreeWidgetItem*> selectedItems = ui.blastSceneTree->selectedItems(); + std::vector<BlastNode*> nodes; + for (int i = 0; i < selectedItems.count(); ++i) + { + QMap<QTreeWidgetItem*, BlastNode*>::iterator itr = _treeItemDataMap.find(selectedItems.at(i)); + if (itr != _treeItemDataMap.end()) + { + nodes.push_back(itr.value()); + + BlastNode* node = itr.value(); + if (eChunk == node->getType()) + { + ((BlastChunkNode*)node)->setSelected(true); + } + else if (eAssetInstance == node->getType()) + { + ((BlastAssetInstanceNode*)node)->setSelected(true); + } + } + } + + for (size_t i = 0; i < _observers.size(); ++i) + { + _observers[i]->dataSelected(nodes); + } +} + +void BlastSceneTree::onMakeSupportMenuItemClicked() +{ + makeSupport(); +} + +void BlastSceneTree::onMakeStaticSupportMenuItemClicked() +{ + makeStaticSupport(); +} + +void BlastSceneTree::onRemoveSupportMenuItemClicked() +{ + removeSupport(); +} + +void BlastSceneTree::onBondChunksMenuItemClicked() +{ + bondChunks(); +} + +void BlastSceneTree::onBondChunksWithJointsMenuItemClicked() +{ + bondChunksWithJoints(); +} + +void BlastSceneTree::onRemoveAllBondsMenuItemClicked() +{ + removeAllBonds(); +} + +void BlastSceneTree::_updateTreeUIs() +{ + ui.blastSceneTree->clear(); + _treeItemDataMap.clear(); + _treeDataItemMap.clear(); + + BlastCompositeNode* compositeNode = BlastTreeData::ins().getCompsiteNode(); + if (compositeNode != nullptr) + { + QTreeWidgetItem* compositeTreeWidgetItem = new QTreeWidgetItem(ui.blastSceneTree); + compositeTreeWidgetItem->setText(0, compositeNode->name.c_str()); + compositeTreeWidgetItem->setIcon(0, QIcon(":/AppMainWindow/images/AssetComposite.png")); + VisualButton* btn = new VisualButton(this, compositeNode); + ui.blastSceneTree->setItemWidget(compositeTreeWidgetItem, 1, btn); + _treeItemDataMap.insert(compositeTreeWidgetItem, compositeNode); + _treeDataItemMap.insert(compositeNode, compositeTreeWidgetItem); + + size_t count = compositeNode->children.size(); + for (size_t i = 0; i < count; ++i) + { + BlastNode* assetInstanceNode = compositeNode->children[i]; + QTreeWidgetItem* assetInstanceWidgetItem = new QTreeWidgetItem(compositeTreeWidgetItem); + assetInstanceWidgetItem->setText(0, assetInstanceNode->name.c_str()); + if (assetInstanceNode->getType() == eAssetInstance) + assetInstanceWidgetItem->setIcon(0, QIcon(":/AppMainWindow/images/Asset.png")); + VisualButton* btn = new VisualButton(this, assetInstanceNode); + ui.blastSceneTree->setItemWidget(assetInstanceWidgetItem, 1, btn); + _treeItemDataMap.insert(assetInstanceWidgetItem, assetInstanceNode); + _treeDataItemMap.insert(assetInstanceNode, assetInstanceWidgetItem); + } + } + + std::vector<BlastAssetNode*>& assets = BlastTreeData::ins().getAssetNodes(); + size_t count = assets.size(); + for (size_t i = 0; i < count; ++i) + { + BlastAssetNode* assetNode = assets[i]; + + QTreeWidgetItem* assetTreeWidgetItem = new QTreeWidgetItem(ui.blastSceneTree); + assetTreeWidgetItem->setText(0, assetNode->name.c_str()); + assetTreeWidgetItem->setIcon(0, QIcon(":/AppMainWindow/images/Asset.png")); + VisualButton* btn = new VisualButton(this, assetNode); + ui.blastSceneTree->setItemWidget(assetTreeWidgetItem, 1, btn); + _treeItemDataMap.insert(assetTreeWidgetItem, assetNode); + _treeDataItemMap.insert(assetNode, assetTreeWidgetItem); + + _addChunkUI(assetNode, assetTreeWidgetItem); + } + + std::vector<BlastProjectileNode*>& projectiles = BlastTreeData::ins().getProjectileNodes(); + count = projectiles.size(); + for (int i = 0; i < count; ++i) + { + BlastProjectileNode* projectileNode = projectiles[i]; + + QTreeWidgetItem* projectileTreeWidgetItem = new QTreeWidgetItem(ui.blastSceneTree); + projectileTreeWidgetItem->setText(0, projectileNode->name.c_str()); + projectileTreeWidgetItem->setIcon(0, QIcon(":/AppMainWindow/images/Projectile.png")); + VisualButton* btn = new VisualButton(this, projectileNode); + ui.blastSceneTree->setItemWidget(projectileTreeWidgetItem, 1, btn); + _treeItemDataMap.insert(projectileTreeWidgetItem, projectileNode); + _treeDataItemMap.insert(projectileNode, projectileTreeWidgetItem); + } + + std::vector<BlastGraphicsMeshNode*>& graphicsMeshes = BlastTreeData::ins().getGraphicsMeshNodes(); + count = graphicsMeshes.size(); + for (int i = 0; i < count; ++i) + { + BlastGraphicsMeshNode* graphicsMesheNode = graphicsMeshes[i]; + + QTreeWidgetItem* graphicsMesheTreeWidgetItem = new QTreeWidgetItem(ui.blastSceneTree); + graphicsMesheTreeWidgetItem->setText(0, graphicsMesheNode->name.c_str()); + VisualButton* btn = new VisualButton(this, graphicsMesheNode); + ui.blastSceneTree->setItemWidget(graphicsMesheTreeWidgetItem, 1, btn); + _treeItemDataMap.insert(graphicsMesheTreeWidgetItem, graphicsMesheNode); + _treeDataItemMap.insert(graphicsMesheNode, graphicsMesheTreeWidgetItem); + } + + //for (int j = 0; j < ui.blastSceneTree->topLevelItemCount(); ++j) + //{ + // QTreeWidgetItem* topLevelItem = ui.blastSceneTree->topLevelItem(j); + // ui.blastSceneTree->expandItem(topLevelItem); + //} + ui.blastSceneTree->expandAll(); +} + +void BlastSceneTree::_addChunkUI(const BlastNode* parentNode, QTreeWidgetItem* parentTreeItem) +{ + if (parentNode != nullptr && parentTreeItem != nullptr) + { + for (size_t i = 0; i < parentNode->children.size(); ++i) + { + BlastNode* node = parentNode->children[i]; + if (node == nullptr) + continue; + + QTreeWidgetItem* treeWidgetItem = nullptr; + + if (node->getType() == eChunk) + { + BlastChunkNode* chunk = static_cast<BlastChunkNode*>(node); + treeWidgetItem = new QTreeWidgetItem(parentTreeItem); + treeWidgetItem->setText(0, chunk->name.c_str()); + if (chunk->isSupport()) + { + treeWidgetItem->setIcon(0, QIcon(":/AppMainWindow/images/Chunk_Support_Unstatic.png")); + } + else + { + treeWidgetItem->setIcon(0, QIcon(":/AppMainWindow/images/Chunk_Unsupport_Unstatic.png")); + } + + _addChunkUI(chunk, treeWidgetItem); + } + else if (node->getType() == eBond) + { + BlastBondNode* bond = static_cast<BlastBondNode*>(node); + treeWidgetItem = new QTreeWidgetItem(parentTreeItem); + treeWidgetItem->setIcon(0, QIcon(":/AppMainWindow/images/Bond.png")); + treeWidgetItem->setText(0, bond->name.c_str()); + } + + if (treeWidgetItem == nullptr) + continue; + VisualButton* btn = new VisualButton(this, node); + ui.blastSceneTree->setItemWidget(treeWidgetItem, 1, btn); + _treeItemDataMap.insert(treeWidgetItem, node); + _treeDataItemMap.insert(node, treeWidgetItem); + } + } +} + +void BlastSceneTree::_updateChunkTreeItemAndMenu(BPPChunk* chunk, QTreeWidgetItem* chunkItem) +{ + assert(chunk != nullptr); + + _removeSupportAction->setEnabled(true); + _makeSupportAction->setEnabled(true); + _makeStaticSupportAction->setEnabled(true); + + if (!chunk->support && !chunk->staticFlag) + { + _removeSupportAction->setEnabled(false); + chunkItem->setIcon(0, QIcon(":/AppMainWindow/images/Chunk_Unsupport_Unstatic.png")); + } + else if (chunk->support && !chunk->staticFlag) + { + _makeSupportAction->setEnabled(false); + chunkItem->setIcon(0, QIcon(":/AppMainWindow/images/Chunk_Support_Unstatic.png")); + } + else if (chunk->support && chunk->staticFlag) + { + _makeStaticSupportAction->setEnabled(false); + chunkItem->setIcon(0, QIcon(":/AppMainWindow/images/Chunk_Support_Static.png")); + } +} + +void BlastSceneTree::_updateChunkTreeItems() +{ + for (QMap<BlastNode*, QTreeWidgetItem*>::iterator itr = _treeDataItemMap.begin(); itr != _treeDataItemMap.end(); ++itr) + { + BlastNode* node = itr.key(); + QTreeWidgetItem* treeItem = itr.value(); + if (eChunk == node->getType()) + { + BPPChunk* chunk = static_cast<BPPChunk*>(node->getData()); + if (!chunk->support && !chunk->staticFlag) + { + treeItem->setIcon(0, QIcon(":/AppMainWindow/images/Chunk_Unsupport_Unstatic.png")); + } + else if (chunk->support && !chunk->staticFlag) + { + treeItem->setIcon(0, QIcon(":/AppMainWindow/images/Chunk_Support_Unstatic.png")); + } + else if (chunk->support && chunk->staticFlag) + { + treeItem->setIcon(0, QIcon(":/AppMainWindow/images/Chunk_Support_Static.png")); + } + } + } +} + +void BlastSceneTree::_selectTreeItem(BlastNode* node) +{ + QMap<BlastNode*, QTreeWidgetItem*>::iterator itr = _treeDataItemMap.find(node); + if (itr != _treeDataItemMap.end()) + { + ui.blastSceneTree->setItemSelected(itr.value(), true); + } +} + +//void BlastSceneTree::_createTestData() +//{ +// BPPBlast& blast = BlastProject::ins().getParams().blast; +// +// // compoistie +// { +// BPPComposite& composite = blast.composite; +// composite.composite.buf = nullptr; +// composite.visible = true; +// +// copy(composite.composite, "BlastComposite"); +// +// // asset instance array +// { +// BPPAssetInstanceArray& instanceArray = composite.blastAssetInstances; +// instanceArray.buf = new BPPAssetInstance[4]; +// instanceArray.arraySizes[0] = 4; +// instanceArray.buf[0].name.buf = nullptr; +// instanceArray.buf[1].name.buf = nullptr; +// instanceArray.buf[2].name.buf = nullptr; +// instanceArray.buf[3].name.buf = nullptr; +// instanceArray.buf[0].source.buf = nullptr; +// instanceArray.buf[1].source.buf = nullptr; +// instanceArray.buf[2].source.buf = nullptr; +// instanceArray.buf[3].source.buf = nullptr; +// +// copy(instanceArray.buf[0].name, "BlastAsset_instance1"); +// instanceArray.buf[0].visible = true; +// +// copy(instanceArray.buf[1].name, "BlastAsset_instance2"); +// instanceArray.buf[1].visible = true; +// +// copy(instanceArray.buf[2].name, "BlastAsset1_instance1"); +// instanceArray.buf[2].visible = true; +// +// copy(instanceArray.buf[3].name, "BlastAsset1_instance2"); +// instanceArray.buf[3].visible = true; +// } +// +// // landmark array +// { +// BPPLandmarkArray& landmarkArray = composite.landmarks; +// landmarkArray.buf = new BPPLandmark[2]; +// landmarkArray.arraySizes[0] = 2; +// landmarkArray.buf[0].name.buf = nullptr; +// landmarkArray.buf[1].name.buf = nullptr; +// +// copy(landmarkArray.buf[0].name, "Landmark_1"); +// copy(landmarkArray.buf[1].name, "Landmark_2"); +// } +// } +// +// // asset array +// { +// BPPAssetArray& assetArray = blast.blastAssets; +// assetArray.buf = new BPPAsset[2]; +// assetArray.arraySizes[0] = 2; +// +// // asset 0 +// { +// BPPAsset& asset = assetArray.buf[0]; +// asset.path.buf = nullptr; +// asset.activePreset.buf = nullptr; +// asset.bonds.buf = nullptr; +// asset.chunks.buf = nullptr; +// +// copy(asset.path, "c:/temp/BlastAsset.asset"); +// +// // chunks +// { +// asset.chunks.buf = new BPPChunk[10]; +// asset.chunks.arraySizes[0] = 10; +// for (int i = 0; i < 10; ++i) +// { +// asset.chunks.buf[i].name.buf = nullptr; +// asset.chunks.buf[i].visible = true; +// asset.chunks.buf[i].staticFlag = false; +// } +// +// copy(asset.chunks.buf[0].name, "Chunk_L0_00"); +// asset.chunks.buf[0].ID = 0; +// asset.chunks.buf[0].parentID = -1; +// asset.chunks.buf[0].support = false; +// +// copy(asset.chunks.buf[1].name, "Chunk_L0_01"); +// asset.chunks.buf[1].ID = 1; +// asset.chunks.buf[1].parentID = -1; +// asset.chunks.buf[1].support = false; +// +// copy(asset.chunks.buf[2].name, "Chunk_L1_02"); +// asset.chunks.buf[2].ID = 2; +// asset.chunks.buf[2].parentID = 0; +// asset.chunks.buf[2].support = false; +// +// copy(asset.chunks.buf[3].name, "Chunk_L1_03"); +// asset.chunks.buf[3].ID = 3; +// asset.chunks.buf[3].parentID = 0; +// asset.chunks.buf[3].support = false; +// +// copy(asset.chunks.buf[4].name, "Chunk_L1_04"); +// asset.chunks.buf[4].ID = 4; +// asset.chunks.buf[4].parentID = 1; +// asset.chunks.buf[4].support = false; +// +// copy(asset.chunks.buf[5].name, "Chunk_L1_05"); +// asset.chunks.buf[5].ID = 5; +// asset.chunks.buf[5].parentID = 1; +// asset.chunks.buf[5].support = false; +// +// copy(asset.chunks.buf[6].name, "Chunk_L2_06"); +// asset.chunks.buf[6].ID = 6; +// asset.chunks.buf[6].parentID = 2; +// asset.chunks.buf[6].support = true; +// +// copy(asset.chunks.buf[7].name, "Chunk_L2_07"); +// asset.chunks.buf[7].ID = 7; +// asset.chunks.buf[7].parentID = 2; +// asset.chunks.buf[7].support = true; +// +// copy(asset.chunks.buf[8].name, "Chunk_L2_08"); +// asset.chunks.buf[8].ID = 8; +// asset.chunks.buf[8].parentID = 3; +// asset.chunks.buf[8].support = true; +// +// copy(asset.chunks.buf[9].name, "Chunk_L2_09"); +// asset.chunks.buf[9].ID = 9; +// asset.chunks.buf[9].parentID = 3; +// asset.chunks.buf[9].support = true; +// } +// +// // bonds +// { +// asset.bonds.buf = new BPPBond[4]; +// asset.bonds.arraySizes[0] = 4; +// for (int i = 0; i < 4; ++i) +// { +// asset.bonds.buf[i].name.buf = nullptr; +// asset.bonds.buf[i].visible = true; +// asset.bonds.buf[i].support.healthMask.buf = nullptr; +// } +// +// copy(asset.bonds.buf[0].name, "Chunk_L2_08"); +// asset.bonds.buf[0].fromChunk = 6; +// asset.bonds.buf[0].toChunk = 8; +// +// copy(asset.bonds.buf[1].name, "Chunk_L2_06"); +// asset.bonds.buf[1].fromChunk = 6; +// asset.bonds.buf[1].toChunk = 8; +// +// copy(asset.bonds.buf[2].name, "Chunk_L2_09"); +// asset.bonds.buf[2].fromChunk = 7; +// asset.bonds.buf[2].toChunk = 9; +// +// copy(asset.bonds.buf[3].name, "Chunk_L2_07"); +// asset.bonds.buf[3].fromChunk = 7; +// asset.bonds.buf[3].toChunk = 9; +// } +// } +// +// // asset 1 +// { +// BPPAsset& asset = assetArray.buf[1]; +// asset.path.buf = nullptr; +// asset.activePreset.buf = nullptr; +// asset.bonds.buf = nullptr; +// asset.chunks.buf = nullptr; +// +// copy(asset.path, "c:/temp/BlastAsset1.asset"); +// { +// asset.chunks.buf = new BPPChunk[10]; +// asset.chunks.arraySizes[0] = 10; +// for (int i = 0; i < 10; ++i) +// { +// asset.chunks.buf[i].name.buf = nullptr; +// asset.chunks.buf[i].visible = true; +// } +// +// copy(asset.chunks.buf[0].name, "Chunk_L0_00"); +// asset.chunks.buf[0].ID = 0; +// asset.chunks.buf[0].parentID = -1; +// asset.chunks.buf[0].support = false; +// +// copy(asset.chunks.buf[1].name, "Chunk_L0_01"); +// asset.chunks.buf[1].ID = 1; +// asset.chunks.buf[1].parentID = -1; +// asset.chunks.buf[1].support = false; +// +// copy(asset.chunks.buf[2].name, "Chunk_L1_02"); +// asset.chunks.buf[2].ID = 2; +// asset.chunks.buf[2].parentID = 0; +// asset.chunks.buf[2].support = false; +// +// copy(asset.chunks.buf[3].name, "Chunk_L1_03"); +// asset.chunks.buf[3].ID = 3; +// asset.chunks.buf[3].parentID = 0; +// asset.chunks.buf[3].support = false; +// +// copy(asset.chunks.buf[4].name, "Chunk_L1_04"); +// asset.chunks.buf[4].ID = 4; +// asset.chunks.buf[4].parentID = 1; +// asset.chunks.buf[4].support = false; +// +// copy(asset.chunks.buf[5].name, "Chunk_L1_05"); +// asset.chunks.buf[5].ID = 5; +// asset.chunks.buf[5].parentID = 1; +// asset.chunks.buf[5].support = false; +// +// copy(asset.chunks.buf[6].name, "Chunk_L2_06"); +// asset.chunks.buf[6].ID = 6; +// asset.chunks.buf[6].parentID = 2; +// asset.chunks.buf[6].support = true; +// +// copy(asset.chunks.buf[7].name, "Chunk_L2_07"); +// asset.chunks.buf[7].ID = 7; +// asset.chunks.buf[7].parentID = 2; +// asset.chunks.buf[7].support = true; +// +// copy(asset.chunks.buf[8].name, "Chunk_L2_08"); +// asset.chunks.buf[8].ID = 8; +// asset.chunks.buf[8].parentID = 3; +// asset.chunks.buf[8].support = true; +// +// copy(asset.chunks.buf[9].name, "Chunk_L2_09"); +// asset.chunks.buf[9].ID = 9; +// asset.chunks.buf[9].parentID = 3; +// asset.chunks.buf[9].support = true; +// } +// } +// } +// +// // projectile +// { +// BPPProjectileArray& projectileArray = blast.projectiles; +// projectileArray.buf = new BPPProjectile[1]; +// projectileArray.arraySizes[0] = 1; +// projectileArray.buf[0].name.buf = nullptr; +// copy(projectileArray.buf[0].name, "Projectile"); +// projectileArray.buf[0].visible = true; +// } +// +// // graphics meshes +// { +// BPPGraphicsMeshArray& graphicsMeshArray = blast.graphicsMeshes; +// graphicsMeshArray.buf = new BPPGraphicsMesh[3]; +// graphicsMeshArray.arraySizes[0] = 3; +// graphicsMeshArray.buf[0].name.buf = nullptr; +// copy(graphicsMeshArray.buf[0].name, "SurfaceMesh1"); +// graphicsMeshArray.buf[0].visible = true; +// +// graphicsMeshArray.buf[1].name.buf = nullptr; +// copy(graphicsMeshArray.buf[1].name, "SurfaceMesh2"); +// graphicsMeshArray.buf[1].visible = true; +// +// graphicsMeshArray.buf[2].name.buf = nullptr; +// copy(graphicsMeshArray.buf[2].name, "DisplayMesh1"); +// graphicsMeshArray.buf[2].visible = true; +// } +//} |