feat: add audio system
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
#define EDITOR_ASSETBROWSER_H
|
||||
|
||||
#include <filesystem>
|
||||
#include <future>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -10,6 +11,8 @@ class AssetBrowser final {
|
||||
public:
|
||||
std::optional<std::string> Draw(bool* open = nullptr);
|
||||
|
||||
void ConfigureCooking(std::filesystem::path cooker, std::vector<std::string> schemes);
|
||||
|
||||
private:
|
||||
struct Entry {
|
||||
std::string name;
|
||||
@@ -17,6 +20,8 @@ private:
|
||||
};
|
||||
|
||||
void Refresh();
|
||||
void StartCook();
|
||||
void PollCook();
|
||||
void Navigate(const std::string& scheme, const std::filesystem::path& folder);
|
||||
[[nodiscard]] std::string VirtualPath(const std::string& name) const;
|
||||
void DrawEntry(const Entry& entry, std::optional<std::string>& opened, bool& navigated);
|
||||
@@ -27,6 +32,11 @@ private:
|
||||
std::vector<Entry> m_Entries;
|
||||
std::string m_Filter;
|
||||
bool m_Dirty{true};
|
||||
|
||||
std::filesystem::path m_Cooker;
|
||||
std::vector<std::string> m_CookSchemes;
|
||||
std::future<bool> m_Cook;
|
||||
bool m_AppFocused{true};
|
||||
};
|
||||
|
||||
#endif // EDITOR_ASSETBROWSER_H
|
||||
|
||||
@@ -2,9 +2,15 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <chrono>
|
||||
#include <cstdlib>
|
||||
#include <exception>
|
||||
#include <utility>
|
||||
|
||||
#include <imgui.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
#include <destrum/Assets/AssetDatabase.h>
|
||||
#include <destrum/Assets/AssetTypes.h>
|
||||
#include <destrum/FS/AssetFS.h>
|
||||
#include <destrum/Graphics/Material.h>
|
||||
@@ -42,13 +48,29 @@ namespace {
|
||||
if (AssetTypes::IsPrefab(name)) return "[prefab] ";
|
||||
if (AssetTypes::IsMaterial(name)) return "[material] ";
|
||||
if (AssetTypes::IsImage(name)) return "[image] ";
|
||||
if (AssetTypes::IsAudio(name)) return "[audio] ";
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
void AssetBrowser::ConfigureCooking(std::filesystem::path cooker, std::vector<std::string> schemes)
|
||||
{
|
||||
m_Cooker = std::move(cooker);
|
||||
m_CookSchemes = std::move(schemes);
|
||||
}
|
||||
|
||||
std::optional<std::string> AssetBrowser::Draw(bool* open)
|
||||
{
|
||||
std::optional<std::string> opened;
|
||||
|
||||
// Files dropped into assets_src from Explorer show up when the user comes back to the editor
|
||||
const bool appFocused = !ImGui::GetIO().AppFocusLost;
|
||||
if (appFocused && !m_AppFocused) {
|
||||
StartCook();
|
||||
}
|
||||
m_AppFocused = appFocused;
|
||||
PollCook();
|
||||
|
||||
if (!ImGui::Begin("Assets", open)) {
|
||||
ImGui::End();
|
||||
return opened;
|
||||
@@ -70,9 +92,14 @@ std::optional<std::string> AssetBrowser::Draw(bool* open)
|
||||
}
|
||||
ImGui::SameLine();
|
||||
}
|
||||
if (ImGui::Button("Refresh")) {
|
||||
const bool cooking = m_Cook.valid();
|
||||
ImGui::BeginDisabled(cooking);
|
||||
if (ImGui::Button(cooking ? "Cooking..." : "Refresh")) {
|
||||
m_Dirty = true;
|
||||
StartCook();
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
ImGui::SetItemTooltip("Cooks new and changed files from assets_src, then lists the folder again");
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(-FLT_MIN);
|
||||
ImGuiUtils::InputString("##Filter", m_Filter, 0, "Search this folder");
|
||||
@@ -172,6 +199,55 @@ void AssetBrowser::Navigate(const std::string& scheme, const std::filesystem::pa
|
||||
m_Dirty = true;
|
||||
}
|
||||
|
||||
void AssetBrowser::StartCook()
|
||||
{
|
||||
if (m_Cooker.empty() || m_Cook.valid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<std::string> commands;
|
||||
for (const std::string& scheme : m_CookSchemes) {
|
||||
const FSMount* mount = FindMount(scheme);
|
||||
if (mount == nullptr || !mount->sourceRoot) {
|
||||
continue;
|
||||
}
|
||||
// cmd.exe strips the outer quotes, the inner ones keep paths with spaces intact
|
||||
commands.push_back("\"\"" + m_Cooker.string() + "\" --input \"" + mount->sourceRoot->string() +
|
||||
"\" --output \"" + mount->root.string() + "\"\"");
|
||||
}
|
||||
if (commands.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_Cook = std::async(std::launch::async, [commands = std::move(commands)] {
|
||||
bool succeeded = true;
|
||||
for (const std::string& command : commands) {
|
||||
succeeded = std::system(command.c_str()) == 0 && succeeded;
|
||||
}
|
||||
return succeeded;
|
||||
});
|
||||
}
|
||||
|
||||
void AssetBrowser::PollCook()
|
||||
{
|
||||
if (!m_Cook.valid() || m_Cook.wait_for(std::chrono::seconds{0}) != std::future_status::ready) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_Cook.get()) {
|
||||
spdlog::error("Cooking the assets failed, see the log above");
|
||||
}
|
||||
try {
|
||||
for (const std::string& scheme : m_CookSchemes) {
|
||||
AssetFS::GetInstance().ReloadManifest(scheme);
|
||||
}
|
||||
AssetDatabase::GetInstance().Refresh();
|
||||
} catch (const std::exception& exception) {
|
||||
spdlog::error("Could not reload the asset manifest: {}", exception.what());
|
||||
}
|
||||
m_Dirty = true;
|
||||
}
|
||||
|
||||
void AssetBrowser::Refresh()
|
||||
{
|
||||
m_Dirty = false;
|
||||
|
||||
@@ -53,6 +53,10 @@ void Editor::onAttach()
|
||||
#if defined(DESTRUM_ENGINE_ASSETS_SRC_DIR) && defined(DESTRUM_THECHEF_PATH)
|
||||
m_ShaderHotReload.Configure(DESTRUM_THECHEF_PATH, DESTRUM_ENGINE_ASSETS_SRC_DIR, assetFs.GetFullPath("engine://shaders").parent_path());
|
||||
#endif
|
||||
#ifdef DESTRUM_THECHEF_PATH
|
||||
// Engine assets are left to the shader hot reload, two cooks writing one manifest would race
|
||||
m_AssetBrowser.ConfigureCooking(DESTRUM_THECHEF_PATH, {"game"});
|
||||
#endif
|
||||
|
||||
if (m_Settings.startInEditMode) {
|
||||
m_PlayMode.EnterEditMode();
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include <destrum/App.h>
|
||||
#include <destrum/Assets/AssetTypes.h>
|
||||
#include <destrum/Components/AudioSource.h>
|
||||
#include <destrum/Components/MeshRendererComponent.h>
|
||||
#include <destrum/Components/Physics/Collider.h>
|
||||
#include <destrum/Components/Physics/Rigidbody.h>
|
||||
@@ -179,6 +180,11 @@ void Editor::OnAssetDropped(std::string_view path)
|
||||
}
|
||||
instance->GetTransform().SetWorldPosition(spawnPosition);
|
||||
scene->SetSelectedObject(instance->GetId());
|
||||
} else if (AssetTypes::IsAudio(path)) {
|
||||
GameObject* object = scene->CreateGameObject(name);
|
||||
object->AddComponent<AudioSource>(std::string{path});
|
||||
object->GetTransform().SetWorldPosition(spawnPosition);
|
||||
scene->SetSelectedObject(object->GetId());
|
||||
} else if (AssetTypes::IsMaterial(path)) {
|
||||
GameObject* selected = scene->GetSelectedObject();
|
||||
if (selected == nullptr) {
|
||||
|
||||
Reference in New Issue
Block a user