LumixEngine/src/studio/asset_browser.cpp
Mikulas Florek c0c3161b22 some W4 level warnings fixed;
some x64 warnings fixed;
2015-11-14 00:25:08 +01:00

862 lines
No EOL
22 KiB
C++

#include "asset_browser.h"
#include "core/crc32.h"
#include "core/FS/file_system.h"
#include "core/FS/ifile.h"
#include "core/json_serializer.h"
#include "core/path_utils.h"
#include "core/profiler.h"
#include "core/resource.h"
#include "core/resource_manager.h"
#include "core/resource_manager_base.h"
#include "core/string.h"
#include "core/system.h"
#include "editor/ieditor_command.h"
#include "editor/world_editor.h"
#include "engine/engine.h"
#include "engine/iplugin.h"
#include "file_system_watcher.h"
#include "lua_script/lua_script_manager.h"
#include "metadata.h"
#include "ocornut-imgui/imgui.h"
#include "platform_interface.h"
#include "renderer/material.h"
#include "renderer/model.h"
#include "renderer/render_scene.h"
#include "renderer/shader.h"
#include "renderer/texture.h"
#include "universe/universe.h"
#include "utils.h"
static const Lumix::uint32 UNIVERSE_HASH = Lumix::crc32("universe");
static const Lumix::uint32 SOURCE_HASH = Lumix::crc32("source");
static const Lumix::uint32 LUA_SCRIPT_HASH = Lumix::crc32("lua_script");
static Lumix::uint32 getResourceType(const char* path)
{
char ext[10];
Lumix::PathUtils::getExtension(ext, sizeof(ext), path);
if (Lumix::compareString(ext, "mat") == 0) return Lumix::ResourceManager::MATERIAL;
if (Lumix::compareString(ext, "msh") == 0) return Lumix::ResourceManager::MODEL;
if (Lumix::compareString(ext, "dds") == 0) return Lumix::ResourceManager::TEXTURE;
if (Lumix::compareString(ext, "raw") == 0) return Lumix::ResourceManager::TEXTURE;
if (Lumix::compareString(ext, "tga") == 0) return Lumix::ResourceManager::TEXTURE;
if (Lumix::compareString(ext, "shd") == 0) return Lumix::ResourceManager::SHADER;
if (Lumix::compareString(ext, "unv") == 0) return UNIVERSE_HASH;
if (Lumix::compareString(ext, "lua") == 0) return LUA_SCRIPT_HASH;
return 0;
}
AssetBrowser::AssetBrowser(Lumix::WorldEditor& editor, Metadata& metadata)
: m_editor(editor)
, m_metadata(metadata)
, m_resources(editor.getAllocator())
, m_selected_resource(nullptr)
, m_autoreload_changed_resource(true)
, m_changed_files(editor.getAllocator())
, m_is_focus_requested(false)
, m_changed_files_mutex(false)
, m_history(editor.getAllocator())
{
m_filter[0] = '\0';
m_current_type = 0;
m_text_buffer[0] = '\0';
m_is_opened = false;
for (int i = 0; i < Count; ++i)
{
m_resources.emplace(editor.getAllocator());
}
findResources();
m_watcher = FileSystemWatcher::create(editor.getBasePath(), editor.getAllocator());
m_watcher->getCallback().bind<AssetBrowser, &AssetBrowser::onFileChanged>(this);
}
AssetBrowser::~AssetBrowser()
{
unloadResource();
FileSystemWatcher::destroy(m_watcher);
}
void AssetBrowser::onFileChanged(const char* path)
{
Lumix::uint32 resource_type = getResourceType(path);
if (resource_type == 0) return;
Lumix::MT::SpinLock lock(m_changed_files_mutex);
m_changed_files.push(Lumix::Path(path));
}
void AssetBrowser::unloadResource()
{
if (!m_selected_resource) return;
m_selected_resource->getResourceManager()
.get(getResourceType(m_selected_resource->getPath().c_str()))
->unload(*m_selected_resource);
m_selected_resource = nullptr;
}
AssetBrowser::Type AssetBrowser::getTypeFromResourceManagerType(Lumix::uint32 type) const
{
switch (type)
{
case Lumix::ResourceManager::MODEL: return MODEL;
case Lumix::ResourceManager::SHADER: return SHADER;
case Lumix::ResourceManager::TEXTURE: return TEXTURE;
case Lumix::ResourceManager::MATERIAL: return MATERIAL;
}
if (type == UNIVERSE_HASH) return UNIVERSE;
if (type == LUA_SCRIPT_HASH) return LUA_SCRIPT;
return MODEL;
}
void AssetBrowser::update()
{
PROFILE_FUNCTION();
bool is_empty;
{
Lumix::MT::SpinLock lock(m_changed_files_mutex);
is_empty = m_changed_files.empty();
}
while (!is_empty)
{
Lumix::Path path_obj;
{
Lumix::MT::SpinLock lock(m_changed_files_mutex);
path_obj = m_changed_files.back();
m_changed_files.pop();
is_empty = m_changed_files.empty();
}
const char* path = path_obj.c_str();
Lumix::uint32 resource_type = getResourceType(path);
if (resource_type == 0) continue;
if (m_autoreload_changed_resource) m_editor.getEngine().getResourceManager().reload(path);
if (!Lumix::fileExists(path))
{
int index = getTypeFromResourceManagerType(resource_type);
m_resources[index].eraseItemFast(path_obj);
continue;
}
char dir[Lumix::MAX_PATH_LENGTH];
char filename[Lumix::MAX_PATH_LENGTH];
Lumix::PathUtils::getDir(dir, sizeof(dir), path);
Lumix::PathUtils::getFilename(filename, sizeof(filename), path);
addResource(dir, filename);
}
m_changed_files.clear();
}
void AssetBrowser::onGUI()
{
if (m_wanted_resource.isValid())
{
selectResource(m_wanted_resource);
m_wanted_resource = "";
}
if (!m_is_opened) return;
if (!ImGui::Begin("AssetBrowser", &m_is_opened))
{
ImGui::End();
return;
}
if (m_is_focus_requested)
{
m_is_focus_requested = false;
ImGui::SetWindowFocus();
}
if (ImGui::Button("Refresh")) findResources();
ImGui::SameLine();
ImGui::Checkbox("Autoreload", &m_autoreload_changed_resource);
const char* items = "Material\0Model\0Shader\0Texture\0Universe\0Lua Script\0";
ImGui::Combo("Type", &m_current_type, items);
ImGui::InputText("Filter", m_filter, sizeof(m_filter));
ImGui::ListBoxHeader("Resources");
auto& resources = m_resources[m_current_type];
for (auto& resource : resources)
{
if (m_filter[0] != '\0' && strstr(resource.c_str(), m_filter) == nullptr) continue;
bool is_selected = m_selected_resource ? m_selected_resource->getPath() == resource : false;
if (ImGui::Selectable(resource.c_str(), is_selected))
{
selectResource(resource);
}
}
ImGui::ListBoxFooter();
onGUIResource();
ImGui::End();
}
void AssetBrowser::selectResource(Lumix::Resource* resource)
{
if (m_selected_resource) m_history.push(m_selected_resource->getPath());
if (m_history.size() > 20) m_history.erase(0);
m_text_buffer[0] = '\0';
m_wanted_resource = "";
unloadResource();
m_selected_resource = resource;
ASSERT(m_selected_resource->getRefCount() > 0);
}
void AssetBrowser::selectResource(const Lumix::Path& resource)
{
char ext[30];
Lumix::PathUtils::getExtension(ext, Lumix::lengthOf(ext), resource.c_str());
if (Lumix::compareString(ext, "unv") == 0) return;
auto& manager = m_editor.getEngine().getResourceManager();
auto* resource_manager = manager.get(getResourceType(resource.c_str()));
if (resource_manager) selectResource(resource_manager->load(resource));
}
void AssetBrowser::saveMaterial(Lumix::Material* material)
{
Lumix::FS::FileSystem& fs = m_editor.getEngine().getFileSystem();
// use temporary because otherwise the material is reloaded during saving
char tmp_path[Lumix::MAX_PATH_LENGTH];
strcpy(tmp_path, material->getPath().c_str());
strcat(tmp_path, ".tmp");
Lumix::FS::IFile* file =
fs.open(fs.getDefaultDevice(), tmp_path, Lumix::FS::Mode::CREATE | Lumix::FS::Mode::WRITE);
if (file)
{
Lumix::DefaultAllocator allocator;
Lumix::JsonSerializer serializer(*file,
Lumix::JsonSerializer::AccessMode::WRITE,
material->getPath().c_str(),
allocator);
if (!material->save(serializer))
{
Lumix::g_log_error.log("Material manager") << "Error saving "
<< material->getPath().c_str();
}
fs.close(*file);
Lumix::deleteFile(material->getPath().c_str());
Lumix::moveFile(tmp_path, material->getPath().c_str());
}
else
{
Lumix::g_log_error.log("Material manager") << "Could not save file "
<< material->getPath().c_str();
}
}
bool AssetBrowser::resourceInput(const char* label, const char* str_id, char* buf, int max_size, Type type)
{
float item_w = ImGui::CalcItemWidth();
auto& style = ImGui::GetStyle();
ImGui::PushItemWidth(item_w - ImGui::CalcTextSize("...View").x - style.FramePadding.x * 4 -
style.ItemSpacing.x * 2);
if (ImGui::InputText(StringBuilder<30>("##", str_id), buf, max_size)) return true;
ImGui::SameLine();
StringBuilder<50> popup_name("pu", str_id);
if (ImGui::Button(StringBuilder<30>("...##browse", str_id)))
{
ImGui::OpenPopup(popup_name);
}
ImGui::SameLine();
if (ImGui::Button(StringBuilder<30>("View##go", str_id)))
{
m_is_focus_requested = true;
m_is_opened = true;
m_wanted_resource = buf;
}
ImGui::SameLine();
ImGui::Text(label);
ImGui::PopItemWidth();
if (ImGui::BeginPopup(popup_name))
{
static char filter[128] = "";
ImGui::InputText("Filter", filter, sizeof(filter));
for (auto unv : getResources(type))
{
if (filter[0] != '\0' && strstr(unv.c_str(), filter) == nullptr) continue;
if (ImGui::Selectable(unv.c_str(), false))
{
Lumix::copyString(buf, max_size, unv.c_str());
ImGui::EndPopup();
return true;
}
}
ImGui::EndPopup();
}
return false;
}
void AssetBrowser::onGUIMaterial()
{
auto* material = static_cast<Lumix::Material*>(m_selected_resource);
if (ImGui::Button("Save")) saveMaterial(material);
ImGui::SameLine();
if (ImGui::Button("Open in external editor")) openInExternalEditor(material);
bool b;
if (material->hasAlphaCutoutDefine())
{
b = material->isAlphaCutout();
if (ImGui::Checkbox("Is alpha cutout", &b)) material->enableAlphaCutout(b);
}
b = material->isBackfaceCulling();
if (ImGui::Checkbox("Is backface culling", &b)) material->enableBackfaceCulling(b);
if (material->hasShadowReceivingDefine())
{
b = material->isShadowReceiver();
if (ImGui::Checkbox("Is shadow receiver", &b)) material->enableShadowReceiving(b);
}
b = material->isZTest();
if (ImGui::Checkbox("Z test", &b)) material->enableZTest(b);
Lumix::Vec3 specular = material->getSpecular();
if (ImGui::ColorEdit3("Specular", &specular.x))
{
material->setSpecular(specular);
}
float shininess = material->getShininess();
if (ImGui::DragFloat("Shininess", &shininess))
{
material->setShininess(shininess);
}
char buf[256];
Lumix::copyString(buf, material->getShader() ? material->getShader()->getPath().c_str() : "");
if (resourceInput("Shader", "shader", buf, sizeof(buf), SHADER))
{
material->setShader(Lumix::Path(buf));
}
for (int i = 0; i < material->getShader()->getTextureSlotCount(); ++i)
{
auto& slot = material->getShader()->getTextureSlot(i);
auto* texture = material->getTexture(i);
Lumix::copyString(buf, texture ? texture->getPath().c_str() : "");
if (resourceInput(
slot.m_name, StringBuilder<30>("", (Lumix::uint64)&slot), buf, sizeof(buf), TEXTURE))
{
material->setTexturePath(i, Lumix::Path(buf));
}
if (!texture) continue;
ImGui::SameLine();
StringBuilder<100> popup_name("pu", (Lumix::uint64)texture, slot.m_name);
if (ImGui::Button(StringBuilder<100>("Advanced##adv", (Lumix::uint64)texture, slot.m_name)))
{
ImGui::OpenPopup(popup_name);
}
if (ImGui::BeginPopup(popup_name))
{
bool u_clamp = (texture->getFlags() & BGFX_TEXTURE_U_CLAMP) != 0;
if (ImGui::Checkbox("u clamp", &u_clamp))
{
texture->setFlag(BGFX_TEXTURE_U_CLAMP, u_clamp);
}
bool v_clamp = (texture->getFlags() & BGFX_TEXTURE_V_CLAMP) != 0;
if (ImGui::Checkbox("v clamp", &v_clamp))
{
texture->setFlag(BGFX_TEXTURE_V_CLAMP, v_clamp);
}
bool min_point = (texture->getFlags() & BGFX_TEXTURE_MIN_POINT) != 0;
if (ImGui::Checkbox("Min point", &min_point))
{
texture->setFlag(BGFX_TEXTURE_MIN_POINT, min_point);
}
bool mag_point = (texture->getFlags() & BGFX_TEXTURE_MAG_POINT) != 0;
if (ImGui::Checkbox("Mag point", &mag_point))
{
texture->setFlag(BGFX_TEXTURE_MAG_POINT, mag_point);
}
if (slot.m_is_atlas)
{
int size = texture->getAtlasSize() - 2;
const char values[] = { '2', 'x', '2', 0, '3', 'x', '3', 0, '4', 'x', '4', 0, 0 };
if (ImGui::Combo(StringBuilder<30>("Atlas size##", i), &size, values))
{
texture->setAtlasSize(size + 2);
}
}
ImGui::EndPopup();
}
}
for (int i = 0; i < material->getUniformCount(); ++i)
{
auto& uniform = material->getUniform(i);
switch (uniform.m_type)
{
case Lumix::Material::Uniform::FLOAT:
ImGui::DragFloat(uniform.m_name, &uniform.m_float);
break;
}
}
ImGui::Columns(1);
}
void AssetBrowser::onGUITexture()
{
auto* texture = static_cast<Lumix::Texture*>(m_selected_resource);
if (texture->isFailure())
{
ImGui::Text("Texture failed to load");
return;
}
ImGui::LabelText("Size", "%dx%d", texture->getWidth(), texture->getHeight());
ImGui::LabelText("BPP", "%d", texture->getBytesPerPixel());
m_texture_handle = texture->getTextureHandle();
if (bgfx::isValid(m_texture_handle))
{
ImGui::Image(&m_texture_handle, ImVec2(200, 200));
if (ImGui::Button("Open"))
{
openInExternalEditor(m_selected_resource);
}
}
}
void AssetBrowser::onGUILuaScript()
{
auto* script = static_cast<Lumix::LuaScript*>(m_selected_resource);
if (m_text_buffer[0] == '\0')
{
Lumix::copyString(m_text_buffer, script->getSourceCode());
}
ImGui::InputTextMultiline("Code", m_text_buffer, sizeof(m_text_buffer), ImVec2(0, 300));
if (ImGui::Button("Save"))
{
auto& fs = m_editor.getEngine().getFileSystem();
auto* file = fs.open(fs.getDiskDevice(),
m_selected_resource->getPath().c_str(),
Lumix::FS::Mode::CREATE | Lumix::FS::Mode::WRITE);
if (!file)
{
Lumix::g_log_warning.log("Asset browser") << "Could not save "
<< m_selected_resource->getPath().c_str();
return;
}
file->write(m_text_buffer, Lumix::stringLength(m_text_buffer));
fs.close(*file);
}
ImGui::SameLine();
if (ImGui::Button("Open in external editor"))
{
openInExternalEditor(m_selected_resource);
}
}
void AssetBrowser::openInExternalEditor(Lumix::Resource* resource)
{
StringBuilder<Lumix::MAX_PATH_LENGTH> path(m_editor.getBasePath());
path << "/" << resource->getPath().c_str();
Lumix::shellExecuteOpen(path);
}
void AssetBrowser::onGUIShader()
{
auto* shader = static_cast<Lumix::Shader*>(m_selected_resource);
StringBuilder<Lumix::MAX_PATH_LENGTH> path(m_editor.getBasePath());
char basename[Lumix::MAX_PATH_LENGTH];
Lumix::PathUtils::getBasename(
basename, Lumix::lengthOf(basename), m_selected_resource->getPath().c_str());
path << "/shaders/" << basename;
if (ImGui::Button("Open vertex shader"))
{
path << "_vs.sc";
Lumix::shellExecuteOpen(path);
}
ImGui::SameLine();
if (ImGui::Button("Open fragment shader"))
{
path << "_fs.sc";
Lumix::shellExecuteOpen(path);
}
if (ImGui::CollapsingHeader("Texture slots", nullptr, true, true))
{
ImGui::Columns(2);
ImGui::Text("name");
ImGui::NextColumn();
ImGui::Text("uniform");
ImGui::NextColumn();
ImGui::Separator();
for (int i = 0; i < shader->getTextureSlotCount(); ++i)
{
auto& slot = shader->getTextureSlot(i);
ImGui::Text(slot.m_name);
ImGui::NextColumn();
ImGui::Text(slot.m_uniform);
ImGui::NextColumn();
}
ImGui::Columns(1);
}
}
class InsertMeshCommand : public Lumix::IEditorCommand
{
public:
InsertMeshCommand(Lumix::WorldEditor& editor);
InsertMeshCommand(Lumix::WorldEditor& editor, const Lumix::Vec3& position, const Lumix::Path& mesh_path);
virtual void serialize(Lumix::JsonSerializer& serializer) override;
virtual void deserialize(Lumix::JsonSerializer& serializer) override;
virtual bool execute() override;
virtual void undo() override;
virtual Lumix::uint32 getType() override;
virtual bool merge(IEditorCommand&);
Lumix::Entity getEntity() const { return m_entity; }
private:
Lumix::Vec3 m_position;
Lumix::Path m_mesh_path;
Lumix::Entity m_entity;
Lumix::WorldEditor& m_editor;
};
static const Lumix::uint32 RENDERABLE_HASH = Lumix::crc32("renderable");
InsertMeshCommand::InsertMeshCommand(Lumix::WorldEditor& editor)
: m_editor(editor)
{
}
InsertMeshCommand::InsertMeshCommand(Lumix::WorldEditor& editor,
const Lumix::Vec3& position,
const Lumix::Path& mesh_path)
: m_mesh_path(mesh_path)
, m_position(position)
, m_editor(editor)
{
}
void InsertMeshCommand::serialize(Lumix::JsonSerializer& serializer)
{
serializer.serialize("path", m_mesh_path.c_str());
serializer.beginArray("pos");
serializer.serializeArrayItem(m_position.x);
serializer.serializeArrayItem(m_position.y);
serializer.serializeArrayItem(m_position.z);
serializer.endArray();
}
void InsertMeshCommand::deserialize(Lumix::JsonSerializer& serializer)
{
char path[Lumix::MAX_PATH_LENGTH];
serializer.deserialize("path", path, sizeof(path), "");
m_mesh_path = path;
serializer.deserializeArrayBegin("pos");
serializer.deserializeArrayItem(m_position.x, 0);
serializer.deserializeArrayItem(m_position.y, 0);
serializer.deserializeArrayItem(m_position.z, 0);
serializer.deserializeArrayEnd();
}
bool InsertMeshCommand::execute()
{
Lumix::Universe* universe = m_editor.getUniverse();
m_entity = universe->createEntity(Lumix::Vec3(0, 0, 0), Lumix::Quat(0, 0, 0, 1));
universe->setPosition(m_entity, m_position);
const Lumix::Array<Lumix::IScene*>& scenes = m_editor.getScenes();
Lumix::ComponentIndex cmp = -1;
Lumix::IScene* scene = nullptr;
for (int i = 0; i < scenes.size(); ++i)
{
cmp = scenes[i]->createComponent(RENDERABLE_HASH, m_entity);
if (cmp >= 0)
{
scene = scenes[i];
break;
}
}
if (cmp >= 0)
{
char rel_path[Lumix::MAX_PATH_LENGTH];
m_editor.getRelativePath(rel_path, Lumix::MAX_PATH_LENGTH, m_mesh_path.c_str());
static_cast<Lumix::RenderScene*>(scene)->setRenderablePath(cmp, rel_path);
}
return true;
}
void InsertMeshCommand::undo()
{
const Lumix::WorldEditor::ComponentList& cmps =
m_editor.getComponents(m_entity);
for (int i = 0; i < cmps.size(); ++i)
{
cmps[i].scene->destroyComponent(cmps[i].index, cmps[i].type);
}
m_editor.getUniverse()->destroyEntity(m_entity);
m_entity = Lumix::INVALID_ENTITY;
}
Lumix::uint32 InsertMeshCommand::getType()
{
static const Lumix::uint32 type = Lumix::crc32("insert_mesh");
return type;
}
bool InsertMeshCommand::merge(IEditorCommand&)
{
return false;
}
static void insertInScene(Lumix::WorldEditor& editor, Lumix::Model* model)
{
auto* command = LUMIX_NEW(editor.getAllocator(), InsertMeshCommand)(
editor, editor.getCameraRaycastHit(), model->getPath());
editor.executeCommand(command);
}
void AssetBrowser::onGUIModel()
{
auto* model = static_cast<Lumix::Model*>(m_selected_resource);
if (ImGui::Button("Insert in scene"))
{
insertInScene(m_editor, model);
}
ImGui::LabelText("Bone count", "%d", model->getBoneCount());
if (model->getBoneCount() > 0) ImGui::CollapsingHeader("Bones");
for (int i = 0; i < model->getBoneCount(); ++i)
{
ImGui::Text(model->getBone(i).name.c_str());
}
ImGui::LabelText("Bounding radius", "%f", model->getBoundingRadius());
auto& lods = model->getLODs();
if (!lods.empty())
{
ImGui::Separator();
ImGui::Columns(3);
ImGui::Text("LOD"); ImGui::NextColumn();
ImGui::Text("Distance"); ImGui::NextColumn();
ImGui::Text("# of meshes"); ImGui::NextColumn();
ImGui::Separator();
for (int i = 0; i < lods.size() - 1; ++i)
{
ImGui::Text("%d", i); ImGui::NextColumn();
ImGui::DragFloat("", &lods[i].m_distance); ImGui::NextColumn();
ImGui::Text("%d", lods[i].m_to_mesh - lods[i].m_from_mesh + 1); ImGui::NextColumn();
}
ImGui::Text("%d", lods.size() - 1); ImGui::NextColumn();
ImGui::Text("INFINITE"); ImGui::NextColumn();
ImGui::Text("%d", lods.back().m_to_mesh - lods.back().m_from_mesh + 1);
ImGui::Columns(1);
}
ImGui::Separator();
for (int i = 0; i < model->getMeshCount(); ++i)
{
auto& mesh = model->getMesh(i);
if (ImGui::TreeNode(&mesh, mesh.getName()[0] != 0 ? mesh.getName() : "N/A"))
{
ImGui::LabelText("Triangle count", "%d", mesh.getTriangleCount());
ImGui::LabelText("Material", mesh.getMaterial()->getPath().c_str());
ImGui::SameLine();
if (ImGui::Button("->"))
{
selectResource(mesh.getMaterial()->getPath());
}
ImGui::TreePop();
}
}
}
void AssetBrowser::onGUIResource()
{
if (!m_selected_resource) return;
const char* path = m_selected_resource->getPath().c_str();
ImGui::Separator();
ImGui::LabelText("Selected resource", path);
if (!m_history.empty() && ImGui::Button("Back"))
{
selectResource(m_history.back());
m_history.pop();
m_history.pop();
return;
}
ImGui::Separator();
if (!m_selected_resource->isReady() && !m_selected_resource->isFailure())
{
ImGui::Text("Not ready");
return;
}
char source[Lumix::MAX_PATH_LENGTH];
if (m_metadata.getString(
m_selected_resource->getPath().getHash(), SOURCE_HASH, source, Lumix::lengthOf(source)))
{
ImGui::LabelText("Source", source);
}
auto resource_type = getResourceType(path);
switch (resource_type)
{
case Lumix::ResourceManager::MATERIAL: onGUIMaterial(); break;
case Lumix::ResourceManager::TEXTURE: onGUITexture(); break;
case Lumix::ResourceManager::MODEL: onGUIModel(); break;
case Lumix::ResourceManager::SHADER: onGUIShader(); break;
default:
if (resource_type == LUA_SCRIPT_HASH)
{
onGUILuaScript();
}
else if (resource_type != UNIVERSE_HASH)
{
ASSERT(false); // unimplemented resource
}
break;
}
}
const Lumix::Array<Lumix::Path>& AssetBrowser::getResources(Type type) const
{
return m_resources[type];
}
void AssetBrowser::addResource(const char* path, const char* filename)
{
char ext[10];
Lumix::PathUtils::getExtension(ext, sizeof(ext), filename);
char fullpath[Lumix::MAX_PATH_LENGTH];
Lumix::copyString(fullpath, path);
Lumix::catString(fullpath, "/");
Lumix::catString(fullpath, filename);
int index = -1;
if (Lumix::compareString(ext, "dds") == 0 || Lumix::compareString(ext, "tga") == 0 || Lumix::compareString(ext, "raw") == 0) index = TEXTURE;
if (Lumix::compareString(ext, "msh") == 0) index = MODEL;
if (Lumix::compareString(ext, "mat") == 0) index = MATERIAL;
if (Lumix::compareString(ext, "unv") == 0) index = UNIVERSE;
if (Lumix::compareString(ext, "shd") == 0) index = SHADER;
if (Lumix::compareString(ext, "lua") == 0) index = LUA_SCRIPT;
if (Lumix::startsWith(path, "./render_tests") != 0 || Lumix::startsWith(path, "./unit_tests") != 0)
{
return;
}
if (index >= 0)
{
Lumix::Path path_obj(fullpath);
if (m_resources[index].indexOf(path_obj) == -1)
{
m_resources[index].push(path_obj);
}
}
}
void AssetBrowser::processDir(const char* dir)
{
auto* iter = PlatformInterface::createFileIterator(dir, m_editor.getAllocator());
PlatformInterface::FileInfo info;
while (getNextFile(iter, &info))
{
if (info.filename[0] == '.') continue;
if (info.is_directory)
{
char child_path[Lumix::MAX_PATH_LENGTH];
Lumix::copyString(child_path, dir);
Lumix::catString(child_path, "/");
Lumix::catString(child_path, info.filename);
processDir(child_path);
}
else
{
addResource(dir, info.filename);
}
}
destroyFileIterator(iter);
}
void AssetBrowser::findResources()
{
for (auto& resources : m_resources)
{
resources.clear();
}
processDir(".");
}