This commit is contained in:
Jack Andersen 2016-01-17 16:34:23 -10:00
commit 323367466e
22 changed files with 901 additions and 32 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
version.h
*.user
.DS_Store

View File

@ -4,12 +4,29 @@ 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")
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")

View File

@ -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

View File

@ -64,13 +64,13 @@ void MaterialSet::ConstructMaterial(Stream& out,
/* 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";
@ -78,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 */
@ -97,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";
}
@ -278,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);

View File

@ -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,21 @@ 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)
ViewManager.hpp ViewManager.cpp
Camera.hpp Camera.cpp)
target_link_libraries(urde
UrdeLocales
UrdeIcons
RuntimeCommonCharacter
RuntimeCommonInput
RuntimeCommon

0
Editor/Camera.cpp Normal file
View File

36
Editor/Camera.hpp Normal file
View File

@ -0,0 +1,36 @@
#ifndef URDE_CAMERA_HPP
#define URDE_CAMERA_HPP
#include <CProjection.hpp>
#include <CFrustum.hpp>
#include <CQuaternion.hpp>
#include <CVector3f.hpp>
#include <Math.hpp>
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

View File

@ -1,8 +1,78 @@
#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<Mode> renderMode = Mode::Material;
Value<Zeus::CVector3f> cameraPosition;
Value<Zeus::CQuaternion> cameraOrientation;
} m_state;
const Space::State& spaceState() const { return m_state; }
struct View : Specter::View
{
};
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

View File

@ -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;
}

View File

@ -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::SubNodeData> 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<Specter::View> Space::SpaceSelectBind::buildMenu(const Specter::Button* button)
{
return std::unique_ptr<Specter::View>(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);
@ -131,26 +159,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
}
}

View File

@ -32,12 +32,74 @@ public:
SplitSpace,
TestSpace,
ResourceBrowser,
ModelViewer
};
struct State : Athena::io::DNAYaml<Athena::BigEndian> {Delete _d;};
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<SubNodeData> 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<SubNode> 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<Specter::View> buildMenu(const Specter::Button* button);
SpaceSelectBind(Space& space) : m_space(space) {}
} m_spaceSelectBind;
std::unique_ptr<Specter::Button> m_spaceSelectButton;
protected:
friend class ViewManager;
friend class RootSpace;
@ -45,7 +107,7 @@ protected:
Class m_class = Class::None;
Space* m_parent;
std::unique_ptr<Specter::Space> 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;
@ -88,7 +150,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));

View File

@ -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);
@ -53,6 +59,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());
@ -88,11 +97,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();
}

View File

@ -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)

View File

@ -4,6 +4,7 @@
#include "SplashScreen.hpp"
#include "locale/locale.hpp"
#include "ResourceBrowser.hpp"
#include <cstdio>
using YAMLNode = Athena::io::YAMLNode;
@ -36,7 +37,6 @@ void ViewManager::RootSpaceViewBuilt(Specter::View *view)
std::vector<Specter::View*>& 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();
}
@ -76,20 +76,77 @@ 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()))
{
Space::SpaceMenuNode::initializeStrings(*this);
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)
{

View File

@ -29,7 +29,9 @@ class ViewManager : public Specter::IViewManager
std::unique_ptr<RootSpace> m_rootSpace;
Specter::View* m_rootSpaceView = nullptr;
HECL::SystemString m_recentProjectsPath;
std::vector<HECL::SystemString> m_recentProjects;
HECL::SystemString m_recentFilesPath;
std::vector<HECL::SystemString> m_recentFiles;
bool m_updatePf = false;

View File

@ -0,0 +1,30 @@
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")
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"
${CMAKE_CURRENT_BINARY_DIR}/icons.bin SHOW_PROGRESS)
else()
message(STATUS "Inkscape found; will render icons locally")
add_custom_command(OUTPUT icons.bin COMMAND $<TARGET_FILE:packicons>
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)

0
Editor/icons/icons.cpp Normal file
View File

0
Editor/icons/icons.hpp Normal file
View File

207
Editor/icons/icons.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 37 KiB

329
Editor/icons/packicons.c Normal file
View File

@ -0,0 +1,329 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <zlib.h>
#include <png.h>
#if _WIN32
#define htonl(v) _byteswap_ulong(v)
#define htons(v) _byteswap_ushort(v)
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#endif
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 <inkscape-bin> <in.svg> <out.bin>\n");
return 1;
}
/* 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]);
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);
#endif
/* 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("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 = {0};
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);
#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");
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;
}
#endif
/* 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 (png_uint_32 r=0 ; r<height ; ++r)
{
png_read_row(pngRead, row, NULL);
z.next_in = row;
z.avail_in = rowSz;
z.next_out = rowC;
z.avail_out = rowSzC;
z.total_out = 0;
deflate(&z, Z_NO_FLUSH);
fwrite(rowC, 1, z.total_out, ofp);
}
rowSz /= 2;
png_destroy_read_struct(&pngRead, &info, NULL);
fclose(fp);
}
if (rowSzC)
{
int finishCycle = Z_OK;
while (finishCycle != Z_STREAM_END)
{
z.next_out = rowC;
z.avail_out = rowSzC;
z.total_out = 0;
finishCycle = deflate(&z, Z_FINISH);
fwrite(rowC, 1, z.total_out, ofp);
}
deflateEnd(&z);
free(row);
free(rowC);
}
fclose(ofp);
return 0;
}

2
hecl

@ -1 +1 @@
Subproject commit 5d0c80b9e603ecb2762b281d8736d21a324c3e76
Subproject commit 7978e31e6fbbbd45915c2684ee0fb1a376020255

@ -1 +1 @@
Subproject commit 2490aa3bb82860fa2969d2cc797324d846e3b51c
Subproject commit cd54225b2af5cd2978b0ad3fab10561693fc54b2