data packing fixes

This commit is contained in:
Mikulas Florek 2020-11-25 23:48:04 +01:00
parent 8753fe1ba0
commit e7116590df
12 changed files with 269 additions and 257 deletions

View file

@ -278,32 +278,25 @@ struct ControllerEditorImpl : ControllerEditor {
}
FileSystem& fs = m_app.getEngine().getFileSystem();
OS::InputFile file;
if (fs.open(path, Ref(file))) {
IAllocator& allocator = m_app.getAllocator();
IAllocator& allocator = m_app.getAllocator();
OutputMemoryStream data(allocator);
if (fs.getContentSync(Path(path), Ref(data))) {
ResourceManager* res_manager = m_app.getEngine().getResourceManager().get(Controller::TYPE);
Array<u8> data(allocator);
data.resize((u32)file.size());
if (!file.read(data.begin(), data.byte_size())) {
logError("Failed to read ", path);
InputMemoryStream str(data);
UniquePtr<Controller> new_controller = UniquePtr<Controller>::create(allocator, Path("anim_editor"), *res_manager, allocator);
if (new_controller->deserialize(str)) {
m_controller = new_controller.move();
m_current_node = m_controller->m_root;
m_path = path;
m_undo_stack.clear();
m_undo_idx = -1;
}
else {
InputMemoryStream str(data.begin(), data.byte_size());
UniquePtr<Controller> new_controller = UniquePtr<Controller>::create(allocator, Path("anim_editor"), *res_manager, allocator);
if (new_controller->deserialize(str)) {
m_controller = new_controller.move();
m_current_node = m_controller->m_root;
m_path = path;
m_undo_stack.clear();
m_undo_idx = -1;
}
pushUndo();
m_dirty = false;
}
file.close();
pushUndo();
m_dirty = false;
}
else {
logError("Failed to open ", path);
logError("Failed to read ", path);
}
}
@ -958,4 +951,4 @@ UniquePtr<ControllerEditor> ControllerEditor::create(StudioApp& app) {
return UniquePtr<ControllerEditorImpl>::create(app.getAllocator(), app);
}
} // ns Lumix::Anim
} // namespace Lumix::Anim

View file

@ -14,6 +14,7 @@
#include "engine/reflection.h"
#include "engine/thread.h"
#include "engine/universe.h"
#include "gui/gui_system.h"
#include "lua_script/lua_script_system.h"
#include "renderer/pipeline.h"
#include "renderer/render_scene.h"
@ -24,6 +25,17 @@ using namespace Lumix;
static const ComponentType ENVIRONMENT_TYPE = Reflection::getComponentType("environment");
static const ComponentType LUA_SCRIPT_TYPE = Reflection::getComponentType("lua_script");
struct GUIInterface : GUISystem::Interface {
Pipeline* getPipeline() override { return pipeline; }
Vec2 getPos() const override { return Vec2(0); }
Vec2 getSize() const override { return size; }
void setCursor(OS::CursorType type) override { OS::setCursor(type); }
void enableCursor(bool enable) override { OS::showCursor(enable); }
Vec2 size;
Pipeline* pipeline;
};
struct Runner final : OS::Interface
{
Runner()
@ -42,6 +54,7 @@ struct Runner final : OS::Interface
const OS::Rect r = OS::getWindowClientRect(m_engine->getWindowHandle());
m_viewport.w = r.width;
m_viewport.h = r.height;
m_gui_interface.size = Vec2((float)r.width, (float)r.height);
}
void initRenderPipeline() {
@ -83,16 +96,9 @@ struct Runner final : OS::Interface
}
bool loadUniverse(const char* path) {
OS::InputFile file;
if (!file.open(path)) return false;
FileSystem& fs = m_engine->getFileSystem();
OutputMemoryStream data(m_allocator);
data.resize(file.size());
if (!file.read(data.getMutableData(), data.size())) {
logError("Failed to read universes/main/entities.unv");
return false;
}
file.close();
if (!fs.getContentSync(Path(path), Ref(data))) return false;
InputMemoryStream tmp(data);
EntityMap entity_map(m_allocator);
@ -115,11 +121,20 @@ struct Runner final : OS::Interface
void onInit() override {
Engine::InitArgs init_data;
m_engine = Engine::create(init_data, m_allocator);
if (OS::fileExists("main.pak")) {
init_data.file_system = FileSystem::createPacked("main.pak", m_allocator);
}
m_engine = Engine::create(static_cast<Engine::InitArgs&&>(init_data), m_allocator);
m_universe = &m_engine->createUniverse(true);
initRenderPipeline();
auto* gui = static_cast<GUISystem*>(m_engine->getPluginManager().getPlugin("gui"));
m_gui_interface.pipeline = m_pipeline.get();
gui->setInterface(&m_gui_interface);
if (!loadUniverse("universes/main/entities.unv")) {
initDemoScene();
}
@ -137,6 +152,8 @@ struct Runner final : OS::Interface
void shutdown() {
m_shutting_down = true;
m_engine->destroyUniverse(*m_universe);
auto* gui = static_cast<GUISystem*>(m_engine->getPluginManager().getPlugin("gui"));
gui->setInterface(nullptr);
m_pipeline.reset();
m_engine.reset();
m_universe = nullptr;
@ -196,6 +213,7 @@ struct Runner final : OS::Interface
UniquePtr<Pipeline> m_pipeline;
Viewport m_viewport;
bool m_shutting_down = false;
GUIInterface m_gui_interface;
};
int main(int args, char* argv[])

View file

@ -295,90 +295,80 @@ struct AssetCompilerImpl : AssetCompiler
void onInitFinished() override
{
OS::InputFile file;
FileSystem& fs = m_app.getEngine().getFileSystem();
const StaticString<MAX_PATH_LENGTH> list_path(fs.getBasePath(), ".lumix/assets/_list.txt");
if (fs.open(".lumix/assets/_list.txt", Ref(file))) {
Array<char> content(m_app.getAllocator());
content.resize((int)file.size());
if (!file.read(content.begin(), content.byte_size())) {
logError("Failed to read .lumix/assets/_list.txt");
file.close();
}
else {
file.close();
OutputMemoryStream content(m_app.getAllocator());
if (fs.getContentSync(Path(".lumix/assets/_list.txt"), Ref(content))) {
lua_State* L = luaL_newstate();
[&](){
if (luaL_loadbuffer(L, (const char*)content.data(), content.size(), "lumix_asset_list") != 0) {
logError(list_path, ": ", lua_tostring(L, -1));
return;
}
lua_State* L = luaL_newstate();
[&](){
if (luaL_loadbuffer(L, content.begin(), content.byte_size(), "lumix_asset_list") != 0) {
logError(list_path, ": ", lua_tostring(L, -1));
return;
}
if (lua_pcall(L, 0, 0, 0) != 0) {
logError(list_path, ": ", lua_tostring(L, -1));
return;
}
if (lua_pcall(L, 0, 0, 0) != 0) {
logError(list_path, ": ", lua_tostring(L, -1));
return;
}
lua_getglobal(L, "resources");
if (lua_type(L, -1) != LUA_TTABLE) return;
lua_getglobal(L, "resources");
if (lua_type(L, -1) != LUA_TTABLE) return;
{
MutexGuard lock(m_resources_mutex);
LuaWrapper::forEachArrayItem<Path>(L, -1, "array of strings expected", [this, &fs](const Path& p){
const ResourceType type = getResourceType(p.c_str());
#ifdef CACHE_MASTER
StaticString<MAX_PATH_LENGTH> res_path(".lumix/assets/", p.getHash(), ".res");
if (type != INVALID_RESOURCE_TYPE && fs.fileExists(res_path)) {
{
MutexGuard lock(m_resources_mutex);
LuaWrapper::forEachArrayItem<Path>(L, -1, "array of strings expected", [this, &fs](const Path& p){
const ResourceType type = getResourceType(p.c_str());
#ifdef CACHE_MASTER
StaticString<MAX_PATH_LENGTH> res_path(".lumix/assets/", p.getHash(), ".res");
if (type != INVALID_RESOURCE_TYPE && fs.fileExists(res_path)) {
m_resources.insert(p.getHash(), {p, type, dirHash(p.c_str())});
}
#else
if (type != INVALID_RESOURCE_TYPE) {
ResourceLocator locator(Span<const char>(p.c_str(), (u32)strlen(p.c_str())));
char tmp[MAX_PATH_LENGTH];
copyString(Span(tmp), locator.resource);
if (fs.fileExists(tmp)) {
m_resources.insert(p.getHash(), {p, type, dirHash(p.c_str())});
}
#else
if (type != INVALID_RESOURCE_TYPE) {
ResourceLocator locator(Span<const char>(p.c_str(), (u32)strlen(p.c_str())));
char tmp[MAX_PATH_LENGTH];
copyString(Span(tmp), locator.resource);
if (fs.fileExists(tmp)) {
m_resources.insert(p.getHash(), {p, type, dirHash(p.c_str())});
}
else {
StaticString<MAX_PATH_LENGTH> res_path(".lumix/assets/", p.getHash(), ".res");
fs.deleteFile(res_path);
}
else {
StaticString<MAX_PATH_LENGTH> res_path(".lumix/assets/", p.getHash(), ".res");
fs.deleteFile(res_path);
}
#endif
});
}
lua_pop(L, 1);
}
#endif
});
}
lua_pop(L, 1);
lua_getglobal(L, "dependencies");
if (lua_type(L, -1) != LUA_TTABLE) return;
lua_pushnil(L);
while (lua_next(L, -2) != 0) {
if (!lua_isstring(L, -2) || !lua_istable(L, -1)) {
logError("Invalid dependencies in _list.txt");
lua_pop(L, 1);
continue;
}
const char* key = lua_tostring(L, -2);
IAllocator& allocator = m_app.getAllocator();
const Path key_path(key);
m_dependencies.insert(key_path, Array<Path>(allocator));
Array<Path>& values = m_dependencies.find(key_path).value();
LuaWrapper::forEachArrayItem<Path>(L, -1, "array of strings expected", [&values](const Path& p){
values.push(p);
});
lua_getglobal(L, "dependencies");
if (lua_type(L, -1) != LUA_TTABLE) return;
lua_pushnil(L);
while (lua_next(L, -2) != 0) {
if (!lua_isstring(L, -2) || !lua_istable(L, -1)) {
logError("Invalid dependencies in _list.txt");
lua_pop(L, 1);
continue;
}
lua_pop(L, 1);
const char* key = lua_tostring(L, -2);
IAllocator& allocator = m_app.getAllocator();
const Path key_path(key);
m_dependencies.insert(key_path, Array<Path>(allocator));
Array<Path>& values = m_dependencies.find(key_path).value();
}();
LuaWrapper::forEachArrayItem<Path>(L, -1, "array of strings expected", [&values](const Path& p){
values.push(p);
});
lua_pop(L, 1);
}
lua_pop(L, 1);
}();
lua_close(L);
}
lua_close(L);
}
const u64 list_last_modified = OS::getLastModified(list_path);
@ -415,7 +405,6 @@ struct AssetCompilerImpl : AssetCompiler
}
}
void onFileChanged(const char* path)
{
if (startsWith(path, ".lumix")) return;
@ -427,22 +416,15 @@ struct AssetCompilerImpl : AssetCompiler
bool getMeta(const Path& res, void* user_ptr, void (*callback)(void*, lua_State*)) const override
{
OS::InputFile file;
const StaticString<MAX_PATH_LENGTH> meta_path(res.c_str(), ".meta");
FileSystem& fs = m_app.getEngine().getFileSystem();
if (!fs.open(meta_path, Ref(file))) return false;
Array<char> buf(m_app.getAllocator());
buf.resize((int)file.size());
const bool read_all = file.read(buf.begin(), buf.byte_size());
file.close();
if (!read_all) {
return false;
}
OutputMemoryStream buf(m_app.getAllocator());
if (!fs.getContentSync(Path(meta_path), Ref(buf))) return false;
lua_State* L = luaL_newstate();
if (luaL_loadbuffer(L, buf.begin(), buf.byte_size(), meta_path) != 0) {
if (luaL_loadbuffer(L, (const char*)buf.data(), buf.size(), meta_path) != 0) {
logError(meta_path, ": ", lua_tostring(L, -1));
lua_close(L);
return false;

View file

@ -316,7 +316,6 @@ Settings::~Settings()
bool Settings::load()
{
auto L = m_state;
OS::InputFile file;
FileSystem& fs = m_app.getEngine().getFileSystem();
const bool has_settings = fs.fileExists(SETTINGS_PATH);
const char* path = has_settings ? SETTINGS_PATH : DEFAULT_SETTINGS_PATH;

View file

@ -371,7 +371,7 @@ struct StudioAppImpl final : StudioApp
init_data.handle_file_drops = true;
init_data.window_title = "Lumix Studio";
init_data.working_dir = data_dir[0] ? data_dir : (saved_data_dir[0] ? saved_data_dir : current_dir);
m_engine = Engine::create(init_data, m_allocator);
m_engine = Engine::create(static_cast<Engine::InitArgs&&>(init_data), m_allocator);
m_main_window = m_engine->getWindowHandle();
m_windows.push(m_main_window);
@ -2826,36 +2826,24 @@ struct StudioAppImpl final : StudioApp
}
void checkScriptCommandLine()
{
void checkScriptCommandLine() {
char command_line[1024];
OS::getCommandLine(Span(command_line));
CommandLineParser parser(command_line);
while (parser.next())
{
if (parser.currentEquals("-run_script"))
{
while (parser.next()) {
if (parser.currentEquals("-run_script")) {
if (!parser.next()) break;
char tmp[MAX_PATH_LENGTH];
parser.getCurrent(tmp, lengthOf(tmp));
OS::InputFile file;
if (m_engine->getFileSystem().open(tmp, Ref(file)))
{
auto size = file.size();
auto* src = (char*)m_allocator.allocate(size + 1);
if (file.read(src, size)) {
src[size] = 0;
runScript((const char*)src, tmp);
m_allocator.deallocate(src);
}
else {
logError("Could not read ", tmp);
}
file.close();
OutputMemoryStream content(m_allocator);
if (m_engine->getFileSystem().getContentSync(Path(tmp), Ref(content))) {
content.write('\0');
runScript((const char*)content.data(), tmp);
}
else
{
logError("Could not open ", tmp);
else {
logError("Could not read ", tmp);
}
break;
}
@ -2868,7 +2856,7 @@ struct StudioAppImpl final : StudioApp
if (filename[0] == '.') return false;
if (compareStringN("bin/", filename, 4) == 0) return false;
if (compareStringN("bin32/", filename, 4) == 0) return false;
if (equalStrings("data.pak", filename)) return false;
if (equalStrings("main.pak", filename)) return false;
if (equalStrings("error.log", filename)) return false;
return true;
}
@ -2883,7 +2871,6 @@ struct StudioAppImpl final : StudioApp
}
#pragma pack(1)
struct PackFileInfo
{
u32 hash;
@ -2892,12 +2879,35 @@ struct StudioAppImpl final : StudioApp
char path[MAX_PATH_LENGTH];
};
#pragma pack()
void scanCompiled(AssociativeArray<u32, PackFileInfo>& infos) {
OS::FileIterator* iter = m_engine->getFileSystem().createFileIterator(".lumix/assets");
const char* base_path = m_engine->getFileSystem().getBasePath();
OS::FileInfo info;
while (OS::getNextFile(iter, &info)) {
if (info.is_directory) continue;
char basename[MAX_PATH_LENGTH];
Path::getBasename(Span(basename), info.filename);
PackFileInfo rec;
fromCString(Span(basename), Ref(rec.hash));
rec.offset = 0;
rec.size = OS::getFileSize(StaticString<MAX_PATH_LENGTH>(base_path, ".lumix/assets/", info.filename));
copyString(rec.path, ".lumix/assets/");
catString(rec.path, info.filename);
infos.insert(rec.hash, rec);
}
OS::destroyFileIterator(iter);
packDataScan("pipelines/", infos);
packDataScan("universes/", infos);
}
void packDataScan(const char* dir_path, AssociativeArray<u32, PackFileInfo>& infos)
{
auto* iter = m_engine->getFileSystem().createFileIterator(dir_path);
const char* base_path = m_engine->getFileSystem().getBasePath();
OS::FileInfo info;
while (OS::getNextFile(iter, &info))
{
@ -2933,7 +2943,7 @@ struct StudioAppImpl final : StudioApp
auto& out_info = infos.emplace(hash);
copyString(out_info.path, out_path);
out_info.hash = hash;
out_info.size = OS::getFileSize(out_path.data);
out_info.size = OS::getFileSize(StaticString<MAX_PATH_LENGTH>(base_path, out_path.data));
out_info.offset = ~0UL;
}
OS::destroyFileIterator(iter);
@ -2977,19 +2987,16 @@ struct StudioAppImpl final : StudioApp
void onPackDataGUI()
{
if (!m_is_pack_data_dialog_open) return;
if (ImGui::Begin("Pack data", &m_is_pack_data_dialog_open))
{
ImGui::LabelText("Destination dir", "%s", m_pack.dest_dir.data);
ImGui::SameLine();
if (ImGui::Button("Choose dir"))
{
if (OS::getOpenDirectory(Span(m_pack.dest_dir.data), m_engine->getFileSystem().getBasePath()))
{
m_pack.dest_dir << "/";
if (ImGui::Begin("Pack data", &m_is_pack_data_dialog_open)) {
ImGuiEx::Label("Destination dir");
if (ImGui::Button(m_pack.dest_dir.empty() ? "..." : m_pack.dest_dir.data)) {
if (OS::getOpenDirectory(Span(m_pack.dest_dir.data), m_engine->getFileSystem().getBasePath())) {
m_pack.dest_dir;
}
}
ImGui::Combo("Mode", (int*)&m_pack.mode, "All files\0Loaded universe\0");
ImGuiEx::Label("Mode");
ImGui::Combo("##mode", (int*)&m_pack.mode, "All files\0Loaded universe\0");
if (ImGui::Button("Pack")) packData();
}
@ -2997,58 +3004,51 @@ struct StudioAppImpl final : StudioApp
}
void packData()
{
void packData() {
if (m_pack.dest_dir.empty()) return;
char dest[MAX_PATH_LENGTH];
static const char* OUT_FILENAME = "data.pak";
static const char* OUT_FILENAME = "main.pak";
copyString(dest, m_pack.dest_dir);
catString(dest, OUT_FILENAME);
AssociativeArray<u32, PackFileInfo> infos(m_allocator);
infos.reserve(10000);
switch (m_pack.mode)
{
case PackConfig::Mode::ALL_FILES: packDataScan("./", infos); break;
switch (m_pack.mode) {
case PackConfig::Mode::ALL_FILES: scanCompiled(infos); break;
case PackConfig::Mode::CURRENT_UNIVERSE: packDataScanResources(infos); break;
default: ASSERT(false); break;
}
if (infos.size() == 0)
{
if (infos.size() == 0) {
logError("No files found while trying to create ", dest);
return;
}
bool success;
OS::OutputFile file;
if (!file.open(dest))
{
if (!file.open(dest)) {
logError("Could not create ", dest);
return;
}
int count = infos.size();
const u32 count = (u32)infos.size();
success = file.write(&count, sizeof(count));
u64 offset = sizeof(count) + (sizeof(u32) + sizeof(u64) * 2) * count;
for (auto& info : infos)
{
for (auto& info : infos) {
info.offset = offset;
offset += info.size;
}
for (auto& info : infos)
{
success = success || file.write(&info.hash, sizeof(info.hash));
success = success || file.write(&info.offset, sizeof(info.offset));
success = success || file.write(&info.size, sizeof(info.size));
for (auto& info : infos) {
success = file.write(&info.hash, sizeof(info.hash)) || success;
success = file.write(&info.offset, sizeof(info.offset)) || success;
success = file.write(&info.size, sizeof(info.size)) || success;
}
FileSystem& fs = m_engine->getFileSystem();
for (auto& info : infos)
{
for (auto& info : infos) {
OS::InputFile src;
if (!fs.open(info.path, Ref(src))) {
file.close();
@ -3078,36 +3078,32 @@ struct StudioAppImpl final : StudioApp
const char* bin_files[] = {"app.exe", "dbghelp.dll", "dbgcore.dll"};
StaticString<MAX_PATH_LENGTH> src_dir("bin/");
if (!OS::fileExists("bin/app.exe"))
{
if (!OS::fileExists("bin/app.exe")) {
char tmp[MAX_PATH_LENGTH];
OS::getExecutablePath(Span(tmp));
Path::getDir(Span(src_dir.data), tmp);
}
for (auto& file : bin_files)
{
for (auto& file : bin_files) {
StaticString<MAX_PATH_LENGTH> tmp(m_pack.dest_dir, file);
StaticString<MAX_PATH_LENGTH> src(src_dir, file);
if (!OS::copyFile(src, tmp))
{
if (!OS::copyFile(src, tmp)) {
logError("Failed to copy ", src, " to ", tmp);
}
}
for (GUIPlugin* plugin : m_gui_plugins)
{
if (!plugin->packData(m_pack.dest_dir))
{
for (GUIPlugin* plugin : m_gui_plugins) {
if (!plugin->packData(m_pack.dest_dir)) {
logError("Plugin ", plugin->getName(), " failed to pack data.");
}
}
logInfo("Packing finished.");
}
void loadLuaPlugin(const char* dir, const char* filename)
{
StaticString<MAX_PATH_LENGTH> path(dir, filename);
OS::InputFile file;
OutputMemoryStream src(m_engine->getAllocator());
if (m_engine->getFileSystem().getContentSync(Path(path), Ref(src))) {

View file

@ -2204,29 +2204,11 @@ public:
}
bool loadProject() override {
const char* base_path = m_engine.getFileSystem().getBasePath();
const StaticString<MAX_PATH_LENGTH> path(base_path, "lumix.prj");
OS::InputFile file;
if (file.open(path)) {
const u64 size = file.size();
if (size < 8) {
logError("Invalid file ", path);
file.close();
return false;
}
OutputMemoryStream data(m_allocator);
data.resize((u32)size);
if (!file.read(data.getMutableData(), data.size())) {
logError("Failed to read ", path);
file.close();
return false;
}
InputMemoryStream stream(data);
bool res = m_engine.deserializeProject(stream);
file.close();
return res;
}
return false;
OutputMemoryStream data(m_allocator);
if (!m_engine.getFileSystem().getContentSync(Path("lumix.prj"), Ref(data))) return false;
InputMemoryStream stream(data);
return m_engine.deserializeProject(stream);
}
void loadUniverse(const char* basename) override

View file

@ -66,7 +66,7 @@ public:
void operator=(const EngineImpl&) = delete;
EngineImpl(const EngineImpl&) = delete;
EngineImpl(const InitArgs& init_data, IAllocator& allocator)
EngineImpl(InitArgs&& init_data, IAllocator& allocator)
: m_allocator(allocator)
, m_prefab_resource_manager(m_allocator)
, m_resource_manager(m_allocator)
@ -104,7 +104,10 @@ public:
registerEngineAPI(m_state, this);
if (init_data.working_dir) {
if (init_data.file_system.get()) {
m_file_system = static_cast<UniquePtr<FileSystem>&&>(init_data.file_system);
}
else if (init_data.working_dir) {
m_file_system = FileSystem::create(init_data.working_dir, m_allocator);
}
else {
@ -541,9 +544,9 @@ private:
};
UniquePtr<Engine> Engine::create(const InitArgs& init_data, IAllocator& allocator)
UniquePtr<Engine> Engine::create(InitArgs&& init_data, IAllocator& allocator)
{
return UniquePtr<EngineImpl>::create(allocator, init_data, allocator);
return UniquePtr<EngineImpl>::create(allocator, static_cast<InitArgs&&>(init_data), allocator);
}

View file

@ -1,6 +1,7 @@
#pragma once
#include "engine/lumix.h"
#include "engine/allocator.h"
struct lua_State;
@ -9,6 +10,7 @@ namespace Lumix
namespace OS { using WindowHandle = void*; }
template <typename T> struct UniquePtr;
struct FileSystem;
struct LUMIX_ENGINE_API Engine
{
@ -19,6 +21,7 @@ public:
bool fullscreen = false;
bool handle_file_drops = false;
const char* window_title = "Lumix App";
UniquePtr<FileSystem> file_system;
};
using LuaResourceHandle = u32;
@ -26,7 +29,7 @@ public:
public:
virtual ~Engine() {}
static UniquePtr<Engine> create(const InitArgs& init_data, struct IAllocator& allocator);
static UniquePtr<Engine> create(InitArgs&& init_data, struct IAllocator& allocator);
virtual struct Universe& createUniverse(bool is_main_universe) = 0;
virtual void destroyUniverse(Universe& context) = 0;

View file

@ -17,12 +17,9 @@
#include "engine/stream.h"
#include "engine/string.h"
namespace Lumix
{
namespace Lumix {
struct AsyncItem
{
struct AsyncItem {
enum class Flags : u32 {
FAILED = 1 << 0,
CANCELED = 1 << 1,
@ -44,19 +41,14 @@ struct AsyncItem
struct FileSystemImpl;
struct FSTask final : Thread
{
public:
struct FSTask final : Thread {
FSTask(FileSystemImpl& fs, IAllocator& allocator)
: Thread(allocator)
, m_fs(fs)
{
}
{}
~FSTask() = default;
void stop();
int task() override;
@ -66,8 +58,7 @@ private:
};
struct FileSystemImpl final : FileSystem
{
struct FileSystemImpl : FileSystem {
explicit FileSystemImpl(const char* base_path, IAllocator& allocator)
: m_allocator(allocator)
, m_queue(allocator)
@ -76,16 +67,14 @@ struct FileSystemImpl final : FileSystem
, m_semaphore(0, 0xffFF)
{
setBasePath(base_path);
m_task = LUMIX_NEW(m_allocator, FSTask)(*this, m_allocator);
m_task.create(*this, m_allocator);
m_task->create("Filesystem", true);
}
~FileSystemImpl()
{
~FileSystemImpl() override {
m_task->stop();
m_task->destroy();
LUMIX_DELETE(m_allocator, m_task);
m_task.destroy();
}
@ -116,6 +105,7 @@ struct FileSystemImpl final : FileSystem
content->resize((int)file.size());
if (!file.read(content->getMutableData(), content->size())) {
logError("Could not read ", path);
file.close();
return false;
}
@ -264,7 +254,7 @@ struct FileSystemImpl final : FileSystem
}
IAllocator& m_allocator;
FSTask* m_task;
Local<FSTask> m_task;
StaticString<MAX_PATH_LENGTH> m_base_path;
Array<AsyncItem> m_queue;
Array<AsyncItem> m_finished;
@ -292,23 +282,8 @@ int FSTask::task()
}
}
bool success = true;
OutputMemoryStream data(m_fs.m_allocator);
OS::InputFile file;
StaticString<MAX_PATH_LENGTH> full_path(m_fs.m_base_path, path);
if (file.open(full_path)) {
data.resize((int)file.size());
if (!file.read(data.getMutableData(), data.size())) {
success = false;
}
file.close();
}
else {
success = false;
}
bool success = m_fs.getContentSync(Path(path), Ref(data));
{
MutexGuard lock(m_fs.m_mutex);
@ -332,11 +307,69 @@ void FSTask::stop()
m_fs.m_semaphore.signal();
}
struct PackFileSystem : FileSystemImpl {
PackFileSystem(const char* pak_path, IAllocator& allocator)
: FileSystemImpl("pack://", allocator)
, m_map(allocator)
{
if (!m_file.open(pak_path)) {
logError("Failed to open game.pak");
return;
}
const u32 count = m_file.read<u32>();
for (u32 i = 0; i < count; ++i) {
const u32 hash = m_file.read<u32>();
PackFile& f = m_map.insert(hash);
f.offset = m_file.read<u64>();
f.size = m_file.read<u64>();
}
}
~PackFileSystem() {
m_file.close();
}
bool getContentSync(const Path& path, Ref<OutputMemoryStream> content) override {
char basename[MAX_PATH_LENGTH];
Path::getBasename(Span(basename), path.c_str());
u32 hash;
fromCString(Span(basename), Ref(hash));
if (basename[0] < '0' || basename[0] > '9' || hash == 0) {
hash = path.getHash();
}
auto iter = m_map.find(hash);
if (!iter.isValid()) return false;
content->resize(iter.value().size);
MutexGuard lock(m_mutex);
if (!m_file.seek(iter.value().offset) || !m_file.read(content->getMutableData(), content->size())) {
logError("Could not read ", path);
return false;
}
return true;
}
struct PackFile {
u64 offset;
u64 size;
};
HashMap<u32, PackFile> m_map;
Mutex m_mutex;
OS::InputFile m_file;
};
UniquePtr<FileSystem> FileSystem::create(const char* base_path, IAllocator& allocator)
{
return UniquePtr<FileSystemImpl>::create(allocator, base_path, allocator);
}
UniquePtr<FileSystem> FileSystem::createPacked(const char* pak_path, IAllocator& allocator)
{
return UniquePtr<PackFileSystem>::create(allocator, pak_path, allocator);
}
} // namespace Lumix

View file

@ -28,6 +28,7 @@ struct LUMIX_ENGINE_API FileSystem
};
static UniquePtr<FileSystem> create(const char* base_path, struct IAllocator& allocator);
static UniquePtr<FileSystem> createPacked(const char* pak_path, struct IAllocator& allocator);
virtual ~FileSystem() {}

View file

@ -333,11 +333,10 @@ struct PhysicsUIPlugin final : StudioApp::GUIPlugin
char exe_dir[MAX_PATH_LENGTH];
const char* physx_dlls[] = {
"nvToolsExt64_1.dll",
"PhysX3CharacterKinematicCHECKED_x64.dll",
"PhysX3CHECKED_x64.dll",
"PhysX3CommonCHECKED_x64.dll",
"PhysX3CookingCHECKED_x64.dll",
"PhysX_64.dll",
"PhysXFoundation_64.dll",
"PhysXCommon_64.dll",
"PhysXCooking_64.dll",
};
for (const char* dll : physx_dlls)
{
@ -945,7 +944,7 @@ struct StudioAppPlugin : StudioApp::IPlugin
void init() override
{
m_app.registerComponent("", "distance_joint", "Physics / Joints/Distance");
m_app.registerComponent("", "distance_joint", "Physics / Joints / Distance");
m_app.registerComponent("", "hinge_joint", "Physics / Joints / Hinge");
m_app.registerComponent("", "spherical_joint", "Physics / Joints / Spherical");
m_app.registerComponent("", "d6_joint", "Physics / Joints / D6");

View file

@ -1539,7 +1539,8 @@ struct ParticleEditorImpl : ParticleEditor {
ASSERT(emitter);
const Path& path = emitter->getResource()->getPath();
load(path.c_str());
FileSystem& fs = m_app.getEngine().getFileSystem();
load(StaticString<MAX_PATH_LENGTH>(fs.getBasePath(), path.c_str()));
}
void load(const char* path) {
@ -1637,7 +1638,9 @@ struct ParticleEditorImpl : ParticleEditor {
m_confirm_load_path = path;
return;
}
load(path);
FileSystem& fs = m_app.getEngine().getFileSystem();
load(StaticString<MAX_PATH_LENGTH>(fs.getBasePath(), path));
}
bool compile(InputMemoryStream& input, OutputMemoryStream& output, const char* path) override {