From 399a48ece3bbb9b1f5d113f3a4d6a3dae40e2cf7 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Thu, 14 Jan 2016 19:44:42 -1000 Subject: [PATCH 01/15] Win32 fix; enabled LTCG for MSVC Release builds --- CMakeLists.txt | 10 ++++++++++ Editor/Space.cpp | 8 ++------ Editor/Space.hpp | 2 +- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3fd163e5a..6ca031d50 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,12 +4,22 @@ project(PathShagged) if(MSVC) # Shaddup MSVC add_definitions(-DUNICODE=1 -D_UNICODE=1 -D__SSE__=1 -D_CRT_SECURE_NO_WARNINGS=1 -DD_SCL_SECURE_NO_WARNINGS=1 /wd4267 /wd4244 /wd4305) + + # Link-time Code Generation for Release builds + set(CMAKE_C_FLAGS_RELEASE "/DNDEBUG /O2 /Oy /GL /Gy /MD") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") + set(CMAKE_C_FLAGS_RELWITHDEBINFO "/DNDEBUG /Zi /O2 /Oy- /GL /Gy /MD") + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}") + set(CMAKE_EXE_LINKER_FLAGS_RELEASE "/RELEASE /LTCG /OPT:REF /OPT:ICF /INCREMENTAL:NO") + set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "/DEBUG /RELEASE /LTCG /OPT:REF /OPT:ICF /INCREMENTAL:NO /DEBUGTYPE:cv,fixup") + else() if (CMAKE_COMPILER_IS_GNUCXX) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpermissive") message(WARNING "GCC needs -fpermissive for nested type redeclarations; expect lotsa warnings!!") endif() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -Wno-multichar -fno-exceptions") + endif() if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") diff --git a/Editor/Space.cpp b/Editor/Space.cpp index 5525b816a..e58f87b90 100644 --- a/Editor/Space.cpp +++ b/Editor/Space.cpp @@ -131,26 +131,22 @@ Space* Space::NewSpaceFromConfigStream(ViewManager& vm, Space* parent, ConfigRea { #ifdef URDE_BINARY_CONFIGS Class cls = Class(r.readUint32Big()); - return BuildNewSpace(vm, cls, parent, r); #else Class cls = Class(r.readUint32("class")); - return BuildNewSpace(vm, cls, parent, r); #endif + return BuildNewSpace(vm, cls, parent, r); } RootSpace* Space::NewRootSpaceFromConfigStream(ViewManager& vm, ConfigReader& r) { #ifdef URDE_BINARY_CONFIGS Class cls = Class(r.readUint32Big()); - if (cls != Class::RootSpace) - return nullptr; - return BuildNewSpace(vm, cls, r); #else Class cls = Class(r.readUint32("class")); +#endif if (cls != Class::RootSpace) return nullptr; return new RootSpace(vm, r); -#endif } } diff --git a/Editor/Space.hpp b/Editor/Space.hpp index b3e533902..616edcbd6 100644 --- a/Editor/Space.hpp +++ b/Editor/Space.hpp @@ -88,7 +88,7 @@ public: { m_state.read(r); #ifdef URDE_BINARY_CONFIGS - m_child.reset(NewSpaceFromConfigStream(vm, this, r)); + m_spaceTree.reset(NewSpaceFromConfigStream(vm, this, r)); #else r.enterSubRecord("spaceTree"); m_spaceTree.reset(NewSpaceFromConfigStream(vm, this, r)); From 342fc4a00ce9e9d4e45e3e1fc2efaf13b87d60fb Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Fri, 15 Jan 2016 13:35:59 -1000 Subject: [PATCH 02/15] Updates for Menu --- .gitignore | 1 + Editor/SplashScreen.cpp | 5 ++++- Editor/ViewManager.cpp | 1 - Editor/ViewManager.hpp | 2 +- hecl | 2 +- libSpecter | 2 +- 6 files changed, 8 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index dca2e8836..c138894b3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ version.h *.user +.DS_Store diff --git a/Editor/SplashScreen.cpp b/Editor/SplashScreen.cpp index 4d4e0ab0a..4320ab179 100644 --- a/Editor/SplashScreen.cpp +++ b/Editor/SplashScreen.cpp @@ -53,6 +53,9 @@ void SplashScreen::think() if (m_fileBrowser.m_view) m_fileBrowser.m_view->think(); + if (m_openButt.m_view) + m_openButt.m_view->think(); + if (m_newProjBind.m_deferPath.size()) { Log.report(LogVisor::Info, _S("Making project '%s'"), m_newProjBind.m_deferPath.c_str()); @@ -78,7 +81,7 @@ void SplashScreen::updateContentOpacity(float opacity) Specter::ViewResources& res = rootView().viewRes(); if (!m_title && res.fontCacheReady()) - { + { m_title.reset(new Specter::TextView(res, *this, res.m_titleFont)); Zeus::CColor clearColor = res.themeData().uiText(); clearColor[3] = 0.0; diff --git a/Editor/ViewManager.cpp b/Editor/ViewManager.cpp index 8aa87fd01..e3a90daa7 100644 --- a/Editor/ViewManager.cpp +++ b/Editor/ViewManager.cpp @@ -36,7 +36,6 @@ void ViewManager::RootSpaceViewBuilt(Specter::View *view) std::vector& cViews = m_rootView->accessContentViews(); cViews.clear(); cViews.push_back(view); - printf("RootView Set: %p [%p]\n\n", m_rootView.get(), view); cViews.push_back(m_splash.get()); m_rootView->updateSize(); } diff --git a/Editor/ViewManager.hpp b/Editor/ViewManager.hpp index 1861a99c6..608916719 100644 --- a/Editor/ViewManager.hpp +++ b/Editor/ViewManager.hpp @@ -29,7 +29,7 @@ class ViewManager : public Specter::IViewManager std::unique_ptr m_rootSpace; Specter::View* m_rootSpaceView = nullptr; - std::vector m_recentProjects; + std::vector m_recentProjects = {"Test", "One", "Two", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j"}; std::vector m_recentFiles; bool m_updatePf = false; diff --git a/hecl b/hecl index 5d0c80b9e..02236f044 160000 --- a/hecl +++ b/hecl @@ -1 +1 @@ -Subproject commit 5d0c80b9e603ecb2762b281d8736d21a324c3e76 +Subproject commit 02236f04488aee598ee268a6aefbdfb9e56bb98c diff --git a/libSpecter b/libSpecter index 2490aa3bb..c0cc30bca 160000 --- a/libSpecter +++ b/libSpecter @@ -1 +1 @@ -Subproject commit 2490aa3bb82860fa2969d2cc797324d846e3b51c +Subproject commit c0cc30bca09e92b0c8e566016334c162c459f9dc From 7c46c3a62f36e3d94f57f75016d1067b92330a7f Mon Sep 17 00:00:00 2001 From: Phillip Stephens Date: Fri, 15 Jan 2016 19:38:37 -0800 Subject: [PATCH 03/15] Update HECL --- hecl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hecl b/hecl index 02236f044..5b5d78c2c 160000 --- a/hecl +++ b/hecl @@ -1 +1 @@ -Subproject commit 02236f04488aee598ee268a6aefbdfb9e56bb98c +Subproject commit 5b5d78c2c50f917b07b2a2f534e3659d23be383e From 877a389da6bfcacca542fe67b41c7b6134b22c21 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Fri, 15 Jan 2016 17:58:11 -1000 Subject: [PATCH 04/15] Recent projects functionality --- Editor/ProjectManager.cpp | 5 ++++ Editor/SplashScreen.hpp | 6 +++- Editor/ViewManager.cpp | 63 +++++++++++++++++++++++++++++++++++++-- Editor/ViewManager.hpp | 4 ++- hecl | 2 +- libSpecter | 2 +- 6 files changed, 75 insertions(+), 7 deletions(-) diff --git a/Editor/ProjectManager.cpp b/Editor/ProjectManager.cpp index 197806b44..bbf33342e 100644 --- a/Editor/ProjectManager.cpp +++ b/Editor/ProjectManager.cpp @@ -99,6 +99,9 @@ bool ProjectManager::openProject(const HECL::SystemString& path) m_vm.m_mainWindow->setTitle(m_proj->getProjectRootPath().getLastComponent()); m_vm.DismissSplash(); m_vm.FadeInEditors(); + + m_vm.pushRecentProject(m_proj->getProjectRootPath().getAbsolutePath()); + return true; makeDefault: @@ -164,6 +167,8 @@ bool ProjectManager::saveProject() HECL::Rename(oldSpacesPath.getAbsolutePath().c_str(), newSpacesPath.getAbsolutePath().c_str()); + m_vm.pushRecentProject(m_proj->getProjectRootPath().getAbsolutePath()); + return true; } diff --git a/Editor/SplashScreen.hpp b/Editor/SplashScreen.hpp index 52b6ddd7d..a93c12297 100644 --- a/Editor/SplashScreen.hpp +++ b/Editor/SplashScreen.hpp @@ -93,7 +93,11 @@ class SplashScreen : public Specter::ModalWindow std::string m_text; const std::string* text() const {return &m_text;} - void activated() {m_parent.m_openProjBind.m_deferPath = m_path;} + void activated(const boo::SWindowCoord& coord) + { + m_parent.m_openProjBind.m_deferPath = m_path; + m_parent.m_openProjBind.m_splash.m_openButt.m_view->closeMenu(coord); + } OpenRecentMenuItem(OpenRecentMenuRoot& parent, const HECL::SystemString& path) : m_parent(parent), m_path(path) diff --git a/Editor/ViewManager.cpp b/Editor/ViewManager.cpp index e3a90daa7..c83fa04f1 100644 --- a/Editor/ViewManager.cpp +++ b/Editor/ViewManager.cpp @@ -4,6 +4,7 @@ #include "SplashScreen.hpp" #include "locale/locale.hpp" #include "ResourceBrowser.hpp" +#include using YAMLNode = Athena::io::YAMLNode; @@ -75,20 +76,76 @@ void ViewManager::DismissSplash() ViewManager::ViewManager(HECL::Runtime::FileStoreManager& fileMgr, HECL::CVarManager& cvarMgr) : m_fileStoreManager(fileMgr), m_cvarManager(cvarMgr), m_projManager(*this), - m_fontCache(fileMgr), m_translator(URDE::SystemLocaleOrEnglish()) -{} + m_fontCache(fileMgr), m_translator(URDE::SystemLocaleOrEnglish()), + m_recentProjectsPath(HECL::SysFormat(_S("%s/recent_projects.txt"), fileMgr.getStoreRoot().c_str())), + m_recentFilesPath(HECL::SysFormat(_S("%s/recent_files.txt"), fileMgr.getStoreRoot().c_str())) +{ + char path[2048]; + HECL::Sstat theStat; + + FILE* fp = HECL::Fopen(m_recentProjectsPath.c_str(), _S("r"), HECL::FileLockType::Read); + if (fp) + { + while (fgets(path, 2048, fp)) + { + std::string pathStr(path); + pathStr.pop_back(); + HECL::SystemStringView pathStrView(pathStr); + if (!HECL::Stat(pathStrView.c_str(), &theStat) && S_ISDIR(theStat.st_mode)) + m_recentProjects.push_back(pathStrView); + } + fclose(fp); + } + + fp = HECL::Fopen(m_recentFilesPath.c_str(), _S("r"), HECL::FileLockType::Read); + if (fp) + { + while (fgets(path, 2048, fp)) + { + std::string pathStr(path); + pathStr.pop_back(); + HECL::SystemStringView pathStrView(pathStr); + if (!HECL::Stat(pathStrView.c_str(), &theStat) && S_ISDIR(theStat.st_mode)) + m_recentFiles.push_back(pathStrView); + } + fclose(fp); + } +} ViewManager::~ViewManager() {} void ViewManager::pushRecentProject(const HECL::SystemString& path) { + for (HECL::SystemString& testPath : m_recentProjects) + { + if (path == testPath) + return; + } m_recentProjects.push_back(path); + FILE* fp = HECL::Fopen(m_recentProjectsPath.c_str(), _S("w"), HECL::FileLockType::Write); + if (fp) + { + for (HECL::SystemString& pPath : m_recentProjects) + fprintf(fp, "%s\n", HECL::SystemUTF8View(pPath).c_str()); + fclose(fp); + } } void ViewManager::pushRecentFile(const HECL::SystemString& path) { + for (HECL::SystemString& testPath : m_recentFiles) + { + if (path == testPath) + return; + } m_recentFiles.push_back(path); -} + FILE* fp = HECL::Fopen(m_recentFilesPath.c_str(), _S("w"), HECL::FileLockType::Write); + if (fp) + { + for (HECL::SystemString& pPath : m_recentFiles) + fprintf(fp, "%s\n", HECL::SystemUTF8View(pPath).c_str()); + fclose(fp); + }} void ViewManager::init(boo::IApplication* app) { diff --git a/Editor/ViewManager.hpp b/Editor/ViewManager.hpp index 608916719..073820a36 100644 --- a/Editor/ViewManager.hpp +++ b/Editor/ViewManager.hpp @@ -29,7 +29,9 @@ class ViewManager : public Specter::IViewManager std::unique_ptr m_rootSpace; Specter::View* m_rootSpaceView = nullptr; - std::vector m_recentProjects = {"Test", "One", "Two", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j"}; + HECL::SystemString m_recentProjectsPath; + std::vector m_recentProjects; + HECL::SystemString m_recentFilesPath; std::vector m_recentFiles; bool m_updatePf = false; diff --git a/hecl b/hecl index 02236f044..691e6180c 160000 --- a/hecl +++ b/hecl @@ -1 +1 @@ -Subproject commit 02236f04488aee598ee268a6aefbdfb9e56bb98c +Subproject commit 691e6180c4ab6eae12ee236f4d35b8c2ff74a6b2 diff --git a/libSpecter b/libSpecter index c0cc30bca..a7644ff04 160000 --- a/libSpecter +++ b/libSpecter @@ -1 +1 @@ -Subproject commit c0cc30bca09e92b0c8e566016334c162c459f9dc +Subproject commit a7644ff04e5a21ffbd18721f4f53cc3d6fa531c4 From 517a43fc62a5f9a98e25c032b525052be63f1060 Mon Sep 17 00:00:00 2001 From: Phillip Stephens Date: Fri, 15 Jan 2016 20:05:34 -0800 Subject: [PATCH 05/15] Update specter --- libSpecter | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libSpecter b/libSpecter index c0cc30bca..5f99edda4 160000 --- a/libSpecter +++ b/libSpecter @@ -1 +1 @@ -Subproject commit c0cc30bca09e92b0c8e566016334c162c459f9dc +Subproject commit 5f99edda473b5a59b8c6dcf6f2c14f86c465b945 From ce0da88c9ee9ab26fbfd8b16786b8bdbfa882d8a Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Fri, 15 Jan 2016 18:20:07 -1000 Subject: [PATCH 06/15] Update submodules --- hecl | 2 +- libSpecter | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hecl b/hecl index 691e6180c..f2dff4f92 160000 --- a/hecl +++ b/hecl @@ -1 +1 @@ -Subproject commit 691e6180c4ab6eae12ee236f4d35b8c2ff74a6b2 +Subproject commit f2dff4f92b9da4ea4d99478a56a6697a91851713 diff --git a/libSpecter b/libSpecter index a7644ff04..77c30bdac 160000 --- a/libSpecter +++ b/libSpecter @@ -1 +1 @@ -Subproject commit a7644ff04e5a21ffbd18721f4f53cc3d6fa531c4 +Subproject commit 77c30bdac07d4fe45cc16b239dfb9d05045c9e95 From e248379d76804eb6e512053192acaa0a5e898f84 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Fri, 15 Jan 2016 20:11:57 -1000 Subject: [PATCH 07/15] Enable LTO for OS X Release builds --- CMakeLists.txt | 10 +++++++++- hecl | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6ca031d50..8596c0851 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,13 +20,21 @@ else() endif() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -Wno-multichar -fno-exceptions") + if(APPLE) + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -flto") + set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -flto") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -flto") + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -flto") + endif() + endif() if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") include_directories(/usr/local/include) endif() -if("${CMAKE_BUILD_TYPE}" STREQUAL "Release" AND "${CMAKE_SYSTEM_NAME}" STREQUAL "Linux") +if(("${CMAKE_BUILD_TYPE}" STREQUAL "Release" OR "${CMAKE_BUILD_TYPE}" STREQUAL "RelWithDebInfo") + AND "${CMAKE_SYSTEM_NAME}" STREQUAL "Linux") option(USE_LD_GOLD "Link with GNU Gold and enable LTO" ON) else() option(USE_LD_GOLD "Link with GNU Gold and enable LTO" OFF) diff --git a/hecl b/hecl index f2dff4f92..c964328bd 160000 --- a/hecl +++ b/hecl @@ -1 +1 @@ -Subproject commit f2dff4f92b9da4ea4d99478a56a6697a91851713 +Subproject commit c964328bd3c286e6d87d1375549103777045fad8 From 51e295e311a9f339956a5f5e3881c684b7c120e1 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Sat, 16 Jan 2016 18:14:13 -1000 Subject: [PATCH 08/15] Initial space selection menu --- Editor/Space.cpp | 30 +++++++++++++++++++- Editor/Space.hpp | 63 +++++++++++++++++++++++++++++++++++++++++- Editor/ViewManager.cpp | 1 + hecl | 2 +- 4 files changed, 93 insertions(+), 3 deletions(-) diff --git a/Editor/Space.cpp b/Editor/Space.cpp index e58f87b90..211fca6ad 100644 --- a/Editor/Space.cpp +++ b/Editor/Space.cpp @@ -6,6 +6,10 @@ namespace URDE { static LogVisor::LogModule Log("URDE::Space"); +Space::Space(ViewManager& vm, Class cls, Space* parent) +: m_spaceMenuNode(*this), m_spaceSelectBind(*this), + m_vm(vm), m_class(cls), m_parent(parent) {} + Specter::View* Space::buildSpaceView(Specter::ViewResources& res) { if (usesToolbar()) @@ -13,7 +17,12 @@ Specter::View* Space::buildSpaceView(Specter::ViewResources& res) m_spaceView.reset(new Specter::Space(res, m_vm.rootView(), *this, Specter::Toolbar::Position::Bottom)); Specter::View* sview = buildContentView(res); m_spaceView->setContentView(sview); - buildToolbarView(res, *m_spaceView->toolbar()); + Specter::Toolbar& tb = *m_spaceView->toolbar(); + const std::string* classStr = SpaceMenuNode::lookupClassString(m_class); + m_spaceSelectButton.reset(new Specter::Button(res, tb, &m_spaceSelectBind, + classStr?*classStr:"Unknown Class")); + tb.push_back(m_spaceSelectButton.get()); + buildToolbarView(res, tb); return m_spaceView.get(); } else @@ -25,6 +34,25 @@ Specter::View* Space::buildSpaceView(Specter::ViewResources& res) } } +std::vector Space::SpaceMenuNode::s_subNodeDats = +{ + {Class::ResourceBrowser, "resource_browser", "Resource Browser"} +}; +std::string Space::SpaceMenuNode::s_text = "Space Types"; + +void Space::SpaceMenuNode::initializeStrings(ViewManager& vm) +{ + s_text = vm.translateOr("space_types", s_text.c_str()); + for (SubNodeData& sn : s_subNodeDats) + sn.m_text = vm.translateOr(sn.m_key, sn.m_text.c_str()); +} + +std::unique_ptr Space::SpaceSelectBind::buildMenu(const Specter::Button* button) +{ + return std::unique_ptr(new Specter::Menu(m_space.m_vm.rootView().viewRes(), + *m_space.m_spaceView, &m_space.m_spaceMenuNode)); +} + Specter::View* RootSpace::buildSpaceView(Specter::ViewResources& res) { Specter::View* newRoot = buildContentView(res); diff --git a/Editor/Space.hpp b/Editor/Space.hpp index 616edcbd6..0f180983c 100644 --- a/Editor/Space.hpp +++ b/Editor/Space.hpp @@ -38,6 +38,67 @@ public: static Space* NewSpaceFromConfigStream(ViewManager& vm, Space* parent, ConfigReader& r); static RootSpace* NewRootSpaceFromConfigStream(ViewManager& vm, ConfigReader& r); + struct SpaceMenuNode : Specter::IMenuNode + { + struct SubNodeData : Specter::IMenuNode + { + Class m_cls; + std::string m_key; + std::string m_text; + const std::string* text() const {return &m_text;} + void activated(const boo::SWindowCoord& coord) {} + + SubNodeData(Class cls, const char* key, const char* text) + : m_cls(cls), m_key(key), m_text(text) {} + }; + static std::vector s_subNodeDats; + + struct SubNode : Specter::IMenuNode + { + Space& m_space; + const SubNodeData& m_data; + const std::string* text() const {return &m_data.m_text;} + void activated(const boo::SWindowCoord& coord) {} + + SubNode(Space& space, const SubNodeData& data) : m_space(space), m_data(data) {} + }; + std::vector m_subNodes; + + SpaceMenuNode(Space& space) + { + m_subNodes.reserve(s_subNodeDats.size()); + for (const SubNodeData& sn : s_subNodeDats) + m_subNodes.emplace_back(space, sn); + } + + static std::string s_text; + const std::string* text() const {return &s_text;} + + size_t subNodeCount() const {return m_subNodes.size();} + IMenuNode* subNode(size_t idx) {return &m_subNodes[idx];} + + static void initializeStrings(ViewManager& vm); + static const std::string* lookupClassString(Class cls) + { + for (const SubNodeData& sn : s_subNodeDats) + if (sn.m_cls == cls) + return &sn.m_text; + return nullptr; + } + } m_spaceMenuNode; + + struct SpaceSelectBind : Specter::IButtonBinding + { + Space& m_space; + const char* name(const Specter::Control* control) const {return SpaceMenuNode::s_text.c_str();} + + MenuStyle menuStyle(const Specter::Button* button) const {return MenuStyle::Primary;} + std::unique_ptr buildMenu(const Specter::Button* button); + + SpaceSelectBind(Space& space) : m_space(space) {} + } m_spaceSelectBind; + std::unique_ptr m_spaceSelectButton; + protected: friend class ViewManager; friend class RootSpace; @@ -45,7 +106,7 @@ protected: Class m_class = Class::None; Space* m_parent; std::unique_ptr m_spaceView; - Space(ViewManager& vm, Class cls, Space* parent) : m_vm(vm), m_class(cls), m_parent(parent) {} + Space(ViewManager& vm, Class cls, Space* parent); /* Allows common Space code to access DNA-encoded state */ virtual const Space::State& spaceState() const=0; diff --git a/Editor/ViewManager.cpp b/Editor/ViewManager.cpp index c83fa04f1..b37a74860 100644 --- a/Editor/ViewManager.cpp +++ b/Editor/ViewManager.cpp @@ -80,6 +80,7 @@ ViewManager::ViewManager(HECL::Runtime::FileStoreManager& fileMgr, HECL::CVarMan m_recentProjectsPath(HECL::SysFormat(_S("%s/recent_projects.txt"), fileMgr.getStoreRoot().c_str())), m_recentFilesPath(HECL::SysFormat(_S("%s/recent_files.txt"), fileMgr.getStoreRoot().c_str())) { + Space::SpaceMenuNode::initializeStrings(*this); char path[2048]; HECL::Sstat theStat; diff --git a/hecl b/hecl index c964328bd..a6c4d4296 160000 --- a/hecl +++ b/hecl @@ -1 +1 @@ -Subproject commit c964328bd3c286e6d87d1375549103777045fad8 +Subproject commit a6c4d42965764850e362dbbfef47bd3022af91cd From fdfccb8fbb089669742f388c661d4d89d6743ed1 Mon Sep 17 00:00:00 2001 From: Phillip Stephens Date: Sat, 16 Jan 2016 21:08:46 -0800 Subject: [PATCH 09/15] ModelViewer stub --- Editor/CMakeLists.txt | 3 +- Editor/ModelViewer.hpp | 68 ++++++++++++++++++++++++++++++++++++++++++ Editor/Space.hpp | 1 + libSpecter | 2 +- 4 files changed, 72 insertions(+), 2 deletions(-) diff --git a/Editor/CMakeLists.txt b/Editor/CMakeLists.txt index 0c3594666..4e8811d59 100644 --- a/Editor/CMakeLists.txt +++ b/Editor/CMakeLists.txt @@ -17,13 +17,14 @@ endif() atdna(atdna_Space.cpp Space.hpp) atdna(atdna_ResourceBrowser.cpp ResourceBrowser.hpp) +atdna(atdna_ModelViewer.cpp ModelViewer.hpp) add_executable(urde WIN32 main.cpp Space.hpp Space.cpp atdna_Space.cpp SplashScreen.hpp SplashScreen.cpp ResourceBrowser.hpp ResourceBrowser.cpp atdna_ResourceBrowser.cpp - ModelViewer.hpp ModelViewer.cpp + ModelViewer.hpp ModelViewer.cpp atdna_ModelViewer.cpp ProjectManager.hpp ProjectManager.cpp ViewManager.hpp ViewManager.cpp) diff --git a/Editor/ModelViewer.hpp b/Editor/ModelViewer.hpp index 77b21391b..103586b82 100644 --- a/Editor/ModelViewer.hpp +++ b/Editor/ModelViewer.hpp @@ -1,8 +1,76 @@ #ifndef URDE_MODEL_VIEWER_HPP #define URDE_MODEL_VIEWER_HPP +#include "Space.hpp" +#include "ViewManager.hpp" +#include "CVector3f.hpp" +#include "CProjection.hpp" + namespace URDE { +class ModelViewer : public Space +{ + struct State : Space::State + { + DECL_YAML + enum class Mode + { + Solid, + Material, + Wireframe + }; + + Value renderMode = Mode::Material; + Value cameraPosition; + } m_state; + + const Space::State& spaceState() const { return m_state; } + + struct View : Specter::View + { + Zeus::CProjection m_cameraProjection; + }; + virtual Specter::View* buildContentView(Specter::ViewResources& res) + { + return nullptr; + } + virtual Specter::View* buildSpaceView(Specter::ViewResources& res) + { + return nullptr; + } + +public: + ModelViewer(ViewManager& vm, Space* parent) + : Space(vm, Class::ModelViewer, parent) + { + reloadState(); + } + + ModelViewer(ViewManager& vm, Space* parent, const ModelViewer& other) + : ModelViewer(vm, parent) + { + m_state = other.m_state; + reloadState(); + } + + ModelViewer(ViewManager& vm, Space* parent, ConfigReader& r) + : ModelViewer(vm, parent) + { + m_state.read(r); + reloadState(); + } + + void reloadState() + {} + + Space* copy(Space *parent) const + { + return new ModelViewer(m_vm, parent, *this); + } + + bool usesToolbar() const { return true; } +}; + } #endif // URDE_MODEL_VIEWER_HPP diff --git a/Editor/Space.hpp b/Editor/Space.hpp index 616edcbd6..9cd05ae58 100644 --- a/Editor/Space.hpp +++ b/Editor/Space.hpp @@ -32,6 +32,7 @@ public: SplitSpace, TestSpace, ResourceBrowser, + ModelViewer }; struct State : Athena::io::DNAYaml {Delete _d;}; diff --git a/libSpecter b/libSpecter index 77c30bdac..0e061705b 160000 --- a/libSpecter +++ b/libSpecter @@ -1 +1 @@ -Subproject commit 77c30bdac07d4fe45cc16b239dfb9d05045c9e95 +Subproject commit 0e061705bb8d009280a1c857e0701f1f1c79b406 From 2b01035064a203faa98485454e5b1d69efa8a9fd Mon Sep 17 00:00:00 2001 From: Phillip Stephens Date: Sun, 17 Jan 2016 08:01:07 -0800 Subject: [PATCH 10/15] Update Specter --- libSpecter | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libSpecter b/libSpecter index 0e061705b..c5dd30dd7 160000 --- a/libSpecter +++ b/libSpecter @@ -1 +1 @@ -Subproject commit 0e061705bb8d009280a1c857e0701f1f1c79b406 +Subproject commit c5dd30dd7d072666956050b5d5bfa4c325d18f56 From adf31e36d1fc6bfeb4136697923cf25f6c4a0abc Mon Sep 17 00:00:00 2001 From: Phillip Stephens Date: Sun, 17 Jan 2016 14:41:49 -0800 Subject: [PATCH 11/15] Fix INCA, closes issue #9 Camera stubs --- DataSpec/Blender/RetroMasterShader.py | 1 + DataSpec/DNAMP3/CMDLMaterials.cpp | 3 +++ Editor/CMakeLists.txt | 3 ++- Editor/Camera.cpp | 0 Editor/Camera.hpp | 36 +++++++++++++++++++++++++++ Editor/ModelViewer.hpp | 6 +++-- libSpecter | 2 +- 7 files changed, 47 insertions(+), 4 deletions(-) create mode 100644 Editor/Camera.cpp create mode 100644 Editor/Camera.hpp diff --git a/DataSpec/Blender/RetroMasterShader.py b/DataSpec/Blender/RetroMasterShader.py index 1be7e3e77..38e58299a 100644 --- a/DataSpec/Blender/RetroMasterShader.py +++ b/DataSpec/Blender/RetroMasterShader.py @@ -673,6 +673,7 @@ def make_pass_inca(): new_grp.links.new(grp_in.outputs[0], add1.inputs[1]) new_grp.links.new(grp_in.outputs[2], add1.inputs[2]) new_grp.links.new(add1.outputs[0], grp_out.inputs[0]) + new_grp.links.new(grp_in.outputs[1], grp_out.inputs[1]) grp_out.inputs[1].default_value = 1.0 # Reflection Map diff --git a/DataSpec/DNAMP3/CMDLMaterials.cpp b/DataSpec/DNAMP3/CMDLMaterials.cpp index acb3baba1..a4030d6bc 100644 --- a/DataSpec/DNAMP3/CMDLMaterials.cpp +++ b/DataSpec/DNAMP3/CMDLMaterials.cpp @@ -63,6 +63,9 @@ void MaterialSet::ConstructMaterial(Stream& out, material.header.flags.shadowOccluderMesh() ? "True" : "False"); + /* TODO: Some models enable both of these flags at once, why? + * And how do we handle this properly? + */ /* Blend factors */ if (material.header.flags.additiveBlending()) out << "new_material.game_settings.alpha_blend = 'ADD'\n" diff --git a/Editor/CMakeLists.txt b/Editor/CMakeLists.txt index 4e8811d59..59258de9f 100644 --- a/Editor/CMakeLists.txt +++ b/Editor/CMakeLists.txt @@ -26,7 +26,8 @@ add_executable(urde WIN32 ResourceBrowser.hpp ResourceBrowser.cpp atdna_ResourceBrowser.cpp ModelViewer.hpp ModelViewer.cpp atdna_ModelViewer.cpp ProjectManager.hpp ProjectManager.cpp - ViewManager.hpp ViewManager.cpp) + ViewManager.hpp ViewManager.cpp + Camera.hpp Camera.cpp) target_link_libraries(urde UrdeLocales diff --git a/Editor/Camera.cpp b/Editor/Camera.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/Editor/Camera.hpp b/Editor/Camera.hpp new file mode 100644 index 000000000..ef710ec46 --- /dev/null +++ b/Editor/Camera.hpp @@ -0,0 +1,36 @@ +#ifndef URDE_CAMERA_HPP +#define URDE_CAMERA_HPP +#include +#include +#include +#include +#include + +namespace URDE +{ +class Camera +{ + Zeus::CFrustum m_frustum; + Zeus::CProjection m_projection; + Zeus::CVector3f m_position; + Zeus::CQuaternion m_orientation; +public: + + Camera(const Zeus::CVector3f& position, Zeus::EProjType projType=Zeus::EProjType::Perspective, + const Zeus::CVector3f& up=Zeus::Math::kUpVec) + : m_position(position) + { + } + + const Zeus::CMatrix4f& projectionMatrix() const { return m_projection.getCachedMatrix(); } + const Zeus::CProjection& projection() const { return m_projection; } + + virtual void think() + { + + } +}; +} + + +#endif // URDE_CAMERA_HPP diff --git a/Editor/ModelViewer.hpp b/Editor/ModelViewer.hpp index 103586b82..82406e01e 100644 --- a/Editor/ModelViewer.hpp +++ b/Editor/ModelViewer.hpp @@ -21,15 +21,17 @@ class ModelViewer : public Space }; Value renderMode = Mode::Material; - Value cameraPosition; + Value cameraPosition; + Value cameraOrientation; + } m_state; const Space::State& spaceState() const { return m_state; } struct View : Specter::View { - Zeus::CProjection m_cameraProjection; }; + virtual Specter::View* buildContentView(Specter::ViewResources& res) { return nullptr; diff --git a/libSpecter b/libSpecter index c5dd30dd7..5e2800b1b 160000 --- a/libSpecter +++ b/libSpecter @@ -1 +1 @@ -Subproject commit c5dd30dd7d072666956050b5d5bfa4c325d18f56 +Subproject commit 5e2800b1bd316b6859c5b913b8e228f2c135424a From d936ce69aba433e86ce0654ec50e2818e4e81889 Mon Sep 17 00:00:00 2001 From: Zero-One101 Date: Sun, 17 Jan 2016 16:10:33 +0000 Subject: [PATCH 12/15] Hide commit information when none exists --- Editor/SplashScreen.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/Editor/SplashScreen.cpp b/Editor/SplashScreen.cpp index 4320ab179..c2906abc1 100644 --- a/Editor/SplashScreen.cpp +++ b/Editor/SplashScreen.cpp @@ -24,10 +24,6 @@ SplashScreen::SplashScreen(ViewManager& vm, Specter::ViewResources& res) m_vm(vm), m_textColor(res.themeData().uiText()), m_textColorClear(m_textColor), - m_buildInfoStr(HECL::Format("%s: %s\n%s: %s\n%s: %s", - vm.translateOr("branch", "Branch").c_str(), GIT_BRANCH, - vm.translateOr("commit", "Commit").c_str(), GIT_COMMIT_HASH, - vm.translateOr("date", "Date").c_str(), GIT_COMMIT_DATE)), m_newString(m_vm.translateOr("new_project", "New Project")), m_newProjBind(*this), m_openString(m_vm.translateOr("open_project", "Open Project")), @@ -35,6 +31,16 @@ SplashScreen::SplashScreen(ViewManager& vm, Specter::ViewResources& res) m_extractString(m_vm.translateOr("extract_game", "Extract Game")), m_extractProjBind(*this) { + if (GIT_COMMIT_DATE[0] != '\0' && + GIT_COMMIT_HASH[0] != '\0' && + GIT_BRANCH[0] != '\0') + { + m_buildInfoStr = HECL::Format("%s: %s\n%s: %s\n%s: %s", + vm.translateOr("branch", "Branch").c_str(), GIT_BRANCH, + vm.translateOr("commit", "Commit").c_str(), GIT_COMMIT_HASH, + vm.translateOr("date", "Date").c_str(), GIT_COMMIT_DATE); + } + m_openProjBind.m_openRecentMenuRoot.m_text = vm.translateOr("recent_projects", "Recent Projects"); m_textColorClear[3] = 0.0; commitResources(res); From e0c8d17d9019e1a54dae01df7723868ba0e46559 Mon Sep 17 00:00:00 2001 From: Phillip Stephens Date: Sun, 17 Jan 2016 16:00:11 -0800 Subject: [PATCH 13/15] Fix OPAC usage (WIP) --- DataSpec/DNAMP3/CMDLMaterials.cpp | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/DataSpec/DNAMP3/CMDLMaterials.cpp b/DataSpec/DNAMP3/CMDLMaterials.cpp index a4030d6bc..50ae08789 100644 --- a/DataSpec/DNAMP3/CMDLMaterials.cpp +++ b/DataSpec/DNAMP3/CMDLMaterials.cpp @@ -63,17 +63,14 @@ void MaterialSet::ConstructMaterial(Stream& out, material.header.flags.shadowOccluderMesh() ? "True" : "False"); - /* TODO: Some models enable both of these flags at once, why? - * And how do we handle this properly? - */ /* Blend factors */ - if (material.header.flags.additiveBlending()) - out << "new_material.game_settings.alpha_blend = 'ADD'\n" + if (material.header.flags.alphaBlending()) + out << "new_material.game_settings.alpha_blend = 'ALPHA'\n" "new_material.use_transparency = True\n" "new_material.transparency_method = 'RAYTRACE'\n" "new_material.alpha = 1.0\n"; - else if (material.header.flags.alphaBlending()) - out << "new_material.game_settings.alpha_blend = 'ALPHA'\n" + else if (material.header.flags.additiveBlending()) + out << "new_material.game_settings.alpha_blend = 'ADD'\n" "new_material.use_transparency = True\n" "new_material.transparency_method = 'RAYTRACE'\n" "new_material.alpha = 1.0\n"; @@ -81,6 +78,7 @@ void MaterialSet::ConstructMaterial(Stream& out, /* Texmap list */ out << "tex_maps = []\n" "pnode = None\n" + "anode = None\n" "rflv_tex_node = None\n"; /* Add PASSes */ @@ -100,9 +98,13 @@ void MaterialSet::ConstructMaterial(Stream& out, /* Connect final PASS */ out << "if pnode:\n" " new_nodetree.links.new(pnode.outputs['Next Color'], final_node.inputs['Color'])\n" - " new_nodetree.links.new(pnode.outputs['Next Alpha'], final_node.inputs['Alpha'])\n" "else:\n" " new_nodetree.links.new(kcolor_nodes[-1][0].outputs[0], final_node.inputs['Color'])\n" + "if anode:\n" + " new_nodetree.links.new(anode.outputs['Value'], final_node.inputs['Alpha'])\n" + "elif pnode:\n" + " new_nodetree.links.new(pnode.outputs['Next Alpha'], final_node.inputs['Alpha'])\n" + "else:\n" " new_nodetree.links.new(kcolor_nodes[-1][1].outputs[0], final_node.inputs['Alpha'])\n"; } @@ -281,7 +283,13 @@ void Material::SectionINT::constructNode(HECL::BlenderConnection::PyOutStream& o switch (Subtype(subtype.toUint32())) { case Subtype::OPAC: - out.format("new_material.retro_opac = %d\n", value); + { + GX::Color clr(value); + out.format("anode = new_nodetree.nodes.new('ShaderNodeValue')\n" + "anode.outputs['Value'].default_value = %f\n", + float(clr[3]) / float(0xff)); + out << "gridder.place_node(anode, 1)\n"; + } break; case Subtype::BLOD: out.format("new_material.retro_blod = %d\n", value); From 96facf238918bc48d9b7c268c4c5e042aac28ca5 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Sun, 17 Jan 2016 14:40:11 -1000 Subject: [PATCH 14/15] Initial icons build system --- Editor/CMakeLists.txt | 5 +- Editor/SplashScreen.cpp | 6 +- Editor/icons/CMakeLists.txt | 21 ++++ Editor/icons/icons.cpp | 0 Editor/icons/icons.hpp | 0 Editor/icons/icons.svg | 207 +++++++++++++++++++++++++++++++ Editor/icons/packicons.c | 241 ++++++++++++++++++++++++++++++++++++ hecl | 2 +- libSpecter | 2 +- 9 files changed, 478 insertions(+), 6 deletions(-) create mode 100644 Editor/icons/CMakeLists.txt create mode 100644 Editor/icons/icons.cpp create mode 100644 Editor/icons/icons.hpp create mode 100644 Editor/icons/icons.svg create mode 100644 Editor/icons/packicons.c diff --git a/Editor/CMakeLists.txt b/Editor/CMakeLists.txt index 0c3594666..a76383467 100644 --- a/Editor/CMakeLists.txt +++ b/Editor/CMakeLists.txt @@ -1,5 +1,6 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}) add_subdirectory(locale) +add_subdirectory(icons) if("${CMAKE_BUILD_TYPE}" STREQUAL "Release") option(RUDE_BINARY_CONFIGS @@ -17,18 +18,20 @@ endif() atdna(atdna_Space.cpp Space.hpp) atdna(atdna_ResourceBrowser.cpp ResourceBrowser.hpp) +atdna(atdna_ModelViewer.cpp ModelViewer.hpp) add_executable(urde WIN32 main.cpp Space.hpp Space.cpp atdna_Space.cpp SplashScreen.hpp SplashScreen.cpp ResourceBrowser.hpp ResourceBrowser.cpp atdna_ResourceBrowser.cpp - ModelViewer.hpp ModelViewer.cpp + ModelViewer.hpp ModelViewer.cpp atdna_ModelViewer.cpp ProjectManager.hpp ProjectManager.cpp ViewManager.hpp ViewManager.cpp) target_link_libraries(urde UrdeLocales + UrdeIcons RuntimeCommonCharacter RuntimeCommonInput RuntimeCommon diff --git a/Editor/SplashScreen.cpp b/Editor/SplashScreen.cpp index 4320ab179..78ab960e9 100644 --- a/Editor/SplashScreen.cpp +++ b/Editor/SplashScreen.cpp @@ -91,11 +91,11 @@ void SplashScreen::updateContentOpacity(float opacity) m_buildInfo->typesetGlyphs(m_buildInfoStr, clearColor); m_newButt.m_view.reset(new Specter::Button(res, *this, &m_newProjBind, m_newString, - Specter::Button::Style::Text)); + nullptr, Specter::Button::Style::Text)); m_openButt.m_view.reset(new Specter::Button(res, *this, &m_openProjBind, m_openString, - Specter::Button::Style::Text)); + nullptr, Specter::Button::Style::Text)); m_extractButt.m_view.reset(new Specter::Button(res, *this, &m_extractProjBind, m_extractString, - Specter::Button::Style::Text)); + nullptr, Specter::Button::Style::Text)); updateSize(); } diff --git a/Editor/icons/CMakeLists.txt b/Editor/icons/CMakeLists.txt new file mode 100644 index 000000000..efdd038c9 --- /dev/null +++ b/Editor/icons/CMakeLists.txt @@ -0,0 +1,21 @@ +include_directories(${LIBPNG_INCLUDE_DIR}) +add_executable(packicons packicons.c) +target_link_libraries(packicons ${PNG_LIB} ${ZLIB_LIBRARIES}) + +unset(INKSCAPE_BIN CACHE) +set(CMAKE_FIND_APPBUNDLE "NEVER") +find_program(INKSCAPE_BIN inkscape) +if(INKSCAPE_BIN STREQUAL "INKSCAPE_BIN-NOTFOUND") + message(STATUS "Inkscape not found; downloading icons") + file(DOWNLOAD "https://www.dropbox.com/s/wnj17dwgcsky0o9/icons.bin" + ${CMAKE_CURRENT_BINARY_DIR}/icons.bin SHOW_PROGRESS) +else() + message(STATUS "Inkscape found; will render icons locally") + add_custom_command(OUTPUT icons.bin COMMAND $ + ARGS ${INKSCAPE_BIN} ${CMAKE_CURRENT_SOURCE_DIR}/icons.svg + ${CMAKE_CURRENT_BINARY_DIR}/icons.bin + MAIN_DEPENDENCY icons.svg COMMENT "Generating icons.bin") +endif() + +bintoc(icons.c ${CMAKE_CURRENT_BINARY_DIR}/icons.bin URDE_ICONS) +add_library(UrdeIcons icons.cpp icons.hpp icons.bin icons.c) diff --git a/Editor/icons/icons.cpp b/Editor/icons/icons.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/Editor/icons/icons.hpp b/Editor/icons/icons.hpp new file mode 100644 index 000000000..e69de29bb diff --git a/Editor/icons/icons.svg b/Editor/icons/icons.svg new file mode 100644 index 000000000..c385489b6 --- /dev/null +++ b/Editor/icons/icons.svg @@ -0,0 +1,207 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Editor/icons/packicons.c b/Editor/icons/packicons.c new file mode 100644 index 000000000..eafada9cf --- /dev/null +++ b/Editor/icons/packicons.c @@ -0,0 +1,241 @@ +#include +#include +#include +#include +#include + +static int CountBits(uint32_t n) +{ + int ret = 0; + for (int i=0 ; i<32 ; ++i) + if (((n >> i) & 1) != 0) + ++ret; + return ret; +} + +int main(int argc, char* argv[]) +{ + if (argc < 4) + { + fprintf(stderr, "Usage: packicons \n"); + return 1; + } + + /* Validate inkscape */ + char command[2048]; + snprintf(command, 2048, "%s --version", argv[1]); + FILE* fp = popen(command, "r"); + if (!fp) + { + fprintf(stderr, "'%s' is not executable on this system\n", command); + return 1; + } + + char readback[8]; + if (fread(readback, 1, 8, fp) != 8 || strncmp(readback, "Inkscape", 8)) + { + fprintf(stderr, "'%s' did not return expected \"Inkscape\"\n", command); + pclose(fp); + return 1; + } + pclose(fp); + + /* Validate input */ + fp = fopen(argv[2], "rb"); + if (!fp) + { + fprintf(stderr, "'%s' is not able to be opened for reading as a regular file\n", argv[2]); + return 1; + } + fclose(fp); + +#ifdef _WIN32 + char* TMPDIR = getenv(L"TEMP"); + if (!TMPDIR) + TMPDIR = (char*)"\\Temp"; +#else + char* TMPDIR = getenv("TMPDIR"); + if (!TMPDIR) + TMPDIR = (char*)"/tmp"; +#endif + + FILE* ofp = fopen(argv[3], "wb"); + if (!ofp) + { + fprintf(stderr, "'%s' is not able to be opened for writing as a regular file\n", argv[3]); + return 1; + } + + int numMips = 0; + for (int i=512 ; i>=1 ; i/=2) + ++numMips; + + z_stream z = {}; + size_t rowSz = 0; + uLong rowSzC = 0; + png_bytep row; + png_bytep rowC; + + for (int i=512 ; i>=1 ; i/=2) + { + printf("Rendering icons @%dx%d\n", i, i); + fflush(stdout); + + snprintf(command, 2048, "%s --export-png=\"%s/icon_pack.png\" --export-width=%d --export-height=%d \"%s\"", + argv[1], TMPDIR, i, i, argv[2]); + fp = popen(command, "r"); + if (!fp) + { + fprintf(stderr, "'%s' is not executable on this system\n", command); + fclose(ofp); + return 1; + } + int status = pclose(fp); + if (WEXITSTATUS(status)) + { + fprintf(stderr, "'%s' failed\n", command); + fclose(ofp); + return 1; + } + + /* Get PNG data */ + snprintf(command, 2048, "%s/icon_pack.png", TMPDIR); + fp = fopen(command, "rb"); + if (!fp) + { + fprintf(stderr, "unable to open '%s' for reading\n", command); + fclose(ofp); + return 1; + } + + char header[8]; + fread(header, 1, 8, fp); + if (png_sig_cmp((png_const_bytep)header, 0, 8)) + { + fprintf(stderr, "invalid PNG signature in '%s'\n", command); + fclose(fp); + fclose(ofp); + return 1; + } + + png_structp pngRead = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!pngRead) + { + fprintf(stderr, "unable to initialize libpng\n"); + fclose(fp); + fclose(ofp); + return 1; + } + png_infop info = png_create_info_struct(pngRead); + if (!info) + { + fprintf(stderr, "unable to initialize libpng info\n"); + fclose(fp); + fclose(ofp); + return 1; + } + + if (setjmp(png_jmpbuf(pngRead))) + { + fprintf(stderr, "unable to initialize libpng I/O for '%s'\n", command); + fclose(fp); + fclose(ofp); + return 1; + } + + png_init_io(pngRead, fp); + png_set_sig_bytes(pngRead, 8); + + png_read_info(pngRead, info); + + png_uint_32 width = png_get_image_width(pngRead, info); + png_uint_32 height = png_get_image_height(pngRead, info); + png_byte colorType = png_get_color_type(pngRead, info); + png_byte bitDepth = png_get_bit_depth(pngRead, info); + + if (CountBits(width) != 1 || CountBits(height) != 1) + { + fprintf(stderr, "'%s' is not power-of-2 in one or both dimensions\n", command); + fclose(fp); + fclose(ofp); + return 1; + } + + if (colorType != PNG_COLOR_TYPE_RGB_ALPHA) + { + fprintf(stderr, "'%s' is not in RGBA color mode\n", command); + fclose(fp); + fclose(ofp); + return 1; + } + + if (bitDepth != 8) + { + fprintf(stderr, "'%s' is not 8 bits-per-channel\n", command); + fclose(fp); + fclose(ofp); + return 1; + } + + if (setjmp(png_jmpbuf(pngRead))) + { + fprintf(stderr, "unable to read image in '%s'\n", command); + fclose(fp); + fclose(ofp); + return 1; + } + + if (i == 512) + { + uint32_t fmt = htonl(16); + uint16_t w = htons(width); + uint16_t h = htons(height); + uint32_t mips = htonl(numMips); + fwrite(&fmt, 1, 4, ofp); + fwrite(&w, 1, 2, ofp); + fwrite(&h, 1, 2, ofp); + fwrite(&mips, 1, 4, ofp); + + rowSz = width*4; + rowSzC = compressBound(rowSz); + deflateInit(&z, Z_DEFAULT_COMPRESSION); + row = malloc(rowSz); + rowC = malloc(rowSzC); + } + + for (int r=0 ; r Date: Sun, 17 Jan 2016 16:12:01 -1000 Subject: [PATCH 15/15] packicons Win32 support --- Editor/icons/CMakeLists.txt | 13 ++++- Editor/icons/packicons.c | 96 +++++++++++++++++++++++++++++++++++-- 2 files changed, 103 insertions(+), 6 deletions(-) diff --git a/Editor/icons/CMakeLists.txt b/Editor/icons/CMakeLists.txt index efdd038c9..80edef7f5 100644 --- a/Editor/icons/CMakeLists.txt +++ b/Editor/icons/CMakeLists.txt @@ -1,10 +1,19 @@ -include_directories(${LIBPNG_INCLUDE_DIR}) +cmake_policy(SET CMP0053 OLD) + +include_directories(${LIBPNG_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR}) add_executable(packicons packicons.c) target_link_libraries(packicons ${PNG_LIB} ${ZLIB_LIBRARIES}) unset(INKSCAPE_BIN CACHE) set(CMAKE_FIND_APPBUNDLE "NEVER") -find_program(INKSCAPE_BIN inkscape) +if(WIN32) + find_program(INKSCAPE_BIN inkscape.exe PATHS + "$ENV{PROGRAMFILES}/Inkscape" + "$ENV{ProgramW6432}/Inkscape" + "$ENV{PROGRAMFILES(X86)}/Inkscape") +else() + find_program(INKSCAPE_BIN inkscape) +endif() if(INKSCAPE_BIN STREQUAL "INKSCAPE_BIN-NOTFOUND") message(STATUS "Inkscape not found; downloading icons") file(DOWNLOAD "https://www.dropbox.com/s/wnj17dwgcsky0o9/icons.bin" diff --git a/Editor/icons/packicons.c b/Editor/icons/packicons.c index eafada9cf..1bc2e48c9 100644 --- a/Editor/icons/packicons.c +++ b/Editor/icons/packicons.c @@ -1,9 +1,17 @@ #include #include #include +#include #include #include +#if _WIN32 +#define htonl(v) _byteswap_ulong(v) +#define htons(v) _byteswap_ushort(v) +#define WIN32_LEAN_AND_MEAN +#include +#endif + static int CountBits(uint32_t n) { int ret = 0; @@ -23,8 +31,66 @@ int main(int argc, char* argv[]) /* Validate inkscape */ char command[2048]; + FILE* fp; + +#if _WIN32 + STARTUPINFOA sinfo = {sizeof(STARTUPINFOA)}; + + HANDLE hChildStd_OUT_Rd = NULL; + HANDLE hChildStd_OUT_Wr = NULL; + + SECURITY_ATTRIBUTES saAttr; + saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); + saAttr.bInheritHandle = TRUE; + saAttr.lpSecurityDescriptor = NULL; + + // Create a pipe for the child process's STDOUT. + if (!CreatePipe(&hChildStd_OUT_Rd, &hChildStd_OUT_Wr, &saAttr, 0)) + { + fprintf(stderr, "unable to CreatePipe\n"); + return 1; + } + + // Ensure the read handle to the pipe for STDOUT is not inherited + if (!SetHandleInformation(hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0)) + { + fprintf(stderr, "unable to SetHandleInformation\n"); + return 1; + } + + sinfo.hStdError = hChildStd_OUT_Wr; + sinfo.hStdOutput = hChildStd_OUT_Wr; + sinfo.dwFlags |= STARTF_USESTDHANDLES; + + PROCESS_INFORMATION pinfo; + if (!CreateProcessA(argv[1], " --version", NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS, NULL, NULL, &sinfo, &pinfo)) + { + LPSTR messageBuffer = NULL; + FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL); + fprintf(stderr, "unable to launch inkscape from %s: %s\n", argv[1], messageBuffer); + return 1; + } + CloseHandle(hChildStd_OUT_Wr); + CloseHandle(pinfo.hThread); + + char readback[8]; + DWORD bytesRead = 0; + if (!ReadFile(hChildStd_OUT_Rd, readback, 8, &bytesRead, NULL) || bytesRead != 8 || + strncmp(readback, "Inkscape", 8)) + { + fprintf(stderr, "'%s' did not return expected \"Inkscape\"\n", command); + CloseHandle(hChildStd_OUT_Rd); + CloseHandle(pinfo.hProcess); + return 1; + } + CloseHandle(hChildStd_OUT_Rd); + WaitForSingleObject(pinfo.hProcess, INFINITE); + CloseHandle(pinfo.hProcess); + +#else snprintf(command, 2048, "%s --version", argv[1]); - FILE* fp = popen(command, "r"); + fp = popen(command, "r"); if (!fp) { fprintf(stderr, "'%s' is not executable on this system\n", command); @@ -40,6 +106,8 @@ int main(int argc, char* argv[]) } pclose(fp); +#endif + /* Validate input */ fp = fopen(argv[2], "rb"); if (!fp) @@ -50,7 +118,7 @@ int main(int argc, char* argv[]) fclose(fp); #ifdef _WIN32 - char* TMPDIR = getenv(L"TEMP"); + char* TMPDIR = getenv("TEMP"); if (!TMPDIR) TMPDIR = (char*)"\\Temp"; #else @@ -70,7 +138,7 @@ int main(int argc, char* argv[]) for (int i=512 ; i>=1 ; i/=2) ++numMips; - z_stream z = {}; + z_stream z = {0}; size_t rowSz = 0; uLong rowSzC = 0; png_bytep row; @@ -81,6 +149,25 @@ int main(int argc, char* argv[]) printf("Rendering icons @%dx%d\n", i, i); fflush(stdout); +#if _WIN32 + snprintf(command, 2048, " --export-png=\"%s/icon_pack.png\" --export-width=%d --export-height=%d \"%s\"", + TMPDIR, i, i, argv[2]); + + STARTUPINFOA sinfo = {sizeof(STARTUPINFOA)}; + PROCESS_INFORMATION pinfo; + if (!CreateProcessA(argv[1], command, NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS, NULL, NULL, &sinfo, &pinfo)) + { + LPSTR messageBuffer = NULL; + FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL); + fprintf(stderr, "unable to launch inkscape from %s: %s\n", argv[1], messageBuffer); + return 1; + } + CloseHandle(pinfo.hThread); + WaitForSingleObject(pinfo.hProcess, INFINITE); + CloseHandle(pinfo.hProcess); + +#else snprintf(command, 2048, "%s --export-png=\"%s/icon_pack.png\" --export-width=%d --export-height=%d \"%s\"", argv[1], TMPDIR, i, i, argv[2]); fp = popen(command, "r"); @@ -97,6 +184,7 @@ int main(int argc, char* argv[]) fclose(ofp); return 1; } +#endif /* Get PNG data */ snprintf(command, 2048, "%s/icon_pack.png", TMPDIR); @@ -203,7 +291,7 @@ int main(int argc, char* argv[]) rowC = malloc(rowSzC); } - for (int r=0 ; r