aboutsummaryrefslogtreecommitdiff
path: root/tools/ArtistTools/source/BlastPlugin/SampleBase/scene/SceneController.cpp
diff options
context:
space:
mode:
authorBryan Galdrikian <[email protected]>2017-02-24 09:32:20 -0800
committerBryan Galdrikian <[email protected]>2017-02-24 09:32:20 -0800
commite1bf674c16e3c8472b29574159c789cd3f0c64e0 (patch)
tree9f0cfce09c71a2c27ff19589fcad6cd83504477c /tools/ArtistTools/source/BlastPlugin/SampleBase/scene/SceneController.cpp
parentfirst commit (diff)
downloadblast-e1bf674c16e3c8472b29574159c789cd3f0c64e0.tar.xz
blast-e1bf674c16e3c8472b29574159c789cd3f0c64e0.zip
Updating to [email protected] and [email protected] with a new directory structure.
NvBlast folder is gone, files have been moved to top level directory. README is changed to reflect this.
Diffstat (limited to 'tools/ArtistTools/source/BlastPlugin/SampleBase/scene/SceneController.cpp')
-rw-r--r--tools/ArtistTools/source/BlastPlugin/SampleBase/scene/SceneController.cpp1509
1 files changed, 1509 insertions, 0 deletions
diff --git a/tools/ArtistTools/source/BlastPlugin/SampleBase/scene/SceneController.cpp b/tools/ArtistTools/source/BlastPlugin/SampleBase/scene/SceneController.cpp
new file mode 100644
index 0000000..ec000b3
--- /dev/null
+++ b/tools/ArtistTools/source/BlastPlugin/SampleBase/scene/SceneController.cpp
@@ -0,0 +1,1509 @@
+/*
+* Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+*
+* NVIDIA CORPORATION and its licensors retain all intellectual property
+* and proprietary rights in and to this software, related documentation
+* and any modifications thereto. Any use, reproduction, disclosure or
+* distribution of this software and related documentation without an express
+* license agreement from NVIDIA CORPORATION is strictly prohibited.
+*/
+
+#include "SceneController.h"
+#include "RenderUtils.h"
+#include "Utils.h"
+
+#include "BlastAssetBoxes.h"
+#include "BlastAssetModelSimple.h"
+#include "BlastAssetModelSkinned.h"
+#include "NvBlastExtPxAsset.h"
+#include "NvBlastExtPxFamily.h"
+#include "NvBlastExtPxManager.h"
+
+#include "SampleAssetListParser.h"
+#include "BlastReplay.h"
+#include "Renderer.h"
+
+#include "BlastController.h"
+#include "CommonUIController.h"
+#include "PhysXController.h"
+
+#include "PxRigidDynamic.h"
+#include <PsFastXml.h>
+#include "PxInputDataFromPxFileBuf.h"
+
+#include <algorithm>
+#include <imgui.h>
+#include <sstream>
+#include <tuple>
+
+
+
+//////// Simple hash function ////////
+static NvBlastID generateIDFromString(const char* str)
+{
+ uint32_t h[4] = { 5381, 5381, 5381, 5381 };
+ int i = 0;
+ for (const char* ptr = str; *ptr; i = ((i + 1) & 3), ++ptr)
+ {
+ h[i] = ((h[i] << 5) + h[i]) ^ static_cast<uint32_t>(*ptr);
+ }
+ return *reinterpret_cast<NvBlastID*>(h);
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Scenes Setup
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+const DirectX::XMFLOAT4 PICK_POINTER_ACTIVE_COLOR(1.0f, 0.f, 0.f, 0.6f);
+const float RIGIDBODY_DENSITY = 2000.0f;
+
+
+class SingleSceneAsset;
+
+class SceneAsset
+{
+public:
+ SceneAsset() : spawnCount(0) {}
+ virtual ~SceneAsset() {}
+
+ void initialize(Scene* scene)
+ {
+ m_scene = scene;
+ }
+
+ virtual const char* getID() const = 0;
+ virtual const char* getName() const = 0;
+
+ virtual void load() = 0;
+ virtual void unload() = 0;
+ virtual bool isLoaded() const = 0;
+ virtual void spawn(PxVec3 shift) = 0;
+
+ virtual ImVec4 getUIColor() const
+ {
+ return ImGui::GetStyle().Colors[ImGuiCol_Text];
+ }
+
+ uint32_t spawnCount;
+protected:
+ Scene* m_scene;
+};
+
+
+class SceneActor
+{
+public:
+ virtual ~SceneActor() {}
+ virtual const char* getName() const = 0;
+ virtual const char* getSubname(int subindex) const { return nullptr; }
+ virtual ImVec4 getUIColor() const = 0;
+ virtual void drawUI(int subindex) {}
+ virtual void drawStatsUI(int subindex) {}
+ virtual uint32_t getSubactorCount() const { return 0; }
+ virtual PxVec3 getSpawnShift() const { return PxVec3(PxZero); }
+ virtual void reload() {}
+ virtual void removeSubactor(int subindex) {}
+};
+
+
+class Scene
+{
+public:
+ struct ActorIndex
+ {
+ int index;
+ int subindex;
+
+ ActorIndex() { reset(); }
+ ActorIndex(int i, int s) : index(i), subindex(s) {}
+
+ bool operator==(const ActorIndex& other) const
+ {
+ return index == other.index && subindex == other.subindex;
+ }
+
+ void reset()
+ {
+ index = -1;
+ subindex = -1;
+ }
+ };
+
+ Scene(Renderer& renderer, PhysXController& physXController, BlastController& blastController, CommonUIController& commonUIController) :
+ m_renderer(renderer), m_physXController(physXController), m_blastController(blastController), m_commonUIController(commonUIController)
+ {
+ }
+
+ ~Scene()
+ {
+ removeAllSceneActors();
+
+ for (uint32_t i = 0; i < m_assets.size(); i++)
+ {
+ SAFE_DELETE(m_assets[i]);
+ }
+ m_assets.clear();
+ m_assetsByID.clear();
+ m_tkAssetMap.clear();
+ }
+
+ void addAsset(SceneAsset* asset)
+ {
+ m_assets.push_back(asset);
+ asset->initialize(this);
+ m_assetsByID[asset->getID()] = asset;
+ }
+
+// Add By Lixu Begin
+ std::vector<SceneAsset*>& getAssets()
+ {
+ return m_assets;
+ }
+
+ std::vector<SceneActor*>& getActors()
+ {
+ return m_sceneActors;
+ }
+// Add By Lixu End
+
+ void drawUI()
+ {
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // Assets Selection
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ {
+ static int mode = 0;
+ ImGui::RadioButton("Replace", &mode, 0); ImGui::SameLine();
+ ImGui::RadioButton("Append", &mode, 1);
+
+ ImGui::ListBoxHeader("Assets", (int)m_assets.size());
+ for (uint32_t i = 0; i < m_assets.size(); ++i)
+ {
+ ImVec4 color = m_assets[i]->getUIColor();
+ color.w = color.w * (m_assets[i]->isLoaded() ? 1.0f : 0.5f);
+ ImGui::PushStyleColor(ImGuiCol_Text, color);
+ if (ImGui::Selectable(m_assets[i]->getName(), m_lastSpawnedAsset == i))
+ {
+ m_lastSpawnedAsset = i;
+ if (mode == 0)
+ {
+ removeAllSceneActors();
+ }
+ m_commonUIController.addDelayedCall([=]() { spawnAsset(m_lastSpawnedAsset); }, "Loading Asset");
+ }
+ ImGui::PopStyleColor();
+ }
+ ImGui::ListBoxFooter();
+ }
+
+ ImGui::Spacing();
+ ImGui::Separator();
+
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // Actors Selection
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ {
+ // actor's list
+ {
+ int itemCount = 0;
+ for (size_t i = 0; i < m_sceneActors.size(); ++i)
+ {
+ itemCount += 1 + m_sceneActors[i]->getSubactorCount();
+ }
+
+ ImGui::ListBoxHeader("Scene Actors", itemCount);
+ for (int i = 0; i < (int)m_sceneActors.size(); ++i)
+ {
+ ImVec4 color = m_sceneActors[i]->getUIColor();
+ ImGui::PushStyleColor(ImGuiCol_Text, color);
+
+ const bool isSelected = (m_selectedActor.index == i);
+
+ ImGui::PushID(i);
+ if (ImGui::Selectable(m_sceneActors[i]->getName(), isSelected && m_selectedActor.subindex == -1))
+ {
+ setSelectedActor(i);
+ }
+
+ for (int s = 0; s < (int)m_sceneActors[i]->getSubactorCount(); ++s)
+ {
+ ImGui::PushID(s);
+ if (ImGui::Selectable(m_sceneActors[i]->getSubname(s), isSelected && m_selectedActor.subindex == s))
+ {
+ setSelectedActor(i, s);
+ }
+ ImGui::PopID();
+ }
+
+ ImGui::PopID();
+ ImGui::PopStyleColor();
+ }
+ ImGui::ListBoxFooter();
+ }
+
+ SceneActor* selectedActor = getSelectedActor();
+ if (selectedActor)
+ {
+ if (ImGui::Button("Remove"))
+ {
+ removeSceneActor(m_selectedActor);
+ }
+
+ ImGui::SameLine();
+
+ if (ImGui::Button("Reload"))
+ {
+ selectedActor->reload();
+ }
+
+ ImGui::SameLine();
+ }
+
+ if (ImGui::Button("Remove All"))
+ {
+ removeAllSceneActors();
+ }
+ ImGui::SameLine();
+ if (ImGui::Button("Reload All (R)"))
+ {
+ reloadAllActors();
+ }
+ }
+
+ ImGui::Spacing();
+ ImGui::Spacing();
+
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // Selected Actor
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ {
+ SceneActor* selectedActor = getSelectedActor();
+ if (selectedActor)
+ {
+ ImGui::Text("Selected Actor: ");
+ ImGui::SameLine();
+ ImGui::PushStyleColor(ImGuiCol_Text, ImColor(40, 200, 80, 255));
+ ImGui::Text(m_selectedActor.subindex >= 0 ? selectedActor->getSubname(m_selectedActor.subindex) : selectedActor->getName());
+ ImGui::PopStyleColor();
+
+ ImGui::Spacing();
+
+ selectedActor->drawUI(m_selectedActor.subindex);
+ }
+ else
+ {
+ ImGui::Text("No Selected Actor");
+ }
+ }
+ }
+
+ void drawStatsUI()
+ {
+ SceneActor* selectedActor = getSelectedActor();
+ if (selectedActor)
+ {
+ selectedActor->drawStatsUI(m_selectedActor.subindex);
+ }
+ }
+
+ void spawnAsset(int32_t num)
+ {
+ m_lastSpawnedAsset = physx::PxClamp<int32_t>(num, -1, (uint32_t)m_assets.size() - 1);
+
+ if (m_lastSpawnedAsset < 0)
+ {
+ return;
+ }
+
+ PxVec3 shift(PxZero);
+// Add By Lixu Begin
+ /*
+ for (SceneActor* a : m_sceneActors)
+ {
+ shift += a->getSpawnShift();
+ }
+ */
+// Add By Lixu End
+
+ SceneAsset* asset = m_assets[m_lastSpawnedAsset];
+ asset->spawn(shift);
+ }
+
+ void addSceneActor(SceneActor* actor)
+ {
+ m_sceneActors.push_back(actor);
+ if (!getSelectedActor())
+ {
+ setSelectedActor((uint32_t)m_sceneActors.size() - 1);
+ }
+ }
+
+ void removeSceneActor(ActorIndex actorIndex)
+ {
+ SceneActor* actor = getActorByIndex(actorIndex.index);
+ if (actorIndex.subindex < 0)
+ {
+ delete actor;
+ m_sceneActors.erase(std::remove(m_sceneActors.begin(), m_sceneActors.end(), actor));
+ }
+ else
+ {
+ actor->removeSubactor(actorIndex.subindex);
+
+ if (actor->getSubactorCount() == 0)
+ {
+ removeSceneActor(ActorIndex(actorIndex.index, -1));
+ return;
+ }
+ }
+
+ SceneActor* selectedActor = getActorByIndex(m_selectedActor.index);
+ if (selectedActor == nullptr)
+ {
+ if (!m_sceneActors.empty())
+ {
+ setSelectedActor((uint32_t)m_sceneActors.size() - 1);
+ }
+ }
+ else
+ {
+ int subactorCount = selectedActor->getSubactorCount();
+ if (m_selectedActor.subindex >= subactorCount || (m_selectedActor.subindex < 0 && subactorCount > 0))
+ {
+ setSelectedActor(m_selectedActor.index, subactorCount - 1);
+ }
+ }
+ }
+
+ void removeAllSceneActors()
+ {
+ for (SceneActor* a : m_sceneActors)
+ {
+ delete a;
+ }
+ m_sceneActors.clear();
+ setSelectedActor(-1);
+ }
+
+ void setSelectedActor(int index, int subindex = -1)
+ {
+ m_selectedActor.index = physx::PxClamp<int32_t>(index, -1, (uint32_t)m_sceneActors.size() - 1);
+ m_selectedActor.subindex = subindex;
+ }
+
+ SceneActor* getSelectedActor() const
+ {
+ return getActorByIndex(m_selectedActor.index);
+ }
+
+ SceneActor* getActorByIndex(int index) const
+ {
+ return (index >= 0 && index < (int)m_sceneActors.size()) ? m_sceneActors[index] : nullptr;
+ }
+
+ int releaseAll()
+ {
+ removeAllSceneActors();
+
+ for (size_t i = 0; i < m_assets.size(); ++i)
+ {
+ m_assets[i]->unload();
+ }
+
+ const int currentAsset = m_lastSpawnedAsset;
+ m_lastSpawnedAsset = -1;
+ return currentAsset;
+ }
+
+ void reloadAllActors()
+ {
+ for (SceneActor* a : m_sceneActors)
+ {
+ a->reload();
+ }
+ }
+
+ void registerTkAsset(const TkAsset& tkAsset, SingleSceneAsset* asset)
+ {
+ m_tkAssetMap[&tkAsset] = asset;
+ }
+
+ void unregisterTkAsset(const TkAsset& tkAsset)
+ {
+ m_tkAssetMap.erase(&tkAsset);
+ }
+
+ SingleSceneAsset* findSingleSceneAsset(const TkAsset& tkAsset)
+ {
+ auto entry = m_tkAssetMap.find(&tkAsset);
+ return entry != m_tkAssetMap.end() ? entry->second : nullptr;
+ }
+
+ SceneAsset* findSceneAsset(const std::string& id)
+ {
+ auto entry = m_assetsByID.find(id);
+ return entry != m_assetsByID.end() ? entry->second : nullptr;
+ }
+
+
+ //////// used controllers ////////
+
+ Renderer& getRenderer() const
+ {
+ return m_renderer;
+ }
+
+ PhysXController& getPhysXController() const
+ {
+ return m_physXController;
+ }
+
+ BlastController& getBlastController() const
+ {
+ return m_blastController;
+ }
+
+ CommonUIController& getCommonUIController() const
+ {
+ return m_commonUIController;
+ }
+
+private:
+
+ Renderer& m_renderer;
+ PhysXController& m_physXController;
+ BlastController& m_blastController;
+ CommonUIController& m_commonUIController;
+
+ std::vector<SceneAsset*> m_assets;
+ std::vector<SceneActor*> m_sceneActors;
+ std::map<const TkAsset*, SingleSceneAsset*> m_tkAssetMap;
+ std::map<std::string, SceneAsset*> m_assetsByID;
+
+ int m_lastSpawnedAsset;
+
+ ActorIndex m_selectedActor;
+};
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Assets
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+class SingleSceneActor;
+
+class SingleSceneAsset : public SceneAsset
+{
+public:
+ SingleSceneAsset() : m_asset(nullptr) {}
+ virtual ~SingleSceneAsset() { unload(); }
+
+ virtual void spawn(PxVec3 shift) override;
+
+ virtual void load() override
+ {
+ if (!m_asset)
+ {
+ m_asset = createAsset();
+ m_scene->registerTkAsset(m_asset->getPxAsset()->getTkAsset(), this);
+ }
+ }
+
+ virtual void unload() override
+ {
+ if (m_asset)
+ {
+ m_scene->unregisterTkAsset(m_asset->getPxAsset()->getTkAsset());
+ delete m_asset;
+ m_asset = nullptr;
+ }
+ }
+
+ virtual bool isLoaded() const override
+ {
+ return m_asset != nullptr;
+ }
+
+ BlastAsset* getAsset() const
+ {
+ return m_asset;
+ }
+
+ virtual PxTransform getInitialTransform() = 0;
+
+protected:
+ virtual BlastAsset* createAsset() = 0;
+
+private:
+ BlastAsset* m_asset;
+};
+
+
+class ModelSceneAsset : public SingleSceneAsset
+{
+public:
+ ModelSceneAsset() {}
+
+ virtual const char* getID() const override{ return desc.id.c_str(); }
+ virtual const char* getName() const override { return desc.name.c_str(); }
+
+ AssetList::ModelAsset desc;
+
+ virtual PxTransform getInitialTransform() { return desc.transform; }
+};
+
+
+class SimpleModelSceneAsset : public ModelSceneAsset
+{
+public:
+ virtual BlastAsset* createAsset()
+ {
+ return new BlastAssetModelSimple(m_scene->getBlastController().getTkFramework(), m_scene->getPhysXController().getPhysics(),
+ m_scene->getPhysXController().getCooking(), m_scene->getRenderer(), desc.file.c_str());
+ }
+
+ virtual ImVec4 getUIColor() const override
+ {
+ return ImColor(255, 255, 200, 255);
+ }
+};
+
+
+class SkinnedModelSceneAsset : public ModelSceneAsset
+{
+public:
+ virtual BlastAsset* createAsset()
+ {
+ return new BlastAssetModelSkinned(m_scene->getBlastController().getTkFramework(), m_scene->getPhysXController().getPhysics(),
+ m_scene->getPhysXController().getCooking(), m_scene->getRenderer(), desc.file.c_str());
+ }
+
+ virtual ImVec4 getUIColor() const override
+ {
+ return ImColor(255, 200, 255, 255);
+ }
+};
+
+
+class BoxesSceneAsset : public SingleSceneAsset
+{
+public:
+ BoxesSceneAsset(const AssetList::BoxAsset& d) : desc(d)
+ {
+ for (uint32_t lv = 0; lv < desc.levels.size(); ++lv)
+ {
+ const AssetList::BoxAsset::Level& level = desc.levels[lv];
+ NvBlastChunkDesc::Flags fl = (level.isSupport) ? NvBlastChunkDesc::Flags::SupportFlag : NvBlastChunkDesc::Flags::NoFlags;
+ assetDesc.generatorSettings.depths.push_back({ GeneratorAsset::Vec3(level.x, level.y, level.z), fl });
+ }
+ assetDesc.generatorSettings.extents = GeneratorAsset::Vec3(desc.extents.x, desc.extents.y, desc.extents.z);
+ assetDesc.staticHeight = desc.staticHeight;
+ assetDesc.jointAllBonds = desc.jointAllBonds;
+ }
+
+ virtual ImVec4 getUIColor() const override
+ {
+ return ImColor(255, 200, 200, 255);
+ }
+
+ virtual const char* getID() const override { return desc.id.c_str(); }
+ virtual const char* getName() const override { return desc.name.c_str(); }
+
+
+ AssetList::BoxAsset desc;
+ BlastAssetBoxes::Desc assetDesc;
+
+ virtual BlastAsset* createAsset()
+ {
+ return new BlastAssetBoxes(m_scene->getBlastController().getTkFramework(), m_scene->getPhysXController().getPhysics(),
+ m_scene->getPhysXController().getCooking(), m_scene->getRenderer(), assetDesc);
+ }
+
+ virtual PxTransform getInitialTransform() { return PxTransform(PxVec3(0, assetDesc.generatorSettings.extents.y / 2, 0)); }
+};
+
+
+class CompositeSceneAsset : public SceneAsset
+{
+public:
+ CompositeSceneAsset(const AssetList::CompositeAsset& desc)
+ : m_desc(desc)
+ {
+ }
+
+ virtual ~CompositeSceneAsset() { unload(); }
+
+ virtual ImVec4 getUIColor() const override
+ {
+ return ImColor(200, 255, 255, 255);
+ }
+
+ virtual const char* getID() const override { return m_desc.id.c_str(); }
+ virtual const char* getName() const override { return m_desc.name.c_str(); }
+
+ virtual void spawn(PxVec3 shift) override;
+
+ virtual void load() override
+ {
+ if (!isLoaded())
+ {
+ // load dependent assets
+ for (const auto& assetRef : m_desc.assetRefs)
+ {
+ SceneAsset* asset = m_scene->findSceneAsset(assetRef.id);
+ if (asset)
+ {
+ asset->load();
+ m_sceneAssets.push_back(static_cast<SingleSceneAsset*>(asset));
+ }
+ else
+ {
+ m_scene->getCommonUIController().addPopupMessage("Error", "Wrong asset dependency on composite");
+ m_sceneAssets.clear();
+ return;
+ }
+ }
+
+ // check joints
+ for (const auto& joint : m_desc.joints)
+ {
+ bool ok = (joint.assetIndices[0] >= 0 || joint.assetIndices[1] >= 0);
+ for (char k = 0; k < 2 && ok; ++k)
+ {
+ if (joint.assetIndices[k] < 0)
+ continue;
+ ok &= (joint.assetIndices[k] < (int32_t)m_sceneAssets.size());
+ if (!ok)
+ break;
+ ok &= joint.chunkIndices[k] < m_sceneAssets[joint.assetIndices[k]]->getAsset()->getPxAsset()->getTkAsset().getChunkCount();
+ }
+ if (!ok)
+ {
+ m_scene->getCommonUIController().addPopupMessage("Error", "Wrong joint on composite");
+ m_sceneAssets.clear();
+ return;
+ }
+ }
+ }
+ }
+
+ virtual void unload() override
+ {
+ m_sceneAssets.clear();
+ }
+
+ virtual bool isLoaded() const override
+ {
+ return !m_sceneAssets.empty();
+ }
+
+ virtual PxTransform getInitialTransform()
+ {
+ return m_desc.transform;
+ }
+
+ const AssetList::CompositeAsset& getDesc() const
+ {
+ return m_desc;
+ }
+
+ const std::vector<SingleSceneAsset*>& getSceneAssets() const
+ {
+ return m_sceneAssets;
+ }
+
+private:
+ AssetList::CompositeAsset m_desc;
+ std::vector<SingleSceneAsset*> m_sceneAssets;
+};
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Scene Actors
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+class SingleSceneActor : public SceneActor
+{
+public:
+ SingleSceneActor(Scene& scene, SingleSceneAsset* asset, PxVec3 shift)
+ : m_scene(scene)
+ , m_asset(asset)
+ , m_shift(shift)
+ {
+ m_index = m_asset->spawnCount++;
+ spawn();
+ }
+
+ SingleSceneActor::~SingleSceneActor()
+ {
+ remove();
+ }
+
+ virtual const char* getName() const override
+ {
+ return m_name.c_str();
+ }
+
+ virtual const char* getSubname(int) const override
+ {
+ return nullptr;
+ }
+
+ virtual ImVec4 getUIColor() const override
+ {
+ return m_asset->getUIColor();
+ }
+
+ virtual void drawUI(int) override
+ {
+ m_actor->drawUI();
+ }
+
+ virtual void drawStatsUI(int) override
+ {
+ m_actor->drawStatsUI();
+ }
+
+ virtual PxVec3 getSpawnShift() const override
+ {
+ return PxVec3(-20, 0, 0);
+ }
+
+ virtual void reload() override
+ {
+ auto settings = m_actor->getSettings();
+ remove();
+ spawn();
+ m_actor->setSettings(settings);
+ }
+
+private:
+ void remove()
+ {
+ m_scene.getBlastController().removeFamily(m_actor);
+ m_actor = nullptr;
+ }
+
+ void spawn()
+ {
+ std::ostringstream str;
+ str << m_asset->getName();
+ if (m_index)
+ str << " (" << m_index << ")";
+ m_name = str.str();
+
+ PxTransform pose = m_asset->getInitialTransform();
+ pose.p += m_shift;
+
+ BlastAsset::ActorDesc actorDesc = {
+ actorDesc.id = generateIDFromString(m_name.c_str()),
+ pose,
+ m_scene.getBlastController().getTkGroup()
+ };
+
+ m_actor = m_scene.getBlastController().spawnFamily(m_asset->getAsset(), actorDesc);
+ }
+
+ Scene& m_scene;
+ BlastFamilyPtr m_actor;
+ SingleSceneAsset* m_asset;
+ PxVec3 m_shift;
+ uint32_t m_index;
+ std::string m_name;
+};
+
+class CompositeSceneActor : public SceneActor
+{
+public:
+ CompositeSceneActor(Scene& scene, CompositeSceneAsset* asset, PxVec3 shift)
+ : m_scene(scene)
+ , m_asset(asset)
+ , m_shift(shift)
+ {
+ m_index = m_asset->spawnCount++;
+ spawn();
+ }
+
+ CompositeSceneActor::~CompositeSceneActor()
+ {
+ remove();
+ }
+
+ virtual uint32_t getSubactorCount() const
+ {
+ return (uint32_t)m_actors.size();
+ }
+
+ virtual const char* getName() const override
+ {
+ return m_name.c_str();
+ }
+
+ virtual const char* getSubname(int subindex) const override
+ {
+ return m_actors[subindex].name.c_str();
+ }
+
+ virtual ImVec4 getUIColor() const override
+ {
+ return m_asset->getUIColor();
+ }
+
+ virtual void drawUI(int subindex) override
+ {
+ if (subindex >= 0)
+ {
+ m_actors[subindex].actor->drawUI();
+ }
+ else
+ {
+ ImGui::Text("Select subactor to edit settings.");
+ }
+ }
+
+ virtual void drawStatsUI(int subindex) override
+ {
+ if (subindex >= 0)
+ {
+ m_actors[subindex].actor->drawStatsUI();
+ }
+ }
+
+ virtual PxVec3 getSpawnShift() const override
+ {
+ return PxVec3(-20, 0, 0);
+ }
+
+ virtual void reload() override
+ {
+ std::map<uint32_t, BlastFamily::Settings> settings;
+ for (uint32_t i = 0; i < m_actors.size(); ++i)
+ {
+ settings[m_actors[i].initialIndex] = m_actors[i].actor->getSettings();
+ }
+ remove();
+ spawn();
+ for (uint32_t i = 0; i < m_actors.size(); ++i)
+ {
+ if (settings.find(i) != settings.end())
+ {
+ m_actors[i].actor->setSettings(settings[i]);
+ }
+ }
+ }
+
+ virtual void removeSubactor(int subindex)
+ {
+ if (subindex >= 0 && subindex < (int)m_actors.size())
+ {
+ m_scene.getBlastController().removeFamily(m_actors[subindex].actor);
+ m_actors[subindex] = m_actors.back();
+ m_actors.resize(m_actors.size() - 1);
+ }
+ }
+
+private:
+ void remove()
+ {
+ for (uint32_t i = 0; i < m_actors.size(); ++i)
+ {
+ m_scene.getBlastController().removeFamily(m_actors[i].actor);
+ }
+ m_actors.clear();
+ }
+
+ void spawn()
+ {
+ std::ostringstream str;
+ str << m_asset->getName();
+ if (m_index)
+ str << " (" << m_index << ")";
+ m_name = str.str();
+
+ const AssetList::CompositeAsset& assetDesc = m_asset->getDesc();
+ const std::vector<SingleSceneAsset*>& sceneAssets = m_asset->getSceneAssets();
+
+ const uint32_t actorCount = (uint32_t)sceneAssets.size();
+ m_actors.resize(actorCount);
+
+ for (uint32_t i = 0; i < actorCount; ++i)
+ {
+ std::ostringstream str;
+ str << " -> " << i << "." << sceneAssets[i]->getName();
+ m_actors[i].name = str.str();
+ }
+
+ ExtPxManager& pxManager = m_scene.getBlastController().getExtPxManager();
+ for (uint32_t i = 0; i < actorCount; ++i)
+ {
+ PxTransform pose = m_asset->getInitialTransform();
+ pose.p += m_shift;
+ pose = assetDesc.assetRefs[i].transform.transform(pose);
+
+ BlastAsset::ActorDesc actorDesc = {
+ generateIDFromString(m_actors[i].name.c_str()),
+ pose,
+ m_scene.getBlastController().getTkGroup()
+ };
+ m_actors[i].actor = m_scene.getBlastController().spawnFamily(sceneAssets[i]->getAsset(), actorDesc);
+ m_actors[i].initialIndex = i;
+ }
+
+ for (const auto& joint : assetDesc.joints)
+ {
+ TkJointDesc jointDesc;
+ for (char k = 0; k < 2; ++k)
+ {
+ jointDesc.attachPositions[k] = joint.attachPositions[k];
+ jointDesc.chunkIndices[k] = joint.chunkIndices[k];
+ jointDesc.families[k] = (joint.assetIndices[k] < 0) ? nullptr : &m_actors[joint.assetIndices[k]].actor->getFamily()->getTkFamily();
+ }
+ TkJoint* joint = pxManager.getFramework().createJoint(jointDesc);
+ if (joint)
+ {
+ pxManager.createJoint(*joint);
+ }
+ else
+ {
+ m_scene.getCommonUIController().addPopupMessage("Error", "Some joints can't be created");
+ }
+ }
+ }
+
+ struct Subactor
+ {
+ BlastFamilyPtr actor;
+ uint32_t initialIndex;
+ std::string name;
+ };
+
+ Scene& m_scene;
+ std::vector<Subactor> m_actors;
+ CompositeSceneAsset* m_asset;
+ PxVec3 m_shift;
+ uint32_t m_index;
+ std::string m_name;
+};
+
+class PhysXSceneActor : public SceneActor
+{
+public:
+ PhysXSceneActor(PhysXController& physXController, PhysXController::Actor* actor, const char* name)
+ : m_physXController(physXController)
+ , m_actor(actor)
+ , m_name(name)
+ {
+ }
+
+ PhysXSceneActor::~PhysXSceneActor()
+ {
+ m_physXController.removePhysXPrimitive(m_actor);
+ }
+
+ virtual const char* getName() const override
+ {
+ return m_name;
+ }
+
+ virtual ImVec4 getUIColor() const override
+ {
+ return ImColor(255, 100, 100, 255);
+ }
+
+
+private:
+ PhysXController& m_physXController;
+ PhysXController::Actor* m_actor;
+ const char* m_name;
+
+};
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Assets Implementation
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void SingleSceneAsset::spawn(PxVec3 shift)
+{
+ load();
+ SingleSceneActor* actor = new SingleSceneActor(*m_scene, this, shift);
+ m_scene->addSceneActor(actor);
+}
+
+void CompositeSceneAsset::spawn(PxVec3 shift)
+{
+ load();
+ if (isLoaded())
+ {
+ CompositeSceneActor* actor = new CompositeSceneActor(*m_scene, this, shift);
+ m_scene->addSceneActor(actor);
+ }
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// PackmanConfigParser
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+class PackmanConfigParser : public physx::shdfnd::FastXml::Callback
+{
+public:
+ std::vector<std::pair<std::string, std::string>> dependencies;
+
+protected:
+
+ // encountered a comment in the XML
+ virtual bool processComment(const char* /*comment*/)
+ {
+ return true;
+ }
+
+ virtual bool processClose(const char* elementName, unsigned int /*depth*/, bool& /*isError*/)
+ {
+ return true;
+ }
+
+ // return true to continue processing the XML document, false to skip.
+ virtual bool processElement(const char* elementName, // name of the element
+ const char* elementData, // element data, null if none
+ const physx::shdfnd::FastXml::AttributePairs& attr,
+ int /*lineno*/) // line number in the source XML file
+ {
+ if (::strcmp(elementName, "dependency") == 0)
+ {
+ dependencies.resize(dependencies.size() + 1);
+ for (int i = 0; i < attr.getNbAttr(); ++i)
+ {
+ if (::strcmp(attr.getKey(i), "name") == 0)
+ {
+ dependencies.back().first = std::string(attr.getValue(i));
+ }
+ else if (::strcmp(attr.getKey(i), "version") == 0)
+ {
+ dependencies.back().second = std::string(attr.getValue(i));
+ }
+ }
+ }
+ return true;
+ }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Controller
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+SceneController::SceneController() : m_cubeScale(1.0f)
+{
+ m_scene = NULL;
+}
+
+SceneController::~SceneController()
+{
+}
+
+void SceneController::onSampleStart()
+{
+ // setup camera
+ CFirstPersonCamera* camera = &getRenderer().getCamera();
+ DirectX::XMVECTORF32 lookAtPt = { 0, 10, 0, 0 };
+ DirectX::XMVECTORF32 eyePt = { 0, 20, 60, 0 };
+ camera->SetViewParams(eyePt, lookAtPt);
+ camera->SetRotateButtons(false, false, true, false);
+ camera->SetEnablePositionMovement(true);
+
+ // setup scene
+ m_scene = new Scene(getRenderer(), getPhysXController(), getBlastController(), getCommonUIController());
+
+ const SampleConfig& config = getManager()->getConfig();
+
+ // add packman repo to search dirs
+ bool packmanResourcesAdded = false;
+ if (const char* packmanPath = std::getenv("PM_PACKAGES_ROOT"))
+ {
+ const char* RESOURCES_CONFIG_FILE = "resources.xml";
+
+ std::string path;
+ if (getRenderer().getResourceManager().findFile(RESOURCES_CONFIG_FILE, path))
+ {
+ physx::PsFileBuffer fileBuffer(path.c_str(), physx::general_PxIOStream2::PxFileBuf::OPEN_READ_ONLY);
+ if (fileBuffer.isOpen())
+ {
+ PxInputDataFromPxFileBuf inputData(fileBuffer);
+ PackmanConfigParser parser;
+ physx::shdfnd::FastXml* xml = physx::shdfnd::createFastXml(&parser);
+ xml->processXml(inputData, false);
+ xml->release();
+ for (auto& dep : parser.dependencies)
+ {
+ std::stringstream ss;
+ ss << packmanPath << "\\" << dep.first << "\\" << dep.second;
+ if (getRenderer().getResourceManager().addSearchDir(ss.str().c_str()))
+ {
+ packmanResourcesAdded = true;
+ }
+ }
+ }
+ }
+ }
+ if (!packmanResourcesAdded)
+ {
+ getManager()->getCommonUIController().addPopupMessage("Error", "BlastSampleResources package wasn't found. Consider running download_sample_resources.bat in root folder.", 5.0f);
+ }
+
+ // parse asset file
+ AssetList assetList;
+ if (!config.assetsFile.empty())
+ {
+ std::string path;
+ if (getRenderer().getResourceManager().findFile(config.assetsFile, path))
+ {
+ parseAssetList(assetList, path);
+ }
+ }
+
+ // add both asset file and asset list from config
+ addAssets(config.additionalAssetList, packmanResourcesAdded);
+ addAssets(assetList, packmanResourcesAdded);
+
+// Add By Lixu Begin
+ int size = m_scene->getAssets().size();
+ for (int i = 0; i < size; i++)
+ {
+ spawnAsset(i);
+ }
+// Add By Lixu End
+}
+
+void SceneController::addAssets(const AssetList& assetList, bool loadModels)
+{
+ if (loadModels)
+ {
+ for (const auto& model : assetList.models)
+ {
+ ModelSceneAsset* asset;
+ if (!model.isSkinned)
+ {
+ asset = new SimpleModelSceneAsset();
+ }
+ else
+ {
+ asset = new SkinnedModelSceneAsset();
+ }
+ asset->desc = model;
+ m_scene->addAsset(asset);
+ }
+
+ for (const auto& composite : assetList.composites)
+ {
+ m_scene->addAsset(new CompositeSceneAsset(composite));
+ }
+ }
+
+ for (const auto& box : assetList.boxes)
+ {
+ BoxesSceneAsset* asset = new BoxesSceneAsset(box);
+ m_scene->addAsset(asset);
+ }
+}
+
+void SceneController::onInitialize()
+{
+
+}
+
+void SceneController::onSampleStop()
+{
+ if (NULL != m_scene)
+ {
+ delete m_scene;
+ m_scene = nullptr;
+ }
+}
+
+void SceneController::onTerminate()
+{
+}
+
+void SceneController::Animate(double dt)
+{
+}
+
+LRESULT SceneController::MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ if (uMsg == WM_KEYDOWN)
+ {
+ int iKeyPressed = static_cast<int>(wParam);
+ switch (iKeyPressed)
+ {
+ case 'R':
+ m_scene->reloadAllActors();
+ return 0;
+ case 'F':
+ throwCube();
+ return 0;
+ default:
+ break;
+ }
+ }
+
+ return 1;
+}
+
+void SceneController::drawUI()
+{
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // Scene UI
+ ///////////////////////////////////////////////////////////////////////////////////////////
+
+ m_scene->drawUI();
+
+
+ ImGui::Spacing();
+ ImGui::Spacing();
+ ImGui::Separator();
+ ImGui::Spacing();
+ ImGui::Spacing();
+
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // Replay
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ {
+ ImGui::Text("Replay Control:");
+
+ BlastReplay* replay = getBlastController().getReplay();
+ if (replay->isRecording())
+ {
+ auto getAnimStr = []()
+ {
+ const uint32_t count = 5;
+ const uint64_t periodMS = 150;
+ static char str[count + 1] = "";
+ for (uint32_t i = 0; i < count; i++)
+ {
+ uint64_t ts = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch()).count();
+ str[i] = (i == (ts % (periodMS * count)) / periodMS) ? '*' : ' ';
+ }
+ return str;
+ };
+ ImGui::Text("State: Recording [%s] | Events: %d", getAnimStr(), replay->getEventCount());
+
+ if (ImGui::Button("Stop Recording"))
+ {
+ replay->stopRecording();
+ }
+ }
+ else if (replay->isPlaying())
+ {
+ ImGui::Text("State: Playing | Events: %d / %d", replay->getCurrentEventIndex(), replay->getEventCount());
+
+ if (ImGui::Button("Stop Playing"))
+ {
+ replay->stopPlayback();
+ }
+ }
+ else
+ {
+ ImGui::Text("State: Idle | Events: %d", replay->getEventCount());
+
+ static bool syncFamilies = true;
+ static bool syncPhysics = true;
+
+ ImGui::Checkbox("Sync Initial Actors", &syncFamilies);
+ if (ImGui::Checkbox("Sync Initial Transforms", &syncPhysics))
+ {
+ syncFamilies = syncPhysics;
+ }
+
+ if (ImGui::Button("Start Recording"))
+ {
+ replay->startRecording(getBlastController().getExtPxManager(), syncFamilies, syncPhysics);
+ }
+
+ if (replay->hasRecord())
+ {
+ static bool reload = false;
+ if (ImGui::Button("Start Playback"))
+ {
+ if (reload)
+ m_scene->reloadAllActors();
+ replay->startPlayback(getBlastController().getExtPxManager(), getBlastController().getTkGroup());
+ }
+ ImGui::SameLine();
+ ImGui::Checkbox("Reload Scene On Playback", &reload);
+ }
+ }
+ }
+
+ ImGui::Spacing();
+ ImGui::Spacing();
+ ImGui::Separator();
+
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // Cube
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ {
+ ImGui::Text("Thrown Cube Params (F)");
+ ImGui::DragFloat("Cube Size", &m_cubeScale, 1.0f, 0.0f, 100.0f);
+ }
+
+}
+
+void SceneController::drawStatsUI()
+{
+ m_scene->drawStatsUI();
+}
+
+void SceneController::throwCube()
+{
+ const float CUBE_VELOCITY = 100;
+ const float CUBE_DENSITY = 20000.0f;
+
+ CFirstPersonCamera* camera = &getRenderer().getCamera();
+ PxVec3 eyePos = XMVECTORToPxVec4(camera->GetEyePt()).getXYZ();
+ PxVec3 lookAtPos = XMVECTORToPxVec4(camera->GetLookAtPt()).getXYZ();
+ PhysXController::Actor* cube = getPhysXController().spawnPhysXPrimitiveBox(PxTransform(eyePos), PxVec3(m_cubeScale, m_cubeScale, m_cubeScale), CUBE_DENSITY);
+ PxRigidDynamic* rigidDynamic = cube->getActor()->is<PxRigidDynamic>();
+ cube->setColor(DirectX::XMFLOAT4(1, 0, 0, 1));
+
+ PxVec3 dir = (lookAtPos - eyePos).getNormalized();
+ rigidDynamic->setLinearVelocity(dir * CUBE_VELOCITY);
+
+// Add By Lixu Begin
+ std::string validname = "";
+ if (m_ReusedNames.size() > 0)
+ {
+ validname = m_ReusedNames.back();
+ m_ReusedNames.pop_back();
+ }
+ else
+ {
+ int projectilesSize = m_Projectiles.size();
+ char cubename[10];
+ sprintf(cubename, "Cube_%d", projectilesSize);
+ validname = cubename;
+ }
+ cube->setColor(DirectX::XMFLOAT4(1, 1, 1, 1));
+ PhysXSceneActor* p = new PhysXSceneActor(getPhysXController(), cube, validname.c_str());
+ m_UsedNames.push_back(validname);
+ m_Projectiles.push_back(p);
+ m_scene->addSceneActor(p);
+
+ getManager()->m_bNeedRefreshTree = true;
+// Add By Lixu End
+}
+
+void SceneController::spawnAsset(int32_t num)
+{
+ m_scene->spawnAsset(num);
+}
+
+int SceneController::releaseAll()
+{
+ return m_scene->releaseAll();
+}
+
+// Add By Lixu Begin
+void SceneController::addProjectile()
+{
+ throwCube();
+}
+
+void SceneController::clearProjectile()
+{
+ std::vector<PhysXSceneActor*>::iterator it;
+ for (it = m_Projectiles.begin(); it != m_Projectiles.end(); it++)
+ {
+ std::vector<SceneActor*>& actors = m_scene->getActors();
+ std::map<SceneActor*, int> ActorIndexMap;
+ int actorSize = actors.size();
+ for (int i = 0; i < actorSize; i++)
+ {
+ ActorIndexMap[actors[i]] = i;
+ }
+
+ m_scene->removeSceneActor(Scene::ActorIndex(ActorIndexMap[*it], -1));
+ }
+ m_Projectiles.clear();
+ m_UsedNames.clear();
+ m_ReusedNames.clear();
+}
+
+void SceneController::ResetScene()
+{
+ clearProjectile();
+ m_scene->reloadAllActors();
+}
+
+void SceneController::ClearScene()
+{
+ clearProjectile();
+ m_scene->releaseAll();
+// Add By Lixu Begin
+ PhysXController& pc = getPhysXController();
+ pc.ClearOldCOllisions();
+// Add By Lixu End
+}
+
+bool SceneController::GetAssetDesc(const BlastAsset* asset, AssetList::ModelAsset& desc)
+{
+ SampleManager* pSampleManager = getManager();
+ SampleConfig* config = (SampleConfig*)&(pSampleManager->getConfig());
+ std::vector<AssetList::ModelAsset>& modelAssets = config->additionalAssetList.models;
+ std::vector<AssetList::ModelAsset>::iterator itModelAssets;
+ std::vector<SceneAsset*>& sceneAssets = m_scene->getAssets();
+ std::vector<SceneAsset*>::iterator itSceneAssets;
+
+ bool find = false;
+ for (itSceneAssets = sceneAssets.begin(); itSceneAssets != sceneAssets.end(); itSceneAssets++)
+ {
+ SceneAsset* sceneAsset = *itSceneAssets;
+ std::string id = sceneAsset->getID();
+ for (itModelAssets = modelAssets.begin(); itModelAssets != modelAssets.end(); itModelAssets++)
+ {
+ AssetList::ModelAsset& modelAsset = *itModelAssets;
+ if (modelAsset.id == id)
+ {
+ if (!modelAsset.isSkinned)
+ {
+ SimpleModelSceneAsset* pSimpleModelSceneAsset = (SimpleModelSceneAsset*)sceneAsset;
+ if (pSimpleModelSceneAsset->getAsset() == asset)
+ {
+ desc = modelAsset;
+ find = true;
+ break;
+ }
+ }
+ else
+ {
+ SkinnedModelSceneAsset* pSkinnedModelSceneAsset = (SkinnedModelSceneAsset*)sceneAsset;
+ if (pSkinnedModelSceneAsset->getAsset() == asset)
+ {
+ desc = modelAsset;
+ find = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (find)
+ {
+ break;
+ }
+ }
+
+ return find;
+}
+
+void SceneController::GetProjectilesNames(std::vector<std::string>& projectilesNames)
+{
+ projectilesNames.clear();
+ std::vector<std::string>::iterator it = m_UsedNames.begin();
+ for (; it != m_UsedNames.end(); it++)
+ {
+ projectilesNames.push_back(*it);
+ }
+}
+// Add By Lixu End \ No newline at end of file