From e9fbc9c2056a433cfe49dc99c4f89462ceb6fdbd Mon Sep 17 00:00:00 2001 From: Turanszki Janos Date: Sun, 10 May 2020 20:23:49 +0100 Subject: [PATCH] file operation updates for uwp platform #110 --- Editor/ModelImporter_GLTF.cpp | 96 ++++++++- Editor/ModelImporter_OBJ.cpp | 74 ++++++- WickedEngine/MainComponent.cpp | 2 + WickedEngine/wiArchive.cpp | 23 +- WickedEngine/wiAudio.cpp | 100 +++------ WickedEngine/wiAudio.h | 2 + WickedEngine/wiBackLog.cpp | 2 +- WickedEngine/wiFont.cpp | 2 +- WickedEngine/wiHelper.cpp | 329 +++++++++++++++++++++++++---- WickedEngine/wiHelper.h | 12 +- WickedEngine/wiLua.cpp | 43 +++- WickedEngine/wiPlatform.h | 29 +++ WickedEngine/wiRenderer.cpp | 2 +- WickedEngine/wiResourceManager.cpp | 12 +- WickedEngine/wiVersion.cpp | 2 +- 15 files changed, 577 insertions(+), 153 deletions(-) diff --git a/Editor/ModelImporter_GLTF.cpp b/Editor/ModelImporter_GLTF.cpp index a502d7637..37c4bb5db 100644 --- a/Editor/ModelImporter_GLTF.cpp +++ b/Editor/ModelImporter_GLTF.cpp @@ -6,6 +6,7 @@ #include "Utility/stb_image.h" #define TINYGLTF_IMPLEMENTATION +#define TINYGLTF_NO_FS #define TINYGLTF_NO_STB_IMAGE #define TINYGLTF_NO_STB_IMAGE_WRITE #include "tiny_gltf.h" @@ -26,6 +27,69 @@ static const bool transform_to_LH = true; namespace tinygltf { + + bool FileExists(const std::string& abs_filename, void*) { + return wiHelper::FileExists(abs_filename); + } + + std::string ExpandFilePath(const std::string& filepath, void*) { +#ifdef _WIN32 + DWORD len = ExpandEnvironmentStringsA(filepath.c_str(), NULL, 0); + char* str = new char[len]; + ExpandEnvironmentStringsA(filepath.c_str(), str, len); + + std::string s(str); + + delete[] str; + + return s; +#else + +#if defined(TARGET_OS_IPHONE) || defined(TARGET_IPHONE_SIMULATOR) || \ + defined(__ANDROID__) || defined(__EMSCRIPTEN__) + // no expansion + std::string s = filepath; +#else + std::string s; + wordexp_t p; + + if (filepath.empty()) { + return ""; + } + + // char** w; + int ret = wordexp(filepath.c_str(), &p, 0); + if (ret) { + // err + s = filepath; + return s; + } + + // Use first element only. + if (p.we_wordv) { + s = std::string(p.we_wordv[0]); + wordfree(&p); + } + else { + s = filepath; + } + +#endif + + return s; +#endif + } + + bool ReadWholeFile(std::vector* out, std::string* err, + const std::string& filepath, void*) { + return wiHelper::FileRead(filepath, *out); + } + + bool WriteWholeFile(std::string* err, const std::string& filepath, + const std::vector& contents, void*) { + return wiHelper::FileWrite(filepath, contents.data(), contents.size()); + } + bool LoadImageData(Image *image, const int image_idx, std::string *err, std::string *warn, int req_width, int req_height, const unsigned char *bytes, int size, void *) @@ -297,6 +361,14 @@ void ImportModel_GLTF(const std::string& fileName, Scene& scene) tinygltf::TinyGLTF loader; std::string err; std::string warn; + bool ret; + + tinygltf::FsCallbacks callbacks; + callbacks.ReadWholeFile = tinygltf::ReadWholeFile; + callbacks.WriteWholeFile = tinygltf::WriteWholeFile; + callbacks.FileExists = tinygltf::FileExists; + callbacks.ExpandFilePath = tinygltf::ExpandFilePath; + loader.SetFsCallbacks(callbacks); loader.SetImageLoader(tinygltf::LoadImageData, nullptr); loader.SetImageWriter(tinygltf::WriteImageData, nullptr); @@ -304,15 +376,31 @@ void ImportModel_GLTF(const std::string& fileName, Scene& scene) LoaderState state; state.scene = &scene; - bool ret; - if (!extension.compare("GLTF")) + std::vector filedata; + ret = wiHelper::FileRead(fileName, filedata); + + if (ret) { - ret = loader.LoadASCIIFromFile(&state.gltfModel, &err, &warn, fileName); + std::string basedir = tinygltf::GetBaseDir(fileName); + + if (!extension.compare("GLTF")) + { + ret = loader.LoadASCIIFromString(&state.gltfModel, &err, &warn, + reinterpret_cast(&filedata.at(0)), + static_cast(filedata.size()), basedir); + } + else + { + ret = loader.LoadBinaryFromMemory(&state.gltfModel, &err, &warn, + filedata.data(), + static_cast(filedata.size()), basedir); + } } else { - ret = loader.LoadBinaryFromFile(&state.gltfModel, &err, &warn, fileName); // for binary glTF(.glb) + err = "Failed to read file: " + fileName; } + if (!ret) { wiHelper::messageBox(err, "GLTF error!"); } diff --git a/Editor/ModelImporter_OBJ.cpp b/Editor/ModelImporter_OBJ.cpp index 046e74871..742d29327 100644 --- a/Editor/ModelImporter_OBJ.cpp +++ b/Editor/ModelImporter_OBJ.cpp @@ -5,13 +5,70 @@ #define TINYOBJLOADER_IMPLEMENTATION #include "tiny_obj_loader.h" -#include +#include +#include using namespace std; using namespace wiGraphics; using namespace wiScene; using namespace wiECS; +struct membuf : std::streambuf +{ + membuf(char* begin, char* end) { + this->setg(begin, begin, end); + } +}; + +// Custom material file reader: +class MaterialFileReader : public tinyobj::MaterialReader { +public: + explicit MaterialFileReader(const std::string& mtl_basedir) + : m_mtlBaseDir(mtl_basedir) {} + virtual ~MaterialFileReader() {} + virtual bool operator()(const std::string& matId, + std::vector* materials, + std::map* matMap, std::string* err) + { + std::string filepath; + + if (!m_mtlBaseDir.empty()) { + filepath = std::string(m_mtlBaseDir) + matId; + } + else { + filepath = matId; + } + + std::vector filedata; + if (!wiHelper::FileRead(filepath, filedata)) + { + std::stringstream ss; + ss << "WARN: Material file [ " << filepath << " ] not found." << std::endl; + if (err) { + (*err) += ss.str(); + } + return false; + } + + membuf sbuf((char*)filedata.data(), (char*)filedata.data() + filedata.size()); + std::istream matIStream(&sbuf); + + std::string warning; + LoadMtl(matMap, materials, &matIStream, &warning); + + if (!warning.empty()) { + if (err) { + (*err) += warning; + } + } + + return true; + } + +private: + std::string m_mtlBaseDir; +}; + // Transform the data from OBJ space to engine-space: static const bool transform_to_LH = true; @@ -26,7 +83,20 @@ void ImportModel_OBJ(const std::string& fileName, Scene& scene) vector obj_materials; string obj_errors; - bool success = tinyobj::LoadObj(&obj_attrib, &obj_shapes, &obj_materials, &obj_errors, fileName.c_str(), directory.c_str(), true); + std::vector filedata; + bool success = wiHelper::FileRead(fileName, filedata); + + if (success) + { + membuf sbuf((char*)filedata.data(), (char*)filedata.data() + filedata.size()); + std::istream in(&sbuf); + MaterialFileReader matFileReader(directory); + success = tinyobj::LoadObj(&obj_attrib, &obj_shapes, &obj_materials, &obj_errors, &in, &matFileReader, true); + } + else + { + obj_errors = "Failed to read file: " + fileName; + } if (!obj_errors.empty()) { diff --git a/WickedEngine/MainComponent.cpp b/WickedEngine/MainComponent.cpp index 8efab7e3c..aba3111c0 100644 --- a/WickedEngine/MainComponent.cpp +++ b/WickedEngine/MainComponent.cpp @@ -121,6 +121,8 @@ void MainComponent::Run() wiLua::GetGlobal()->RunFile("startup.lua"); } + wiPlatform::PopMessages(); + wiProfiler::BeginFrame(); deltaTime = float(std::max(0.0, timer.elapsed() / 1000.0)); diff --git a/WickedEngine/wiArchive.cpp b/WickedEngine/wiArchive.cpp index 636e653a3..2b0381c32 100644 --- a/WickedEngine/wiArchive.cpp +++ b/WickedEngine/wiArchive.cpp @@ -23,14 +23,8 @@ wiArchive::wiArchive(const std::string& fileName, bool readMode) : fileName(file { if (readMode) { - ifstream file(fileName, ios::binary | ios::ate); - if (file.is_open()) + if (wiHelper::FileRead(fileName, DATA)) { - size_t dataSize = (size_t)file.tellg(); - file.seekg(0, file.beg); - DATA.resize((size_t)dataSize); - file.read((char*)DATA.data(), dataSize); - file.close(); (*this) >> version; if (version < __archiveVersionBarrier) { @@ -98,20 +92,7 @@ void wiArchive::Close() bool wiArchive::SaveFile(const std::string& fileName) { - if (pos <= 0) - { - return false; - } - - ofstream file(fileName, ios::binary | ios::trunc); - if (file.is_open()) - { - file.write((const char*)DATA.data(), (streamsize)pos); - file.close(); - return true; - } - - return false; + return wiHelper::FileWrite(fileName, DATA.data(), pos); } string wiArchive::GetSourceDirectory() const diff --git a/WickedEngine/wiAudio.cpp b/WickedEngine/wiAudio.cpp index 486de539a..ac4b4f9d7 100644 --- a/WickedEngine/wiAudio.cpp +++ b/WickedEngine/wiAudio.cpp @@ -196,11 +196,9 @@ namespace wiAudio } } - HRESULT FindChunk(HANDLE hFile, DWORD fourcc, DWORD& dwChunkSize, DWORD& dwChunkDataPosition) + bool FindChunk(const uint8_t* data, DWORD fourcc, DWORD& dwChunkSize, DWORD& dwChunkDataPosition) { - HRESULT hr = S_OK; - if (INVALID_SET_FILE_POINTER == SetFilePointerEx(hFile, LARGE_INTEGER(), NULL, FILE_BEGIN)) - return HRESULT_FROM_WIN32(GetLastError()); + size_t pos = 0; DWORD dwChunkType; DWORD dwChunkDataSize; @@ -209,29 +207,26 @@ namespace wiAudio DWORD bytesRead = 0; DWORD dwOffset = 0; - while (hr == S_OK) + while(true) { - DWORD dwRead; - if (0 == ReadFile(hFile, &dwChunkType, sizeof(DWORD), &dwRead, NULL)) - hr = HRESULT_FROM_WIN32(GetLastError()); - - if (0 == ReadFile(hFile, &dwChunkDataSize, sizeof(DWORD), &dwRead, NULL)) - hr = HRESULT_FROM_WIN32(GetLastError()); + memcpy(&dwChunkType, data + pos, sizeof(DWORD)); + pos += sizeof(DWORD); + memcpy(&dwChunkDataSize, data + pos, sizeof(DWORD)); + pos += sizeof(DWORD); switch (dwChunkType) { case fourccRIFF: dwRIFFDataSize = dwChunkDataSize; dwChunkDataSize = 4; - if (0 == ReadFile(hFile, &dwFileType, sizeof(DWORD), &dwRead, NULL)) - hr = HRESULT_FROM_WIN32(GetLastError()); + memcpy(&dwFileType, data + pos, sizeof(DWORD)); + pos += sizeof(DWORD); break; default: LARGE_INTEGER li = LARGE_INTEGER(); li.QuadPart = dwChunkDataSize; - if (INVALID_SET_FILE_POINTER == SetFilePointerEx(hFile, li, NULL, FILE_CURRENT)) - return HRESULT_FROM_WIN32(GetLastError()); + pos += dwChunkDataSize; } dwOffset += sizeof(DWORD) * 2; @@ -240,84 +235,57 @@ namespace wiAudio { dwChunkSize = dwChunkDataSize; dwChunkDataPosition = dwOffset; - return S_OK; + return true; } dwOffset += dwChunkDataSize; - if (bytesRead >= dwRIFFDataSize) return S_FALSE; + if (bytesRead >= dwRIFFDataSize) return false; } - return S_OK; + return true; } - HRESULT ReadChunkData(HANDLE hFile, void* buffer, DWORD buffersize, DWORD bufferoffset) - { - HRESULT hr = S_OK; - - LARGE_INTEGER li = LARGE_INTEGER(); - li.QuadPart = bufferoffset; - if (INVALID_SET_FILE_POINTER == SetFilePointerEx(hFile, li, NULL, FILE_BEGIN)) - return HRESULT_FROM_WIN32(GetLastError()); - DWORD dwRead; - if (0 == ReadFile(hFile, buffer, buffersize, &dwRead, NULL)) - hr = HRESULT_FROM_WIN32(GetLastError()); - return hr; - } bool CreateSound(const std::string& filename, Sound* sound) + { + std::vector filedata; + bool success = wiHelper::FileRead(filename, filedata); + if (!success) + { + return false; + } + return CreateSound(filedata, sound); + } + bool CreateSound(const std::vector& data, Sound* sound) { std::shared_ptr soundinternal = std::make_shared(); sound->internal_state = soundinternal; - std::wstring wfilename; - wiHelper::StringConvert(filename, wfilename); - - HANDLE hFile = CreateFile2( - wfilename.c_str(), - GENERIC_READ, - FILE_SHARE_READ, - OPEN_EXISTING, - nullptr - ); - - HRESULT hr; - if (INVALID_HANDLE_VALUE == hFile) - { - hr = HRESULT_FROM_WIN32(GetLastError()); - return false; - } - - if (INVALID_SET_FILE_POINTER == SetFilePointerEx(hFile, LARGE_INTEGER(), NULL, FILE_BEGIN)) - { - hr = HRESULT_FROM_WIN32(GetLastError()); - return false; - } - DWORD dwChunkSize; DWORD dwChunkPosition; - FindChunk(hFile, fourccRIFF, dwChunkSize, dwChunkPosition); + bool success; + + success = FindChunk(data.data(), fourccRIFF, dwChunkSize, dwChunkPosition); + assert(success); DWORD filetype; - hr = ReadChunkData(hFile, &filetype, sizeof(DWORD), dwChunkPosition); - assert(SUCCEEDED(hr)); + memcpy(&filetype, data.data() + dwChunkPosition, sizeof(DWORD)); assert(filetype == fourccWAVE); soundinternal->audio = audio; - hr = FindChunk(hFile, fourccFMT, dwChunkSize, dwChunkPosition); - assert(SUCCEEDED(hr)); - hr = ReadChunkData(hFile, &soundinternal->wfx, dwChunkSize, dwChunkPosition); - assert(SUCCEEDED(hr)); + success = FindChunk(data.data(), fourccFMT, dwChunkSize, dwChunkPosition); + assert(success); + memcpy(&soundinternal->wfx, data.data() + dwChunkPosition, dwChunkSize); soundinternal->wfx.wFormatTag = WAVE_FORMAT_PCM; - hr = FindChunk(hFile, fourccDATA, dwChunkSize, dwChunkPosition); - assert(SUCCEEDED(hr)); + success = FindChunk(data.data(), fourccDATA, dwChunkSize, dwChunkPosition); + assert(success); soundinternal->audioData.resize(dwChunkSize); - hr = ReadChunkData(hFile, soundinternal->audioData.data(), dwChunkSize, dwChunkPosition); - assert(SUCCEEDED(hr)); + memcpy(soundinternal->audioData.data(), data.data() + dwChunkPosition, dwChunkSize); return true; } diff --git a/WickedEngine/wiAudio.h b/WickedEngine/wiAudio.h index 14e421d7d..b1b2c1f8d 100644 --- a/WickedEngine/wiAudio.h +++ b/WickedEngine/wiAudio.h @@ -3,6 +3,7 @@ #include #include +#include namespace wiAudio { @@ -35,6 +36,7 @@ namespace wiAudio }; bool CreateSound(const std::string& filename, Sound* sound); + bool CreateSound(const std::vector& data, Sound* sound); bool CreateSoundInstance(const Sound* sound, SoundInstance* instance); void Play(SoundInstance* instance); diff --git a/WickedEngine/wiBackLog.cpp b/WickedEngine/wiBackLog.cpp index ec9b083bf..0432b37a9 100644 --- a/WickedEngine/wiBackLog.cpp +++ b/WickedEngine/wiBackLog.cpp @@ -66,7 +66,7 @@ namespace wiBackLog Toggle(); } - if (isActive) + if (isActive()) { if (wiInput::Press(wiInput::KEYBOARD_BUTTON_UP)) { diff --git a/WickedEngine/wiFont.cpp b/WickedEngine/wiFont.cpp index 550ca29e0..b36bae975 100644 --- a/WickedEngine/wiFont.cpp +++ b/WickedEngine/wiFont.cpp @@ -82,7 +82,7 @@ namespace wiFont_Internal void Create(const string& newName) { name = newName; - wiHelper::readByteData(newName, fontBuffer); + wiHelper::FileRead(newName, fontBuffer); int offset = stbtt_GetFontOffsetForIndex(fontBuffer.data(), 0); diff --git a/WickedEngine/wiHelper.cpp b/WickedEngine/wiHelper.cpp index bf64a5ef8..704cd6a3d 100644 --- a/WickedEngine/wiHelper.cpp +++ b/WickedEngine/wiHelper.cpp @@ -14,13 +14,26 @@ #include #include // string conversion +#ifdef _WIN32 #ifdef PLATFORM_UWP #include #include + +// This can be used to access any file on the system, but also needs the following manifests defined: +// xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities" +// IgnorableNamespaces = "uap mp rescap" > +// +// And also the capability: +// +// +// < / Capabilities> +#define UWP_BROAD_FILESYSTEM_ACCESS + #else #include // openfile #include #endif // PLATFORM_UWP +#endif // _WIN32 using namespace std; @@ -37,34 +50,14 @@ namespace wiHelper return result; } - bool readByteData(const std::string& fileName, std::vector& data) - { - ifstream file(fileName, ios::binary | ios::ate); - if (file.is_open()) - { - size_t dataSize = (size_t)file.tellg(); - file.seekg(0, file.beg); - data.resize(dataSize); - file.read((char*)data.data(), dataSize); - file.close(); - return true; - } - stringstream ss(""); - ss << "File not found: " << fileName; - messageBox(ss.str()); - return false; - } - void messageBox(const std::string& msg, const std::string& caption) { -#ifndef PLATFORM_UWP - MessageBoxA(wiPlatform::GetWindow(), msg.c_str(), caption.c_str(), 0); -#else - wstring wmsg; - StringConvert(msg, wmsg); - wstring wcaption(caption.begin(), caption.end()); - Windows::UI::Popups::MessageDialog(ref new Platform::String(wmsg.c_str()), ref new Platform::String(wcaption.c_str())).ShowAsync(); -#endif + auto& state = wiPlatform::GetWindowState(); + state.messagemutex.lock(); + state.messages.emplace_back(); + StringConvert(msg, state.messages.back().message); + StringConvert(caption, state.messages.back().caption); + state.messagemutex.unlock(); } void screenshot(const std::string& name) @@ -158,29 +151,43 @@ namespace wiHelper int write_result = 0; + std::vector filedata; + stbi_write_func* func = [](void* context, void* data, int size) { + std::vector& filedata = *(std::vector*)context; + for (int i = 0; i < size; ++i) + { + filedata.push_back(*((uint8_t*)data + i)); + } + }; + string extension = wiHelper::toUpper(wiHelper::GetExtensionFromFileName(fileName)); if (!extension.compare("JPG")) { - write_result = stbi_write_jpg(fileName.c_str(), (int)desc.Width, (int)desc.Height, 4, textureData.data(), 100); + write_result = stbi_write_jpg_to_func(func, &filedata, (int)desc.Width, (int)desc.Height, 4, textureData.data(), 100); } else if (!extension.compare("PNG")) { - write_result = stbi_write_png(fileName.c_str(), (int)desc.Width, (int)desc.Height, 4, textureData.data(), 0); + write_result = stbi_write_png_to_func(func, &filedata, (int)desc.Width, (int)desc.Height, 4, textureData.data(), 0); } else if (!extension.compare("TGA")) { - write_result = stbi_write_tga(fileName.c_str(), (int)desc.Width, (int)desc.Height, 4, textureData.data()); + write_result = stbi_write_tga_to_func(func, &filedata, (int)desc.Width, (int)desc.Height, 4, textureData.data()); } else if (!extension.compare("BMP")) { - write_result = stbi_write_bmp(fileName.c_str(), (int)desc.Width, (int)desc.Height, 4, textureData.data()); + write_result = stbi_write_bmp_to_func(func, &filedata, (int)desc.Width, (int)desc.Height, 4, textureData.data()); } else { assert(0 && "Unsupported extension"); } - return write_result != 0; + if (write_result != 0) + { + return FileWrite(fileName, filedata.data(), filedata.size()); + } + + return false; } string getCurrentDateTimeAsString() @@ -341,12 +348,205 @@ namespace wiHelper } } + bool FileRead(const std::string& fileName, std::vector& data) + { +#ifndef PLATFORM_UWP + ifstream file(fileName, ios::binary | ios::ate); + if (file.is_open()) + { + size_t dataSize = (size_t)file.tellg(); + file.seekg(0, file.beg); + data.resize(dataSize); + file.read((char*)data.data(), dataSize); + file.close(); + return true; + } +#else + if (!FileExists(fileName)) + { + return false; + } + using namespace concurrency; + using namespace Platform; + using namespace Windows::Storage; + using namespace Windows::Storage::Streams; + wstring wstr; + string filepath = fileName; + if (filepath.find(":\\") == string::npos) + { + filepath = GetWorkingDirectory() + filepath; + } + StringConvert(filepath, wstr); + std::replace(wstr.begin(), wstr.end(), '/', '\\'); + bool success = false; + std::thread([&] { + bool end0 = false; + create_task(StorageFile::GetFileFromPathAsync(ref new String(wstr.c_str()))).then([&](task task) { + + StorageFile^ file; + try + { + file = task.get(); + } + catch (Platform::AccessDeniedException^ e) + { + messageBox("Opening file failed: " + fileName + " , please allow file system access permission!", "Error!"); + end0 = true; + return; + } + catch (...) + { + end0 = true; + return; + } + + if (file) + { + bool end1 = false; + create_task(FileIO::ReadBufferAsync(file)).then([&](IBuffer^ buffer) { + auto reader = DataReader::FromBuffer(buffer); + auto size = buffer->Length; + data.resize((size_t)size); + for (auto& x : data) + { + x = reader->ReadByte(); + } + success = true; + end1 = true; + }); + while (!end1) { Sleep(1); } + } + end0 = true; + }); + while (!end0) { Sleep(1); } + + }).join(); + + if (success) + { + return true; + } +#endif // PLATFORM_UWP + + messageBox("File not found: " + fileName); + return false; + } + + bool FileWrite(const std::string& fileName, const uint8_t* data, size_t size) + { + if (size <= 0) + { + return false; + } + +#ifndef PLATFORM_UWP + ofstream file(fileName, ios::binary | ios::trunc); + if (file.is_open()) + { + file.write((const char*)data, (streamsize)size); + file.close(); + return true; + } +#else + using namespace concurrency; + using namespace Platform; + using namespace Windows::Storage; + using namespace Windows::Storage::Streams; + using namespace Windows::Security::Cryptography; + wstring wstr; + string filepath = fileName; + if (filepath.find(":\\") == string::npos) + { + filepath = GetWorkingDirectory() + filepath; + } + StringConvert(filepath, wstr); + std::replace(wstr.begin(), wstr.end(), '/', '\\'); + bool success = false; + std::thread([&] { + bool end0 = false; + create_task(StorageFile::GetFileFromPathAsync(ref new String(wstr.c_str()))).then([&](StorageFile^ file) { + if (file) + { + bool end1 = false; + create_task(FileIO::WriteBytesAsync(file, ref new Platform::Array((unsigned char*)data, (unsigned int)size))).then([&]() { + success = true; + end1 = true; + }); + while (!end1) { Sleep(1); } + } + end0 = true; + }); + while (!end0) { Sleep(1); } + }).join(); + + if (success) + { + return true; + } +#endif // PLATFORM_UWP + + return false; + } + bool FileExists(const std::string& fileName) { - ifstream f(fileName); - bool exists = f.is_open(); - f.close(); +#ifndef PLATFORM_UWP + ifstream file(fileName); + bool exists = file.is_open(); + file.close(); return exists; +#else + using namespace concurrency; + using namespace Platform; + using namespace Windows::Storage; + using namespace Windows::Storage::Streams; + string filepath = fileName; + if (filepath.find(":\\") == string::npos) + { + filepath = GetWorkingDirectory() + filepath; + } + string directory, name; + SplitPath(filepath, directory, name); + wstring wdir, wname; + StringConvert(directory, wdir); + StringConvert(name, wname); + std::replace(wdir.begin(), wdir.end(), '/', '\\'); + bool success = false; + std::thread([&] { + bool end0 = false; + create_task(StorageFolder::GetFolderFromPathAsync(ref new String(wdir.c_str()))).then([&](task task) { + + StorageFolder^ folder; + try + { + folder = task.get(); + } + catch (Platform::AccessDeniedException^ e) + { + messageBox("Opening file failed: " + fileName + " , please allow file system access permission!", "Error!"); + end0 = true; + return; + } + + if (folder) + { + bool end1 = false; + create_task(folder->TryGetItemAsync(ref new String(wname.c_str()))).then([&](IStorageItem^ item) { + if (item) + { + success = true; + } + end1 = true; + }); + while (!end1) { Sleep(1); } + } + end0 = true; + }); + while (!end0) { Sleep(1); } + }).join(); + + return success; +#endif } void FileDialog(const FileDialogParams& params, std::function onSuccess) @@ -428,14 +628,57 @@ namespace wiHelper using namespace Platform; using namespace Windows::Storage; using namespace Windows::Storage::Pickers; - using namespace Windows::UI::Xaml; - using namespace Windows::UI::Xaml::Controls; - using namespace Windows::UI::Xaml::Navigation; + using namespace Windows::Storage::AccessCache; switch (params.type) { case FileDialogParams::OPEN: { +#ifndef UWP_BROAD_FILESYSTEM_ACCESS + FolderPicker^ picker = ref new FolderPicker(); + picker->ViewMode = PickerViewMode::List; + picker->SuggestedStartLocation = PickerLocationId::ComputerFolder; + + for (auto& x : params.extensions) + { + wstring wstr; + StringConvert(x, wstr); + wstr = L"." + wstr; + picker->FileTypeFilter->Append(ref new String(wstr.c_str())); + } + + create_task(picker->PickSingleFolderAsync()).then([=](StorageFolder^ folder) { + if (folder) + { + auto futureaccess = StorageApplicationPermissions::FutureAccessList; + futureaccess->Clear(); + futureaccess->Add(folder); + + FileOpenPicker^ filepicker = ref new FileOpenPicker(); + filepicker->ViewMode = PickerViewMode::List; + filepicker->SuggestedStartLocation = PickerLocationId::ComputerFolder; + + for (auto& x : params.extensions) + { + wstring wstr; + StringConvert(x, wstr); + wstr = L"." + wstr; + filepicker->FileTypeFilter->Append(ref new String(wstr.c_str())); + } + create_task(filepicker->PickSingleFileAsync()).then([=](StorageFile^ file) { + if (file) + { + wstring wstr = file->Path->Data(); + string str; + StringConvert(wstr, str); + onSuccess(str); + } + }); + + } + }); + +#else FileOpenPicker^ picker = ref new FileOpenPicker(); picker->ViewMode = PickerViewMode::List; picker->SuggestedStartLocation = PickerLocationId::ComputerFolder; @@ -452,12 +695,17 @@ namespace wiHelper if (file) { + auto futureaccess = StorageApplicationPermissions::FutureAccessList; + futureaccess->Clear(); + futureaccess->Add(file); wstring wstr = file->Path->Data(); string str; StringConvert(wstr, str); onSuccess(str); } }); +#endif + } break; case FileDialogParams::SAVE: @@ -480,6 +728,9 @@ namespace wiHelper if (file) { + auto futureaccess = StorageApplicationPermissions::FutureAccessList; + futureaccess->Clear(); + futureaccess->Add(file); wstring wstr = file->Path->Data(); string str; StringConvert(wstr, str); @@ -494,7 +745,7 @@ namespace wiHelper #endif // _WIN32 } - void StringConvert(const std::string from, std::wstring& to) + void StringConvert(const std::string& from, std::wstring& to) { int num = MultiByteToWideChar(CP_UTF8, 0, from.c_str(), -1, NULL, 0); if (num > 0) @@ -504,7 +755,7 @@ namespace wiHelper } } - void StringConvert(const std::wstring from, std::string& to) + void StringConvert(const std::wstring& from, std::string& to) { int num = WideCharToMultiByte(CP_UTF8, 0, from.c_str(), -1, NULL, 0, NULL, NULL); if (num > 0) diff --git a/WickedEngine/wiHelper.h b/WickedEngine/wiHelper.h index c2308261b..058815ee8 100644 --- a/WickedEngine/wiHelper.h +++ b/WickedEngine/wiHelper.h @@ -33,8 +33,6 @@ namespace wiHelper std::string toUpper(const std::string& s); - bool readByteData(const std::string& fileName, std::vector& data); - void messageBox(const std::string& msg, const std::string& caption = "Warning!"); void screenshot(const std::string& name = ""); @@ -55,8 +53,6 @@ namespace wiHelper bool SetWorkingDirectory(const std::string& path); - void GetFilesInDirectory(std::vector &out, const std::string &directory); - void SplitPath(const std::string& fullPath, std::string& dir, std::string& fileName); std::string GetFileNameFromPath(const std::string& fullPath); @@ -67,6 +63,10 @@ namespace wiHelper void RemoveExtensionFromFileName(std::string& filename); + bool FileRead(const std::string& fileName, std::vector& data); + + bool FileWrite(const std::string& fileName, const uint8_t* data, size_t size); + bool FileExists(const std::string& fileName); struct FileDialogParams @@ -81,9 +81,9 @@ namespace wiHelper }; void FileDialog(const FileDialogParams& params, std::function onSuccess); - void StringConvert(const std::string from, std::wstring& to); + void StringConvert(const std::string& from, std::wstring& to); - void StringConvert(const std::wstring from, std::string& to); + void StringConvert(const std::wstring& from, std::string& to); // Parameter - to - must be pre-allocated! // returns result string length diff --git a/WickedEngine/wiLua.cpp b/WickedEngine/wiLua.cpp index 6cd963316..6d3f97a0e 100644 --- a/WickedEngine/wiLua.cpp +++ b/WickedEngine/wiLua.cpp @@ -1,6 +1,7 @@ #include "wiLua.h" #include "wiLua_Globals.h" #include "wiBackLog.h" +#include "wiHelper.h" #include "MainComponent_BindLua.h" #include "RenderPath_BindLua.h" #include "RenderPath2D_BindLua.h" @@ -27,17 +28,36 @@ #include #include +#include using namespace std; #define WILUA_ERROR_PREFIX "[Lua Error] " +int Internal_DoFile(lua_State* L) +{ + int argc = wiLua::SGetArgCount(L); + + if (argc > 0) + { + std::string filename = wiLua::SGetString(L, 1); + wiLua::GetGlobal()->RunFile(filename); + } + else + { + wiLua::SError(L, "dofile(string filename) not enough arguments!"); + } + + return 0; +} + wiLua::wiLua() { m_luaState = NULL; m_luaState = luaL_newstate(); luaL_openlibs(m_luaState); RegisterFunc("debugout", DebugOut); + RegisterFunc("dofile", Internal_DoFile); RunText(wiLua_Globals); } @@ -134,16 +154,23 @@ void wiLua::PostErrorMsg(bool todebug, bool tobacklog) } bool wiLua::RunFile(const std::string& filename) { - lock.lock(); - m_status = luaL_loadfile(m_luaState, filename.c_str()); - lock.unlock(); - - if (Success()) { - return RunScript(); + std::vector filedata; + if (wiHelper::FileRead(filename, filedata)) + { + return RunText(string(filedata.begin(), filedata.end())); } - - PostErrorMsg(); return false; + + //lock.lock(); + //m_status = luaL_loadfile(m_luaState, filename.c_str()); + //lock.unlock(); + // + //if (Success()) { + // return RunScript(); + //} + + //PostErrorMsg(); + //return false; } bool wiLua::RunText(const std::string& script) { diff --git a/WickedEngine/wiPlatform.h b/WickedEngine/wiPlatform.h index f1240e3c6..f8454c6dd 100644 --- a/WickedEngine/wiPlatform.h +++ b/WickedEngine/wiPlatform.h @@ -1,6 +1,10 @@ #pragma once // This file includes platform, os specific libraries and supplies common platform specific resources +#include +#include +#include + #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN @@ -26,10 +30,18 @@ namespace wiPlatform #endif // PLATFORM_UWP #endif // _WIN32 + struct DeferredMessageBox + { + std::wstring caption; + std::wstring message; + }; + struct WindowState { window_type window; int dpi = 96; + std::vector messages; + std::mutex messagemutex; }; inline WindowState& GetWindowState() { @@ -81,4 +93,21 @@ namespace wiPlatform #endif // PLATFORM_UWP #endif // _WIN32 } + inline void PopMessages() + { + auto& state = GetWindowState(); + state.messagemutex.lock(); + for (auto& x : state.messages) + { +#ifdef _WIN32 +#ifndef PLATFORM_UWP + MessageBox(wiPlatform::GetWindow(), x.message.c_str(), x.caption.c_str(), 0); +#else + Windows::UI::Popups::MessageDialog(ref new Platform::String(x.message.c_str()), ref new Platform::String(x.caption.c_str())).ShowAsync(); +#endif // PLATFORM_UWP +#endif // _WIN32 + } + state.messages.clear(); + state.messagemutex.unlock(); + } } diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp index d05ff2fe2..073c69ce7 100644 --- a/WickedEngine/wiRenderer.cpp +++ b/WickedEngine/wiRenderer.cpp @@ -1028,7 +1028,7 @@ Shader tiledLightingCS[TILEDLIGHTING_TYPE_COUNT][TILEDLIGHTING_CULLING_COUNT][TI bool LoadShader(SHADERSTAGE stage, wiGraphics::Shader& shader, const std::string& filename) { vector buffer; - if (wiHelper::readByteData(SHADERPATH + filename, buffer)) + if (wiHelper::FileRead(SHADERPATH + filename, buffer)) { return GetDevice()->CreateShader(stage, buffer.data(), buffer.size(), &shader); } diff --git a/WickedEngine/wiResourceManager.cpp b/WickedEngine/wiResourceManager.cpp index 49d80dd64..011a1039f 100644 --- a/WickedEngine/wiResourceManager.cpp +++ b/WickedEngine/wiResourceManager.cpp @@ -57,6 +57,12 @@ namespace wiResourceManager return resource; } + std::vector filedata; + if (!wiHelper::FileRead(name, filedata)) + { + resource.reset(); + return nullptr; + } std::string ext = wiHelper::toUpper(name.substr(name.length() - 3, name.length())); wiResource::DATA_TYPE type; @@ -85,7 +91,7 @@ namespace wiResourceManager // Load dds tinyddsloader::DDSFile dds; - auto result = dds.Load(name.c_str()); + auto result = dds.Load(std::move(filedata)); if (result == tinyddsloader::Result::Success) { @@ -226,7 +232,7 @@ namespace wiResourceManager const int channelCount = 4; int width, height, bpp; - unsigned char* rgb = stbi_load(name.c_str(), &width, &height, &bpp, channelCount); + unsigned char* rgb = stbi_load_from_memory(filedata.data(), (int)filedata.size(), &width, &height, &bpp, channelCount); if (rgb != nullptr) { @@ -275,7 +281,7 @@ namespace wiResourceManager case wiResource::SOUND: { wiAudio::Sound* sound = new wiAudio::Sound; - if (wiAudio::CreateSound(name, sound)) + if (wiAudio::CreateSound(filedata, sound)) { success = sound; } diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index ef6a3bd4f..8147a12e5 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -9,7 +9,7 @@ namespace wiVersion // minor features, major updates const int minor = 41; // minor bug fixes, alterations, refactors, updates - const int revision = 10; + const int revision = 11; const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);