data packing fixes
This commit is contained in:
parent
8753fe1ba0
commit
e7116590df
12 changed files with 269 additions and 257 deletions
|
@ -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
|
|
@ -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[])
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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))) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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() {}
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue