Add editor portion of rendering flow

This commit is contained in:
Jack Andersen 2016-01-04 14:01:02 -10:00
parent 5de9028a51
commit 769a20d9dc
11 changed files with 318 additions and 57 deletions

View File

@ -4,6 +4,10 @@ add_subdirectory(locale)
atdna(atdna_Space.cpp Space.hpp)
atdna(atdna_ResourceOutliner.cpp ResourceOutliner.hpp)
if("${CMAKE_BUILD_TYPE}" STREQUAL "Release")
add_definitions("-DRUDE_BINARY_CONFIGS=1")
endif()
add_executable(rude WIN32
main.cpp
Space.hpp Space.cpp atdna_Space.cpp

View File

@ -26,6 +26,7 @@ bool ProjectManager::newProject(const HECL::SystemString& path)
return false;
}
HECL::MakeDir(path.c_str());
m_proj.reset(new HECL::Database::Project(path));
if (!*m_proj)
{
@ -33,6 +34,12 @@ bool ProjectManager::newProject(const HECL::SystemString& path)
return false;
}
m_vm.SetupEditorView();
saveProject();
m_vm.m_mainWindow->setTitle(m_proj->getProjectRootPath().getLastComponent());
m_vm.DismissSplash();
m_vm.FadeInEditors();
return true;
}
@ -52,12 +59,55 @@ bool ProjectManager::openProject(const HECL::SystemString& path)
return false;
}
HECL::ProjectPath rudeSpacesPath(*m_proj, _S(".hecl/rude_spaces.yaml"));
if (rudeSpacesPath.getPathType() == HECL::ProjectPath::Type::File)
{
#ifdef RUDE_BINARY_CONFIGS
HECL::ProjectPath rudeSpacesPath(*m_proj, _S(".hecl/rude_spaces.bin"));
Athena::io::FileReader r(rudeSpacesPath.getAbsolutePath(), 32 * 1024, false);
if (r.hasError())
goto makeDefault;
m_vm.SetupEditorView(r);
#else
HECL::ProjectPath rudeSpacesPath(*m_proj, _S(".hecl/rude_spaces.yaml"));
FILE* fp = HECL::Fopen(rudeSpacesPath.getAbsolutePath().c_str(), _S("r"));
Athena::io::YAMLDocReader r;
if (!fp)
goto makeDefault;
yaml_parser_set_input_file(r.getParser(), fp);
if (!r.ValidateClassType(r.getParser(), "RudeSpacesState"))
{
fclose(fp);
goto makeDefault;
}
r.reset();
fseek(fp, 0, SEEK_SET);
yaml_parser_set_input_file(r.getParser(), fp);
if (!r.parse())
{
fclose(fp);
goto makeDefault;
}
fclose(fp);
m_vm.SetupEditorView(r);
#endif
m_vm.m_mainWindow->setTitle(m_proj->getProjectRootPath().getLastComponent());
m_vm.DismissSplash();
m_vm.FadeInEditors();
return true;
makeDefault:
m_vm.SetupEditorView();
saveProject();
m_vm.m_mainWindow->setTitle(m_proj->getProjectRootPath().getLastComponent());
m_vm.DismissSplash();
m_vm.FadeInEditors();
return true;
}
@ -66,4 +116,52 @@ bool ProjectManager::extractGame(const HECL::SystemString& path)
return false;
}
bool ProjectManager::saveProject()
{
if (!m_proj)
return false;
#ifdef RUDE_BINARY_CONFIGS
HECL::ProjectPath rudeSpacesPath(*m_proj, _S(".hecl/rude_spaces.bin"));
Athena::io::FileReader r(rudeSpacesPath.getAbsolutePath(), 32 * 1024, false);
if (r.hasError())
return false;
m_vm.SetupEditorView(r);
#else
HECL::ProjectPath oldSpacesPath(*m_proj, _S(".hecl/~rude_spaces.yaml"));
FILE* fp = HECL::Fopen(oldSpacesPath.getAbsolutePath().c_str(), _S("w"));
if (!fp)
return false;
Athena::io::YAMLDocWriter w("RudeSpacesState");
yaml_emitter_set_output_file(w.getEmitter(), fp);
if (!w.open())
{
fclose(fp);
return false;
}
m_vm.SaveEditorView(w);
if (!w.finish())
{
fclose(fp);
return false;
}
w.close();
fclose(fp);
HECL::ProjectPath newSpacesPath(*m_proj, _S(".hecl/rude_spaces.yaml"));
HECL::Unlink(newSpacesPath.getAbsolutePath().c_str());
HECL::Rename(oldSpacesPath.getAbsolutePath().c_str(),
newSpacesPath.getAbsolutePath().c_str());
#endif
return true;
}
}

View File

@ -2,11 +2,20 @@
#define RUDE_PROJECT_MANAGER_HPP
#include <HECL/Database.hpp>
#include <Athena/DNAYaml.hpp>
namespace RUDE
{
class ViewManager;
#ifdef RUDE_BINARY_CONFIGS
using ConfigReader = Athena::io::IStreamReader;
using ConfigWriter = Athena::io::IStreamWriter;
#else
using ConfigReader = Athena::io::YAMLDocReader;
using ConfigWriter = Athena::io::YAMLDocWriter;
#endif
class ProjectManager
{
ViewManager& m_vm;
@ -20,6 +29,8 @@ public:
bool openProject(const HECL::SystemString& path);
bool extractGame(const HECL::SystemString& path);
bool saveProject();
};
}

View File

@ -1 +1,6 @@
#include "ResourceOutliner.hpp"
namespace RUDE
{
}

View File

@ -2,6 +2,7 @@
#define RUDE_RESOURCE_OUTLINER_HPP
#include "Space.hpp"
#include "ViewManager.hpp"
namespace RUDE
{
@ -12,17 +13,33 @@ class ResourceOutliner : public Space
{
DECL_YAML
} m_state;
Space::State& spaceState() {return m_state;}
const Space::State& spaceState() const {return m_state;}
struct View : public Specter::View
{
ResourceOutliner& m_ro;
View(ResourceOutliner& ro, Specter::ViewResources& res)
: Specter::View(res, ro.m_vm.rootView()), m_ro(ro)
{
commitResources(res);
setBackground(Zeus::CColor::skBlue);
}
};
std::unique_ptr<View> m_view;
public:
ResourceOutliner(ViewManager& vm) : Space(vm, Class::ResourceOutliner) {}
ResourceOutliner(ViewManager& vm, Athena::io::YAMLDocReader& r)
ResourceOutliner(ViewManager& vm, ConfigReader& r)
: ResourceOutliner(vm)
{
m_state.read(r);
}
Specter::View* buildContentView(Specter::ViewResources& res) {return nullptr;}
Specter::View* buildContentView(Specter::ViewResources& res)
{
m_view.reset(new View(*this, res));
return m_view.get();
}
};
}

View File

@ -4,24 +4,40 @@
namespace RUDE
{
static LogVisor::LogModule Log("RUDE::Space");
Specter::Space* Space::buildSpaceView(Specter::ViewResources& res)
Specter::View* Space::buildSpaceView(Specter::ViewResources& res)
{
m_space.reset(new Specter::Space(res, m_vm.rootView(), Specter::Toolbar::Position::Bottom));
Specter::View* sview = buildContentView(res);
m_space->setContentView(sview);
if (usesToolbar())
buildToolbarView(res, m_space->toolbar());
return m_space.get();
}
Specter::View* SplitSpace::buildContentView(Specter::ViewResources& res)
{
m_splitView.reset(new Specter::SplitView(res, m_vm.rootView(), Specter::SplitView::Axis::Horizontal));
if (m_slots[0])
m_splitView->setContentView(0, m_slots[0]->buildSpaceView(res));
if (m_slots[1])
m_splitView->setContentView(1, m_slots[1]->buildSpaceView(res));
return m_splitView.get();
}
Space* Space::NewSpaceFromYAMLStream(ViewManager& vm, Athena::io::YAMLDocReader& r)
void SplitSpace::setSpaceSlot(unsigned slot, std::unique_ptr<Space>&& space)
{
StateHead head;
head.read(r);
switch (head.cls)
if (slot > 1)
Log.report(LogVisor::FatalError, "invalid slot %u for SplitView", slot);
m_slots[slot] = std::move(space);
}
template <class Reader>
static Space* BuildNewSpace(ViewManager& vm, Space::Class cls, Reader& r)
{
using Class = Space::Class;
switch (cls)
{
case Class::SplitSpace:
return new SplitSpace(vm, r);
@ -32,4 +48,15 @@ Space* Space::NewSpaceFromYAMLStream(ViewManager& vm, Athena::io::YAMLDocReader&
return nullptr;
}
Space* Space::NewSpaceFromConfigStream(ViewManager& vm, ConfigReader& r)
{
#ifdef RUDE_BINARY_CONFIGS
Class cls = Class(r.readUint32Big());
return BuildNewSpace(vm, cls, r);
#else
Class cls = Class(r.readUint32("class"));
return BuildNewSpace(vm, cls, r);
#endif
}
}

View File

@ -3,6 +3,7 @@
#include <Athena/DNAYaml.hpp>
#include <Specter/Specter.hpp>
#include "ProjectManager.hpp"
namespace Specter
{
@ -17,7 +18,11 @@ class ViewManager;
class Space
{
friend class SplitSpace;
public:
Space(const Space& other) = delete;
Space& operator=(const Space& other) = delete;
enum class Class
{
None,
@ -26,14 +31,8 @@ public:
ResourceOutliner,
};
struct StateHead : Athena::io::DNAYaml<Athena::BigEndian>
{
DECL_YAML
Value<Class> cls;
};
struct State : Athena::io::DNAYaml<Athena::BigEndian> {Delete _d;};
static Space* NewSpaceFromYAMLStream(ViewManager& vm, Athena::io::YAMLDocReader& r);
static Space* NewSpaceFromConfigStream(ViewManager& vm, ConfigReader& r);
protected:
friend class ViewManager;
@ -43,39 +42,101 @@ protected:
Space(ViewManager& vm, Class cls) : m_vm(vm), m_class(cls) {}
/* Allows common Space code to access DNA-encoded state */
virtual Space::State& spaceState()=0;
virtual const Space::State& spaceState() const=0;
/* Structural control */
virtual bool usesToolbar() const {return false;}
virtual void buildToolbarView(Specter::ViewResources& res, Specter::Toolbar& tb) {}
virtual Specter::View* buildContentView(Specter::ViewResources& res)=0;
Specter::Space* buildSpaceView(Specter::ViewResources& res);
virtual Specter::View* buildSpaceView(Specter::ViewResources& res);
public:
virtual void saveState(Athena::io::IStreamWriter& w) const
{
w.writeUint32Big(atUint32(m_class));
spaceState().write(w);
}
virtual void saveState(Athena::io::YAMLDocWriter& w) const
{
w.writeUint32("class", atUint32(m_class));
spaceState().write(w);
}
virtual void think() {}
};
class SplitSpace : public Space
{
friend class ViewManager;
std::unique_ptr<Space> m_a;
std::unique_ptr<Space> m_b;
std::unique_ptr<Space> m_slots[2];
std::unique_ptr<Specter::SplitView> m_splitView;
struct State : Space::State
{
DECL_YAML
Value<float> split;
} m_state;
Space::State& spaceState() {return m_state;}
const Space::State& spaceState() const {return m_state;}
public:
SplitSpace(ViewManager& vm) : Space(vm, Class::SplitSpace) {}
SplitSpace(ViewManager& vm, Athena::io::YAMLDocReader& r)
SplitSpace(ViewManager& vm, ConfigReader& r)
: SplitSpace(vm)
{
m_state.read(r);
m_a.reset(NewSpaceFromYAMLStream(vm, r));
m_b.reset(NewSpaceFromYAMLStream(vm, r));
#ifdef RUDE_BINARY_CONFIGS
m_slots[0].reset(NewSpaceFromConfigStream(vm, r));
m_slots[1].reset(NewSpaceFromConfigStream(vm, r));
#else
r.enterSubRecord("slot0");
m_slots[0].reset(NewSpaceFromConfigStream(vm, r));
r.leaveSubRecord();
r.enterSubRecord("slot1");
m_slots[1].reset(NewSpaceFromConfigStream(vm, r));
r.leaveSubRecord();
#endif
}
void saveState(Athena::io::IStreamWriter& w) const
{
w.writeUint32Big(atUint32(m_class));
m_state.write(w);
if (m_slots[0])
m_slots[0]->saveState(w);
else
w.writeUint32Big(0);
if (m_slots[1])
m_slots[1]->saveState(w);
else
w.writeUint32Big(0);
}
void saveState(Athena::io::YAMLDocWriter& w) const
{
w.writeUint32("class", atUint32(m_class));
m_state.write(w);
w.enterSubRecord("slot0");
if (m_slots[0])
m_slots[0]->saveState(w);
else
w.writeUint32("class", 0);
w.leaveSubRecord();
w.enterSubRecord("slot1");
if (m_slots[1])
m_slots[1]->saveState(w);
else
w.writeUint32("class", 0);
w.leaveSubRecord();
}
void setSpaceSlot(unsigned slot, std::unique_ptr<Space>&& space);
Specter::View* buildSpaceView(Specter::ViewResources& res) {return buildContentView(res);}
Specter::View* buildContentView(Specter::ViewResources& res);
};

View File

@ -3,6 +3,7 @@
#include "Specter/Space.hpp"
#include "SplashScreen.hpp"
#include "locale/locale.hpp"
#include "ResourceOutliner.hpp"
using YAMLNode = Athena::io::YAMLNode;
@ -11,43 +12,62 @@ namespace RUDE
Specter::View* ViewManager::BuildSpaceViews(RUDE::Space* space)
{
Specter::Space* sspace = space->buildSpaceView(m_viewResources);
Specter::View* sview = space->buildContentView(m_viewResources);
sspace->setContentView(sview);
if (space->usesToolbar())
space->buildToolbarView(m_viewResources, sspace->toolbar());
return sspace;
m_rootSpaceView = space->buildSpaceView(m_viewResources);
return m_rootSpaceView;
}
void ViewManager::SetupRootView()
Specter::RootView* ViewManager::SetupRootView()
{
m_rootView.reset(new Specter::RootView(*this, m_viewResources, m_mainWindow.get()));
m_rootView->setBackground(Zeus::CColor::skBlack);
m_rootView->updateSize();
return m_rootView.get();
}
void ViewManager::SetupSplashView()
SplashScreen* ViewManager::SetupSplashView()
{
m_splash.reset(new SplashScreen(*this, m_viewResources));
m_rootView->setContentView(m_splash.get());
m_rootView->updateSize();
m_showSplash = true;
if (!m_showSplash)
m_splash->close(true);
return m_splash.get();
}
void ViewManager::SetupEditorView()
{
m_rootSpace.reset(new SplitSpace(*this));
m_rootView->setContentView(BuildSpaceViews(m_rootSpace.get()));
SplitSpace* split = new SplitSpace(*this);
split->setSpaceSlot(0, std::make_unique<ResourceOutliner>(*this));
split->setSpaceSlot(1, std::make_unique<ResourceOutliner>(*this));
m_rootSpace.reset(split);
std::vector<Specter::View*>& cViews = m_rootView->accessContentViews();
cViews.clear();
cViews.push_back(BuildSpaceViews(m_rootSpace.get()));
cViews.push_back(m_splash.get());
m_rootView->updateSize();
m_showSplash = false;
}
void ViewManager::SetupEditorView(Athena::io::YAMLDocReader& r)
void ViewManager::SetupEditorView(ConfigReader& r)
{
m_rootSpace.reset(Space::NewSpaceFromYAMLStream(*this, r));
m_rootView->setContentView(BuildSpaceViews(m_rootSpace.get()));
m_rootSpace.reset(Space::NewSpaceFromConfigStream(*this, r));
std::vector<Specter::View*>& cViews = m_rootView->accessContentViews();
cViews.clear();
cViews.push_back(BuildSpaceViews(m_rootSpace.get()));
cViews.push_back(m_splash.get());
m_rootView->updateSize();
}
void ViewManager::SaveEditorView(ConfigWriter& w)
{
if (!m_rootSpace)
return;
m_rootSpace->saveState(w);
}
void ViewManager::DismissSplash()
{
if (!m_showSplash)
return;
m_showSplash = false;
m_splash->close();
}
ViewManager::ViewManager(HECL::Runtime::FileStoreManager& fileMgr, HECL::CVarManager& cvarMgr)
@ -78,8 +98,10 @@ void ViewManager::init(boo::IApplication* app)
boo::IGraphicsDataFactory* gf = m_mainWindow->getMainContextDataFactory();
m_viewResources.init(gf, &m_fontCache, Specter::ThemeData(), pixelFactor);
m_viewResources.prepFontCacheAsync(m_mainWindow.get());
SetupRootView();
SetupSplashView();
Specter::RootView* root = SetupRootView();
m_showSplash = true;
root->accessContentViews().push_back(SetupSplashView());
root->updateSize();
m_mainWindow->setWaitCursor(false);
}
@ -89,19 +111,29 @@ bool ViewManager::proc()
boo::IGraphicsCommandQueue* gfxQ = m_mainWindow->getCommandQueue();
if (m_rootView->isDestroyed())
return false;
if (m_updatePf)
{
m_viewResources.resetPixelFactor(m_reqPf);
SetupRootView();
if (m_showSplash)
SetupSplashView();
else
SetupEditorView();
Specter::RootView* root = SetupRootView();
std::vector<Specter::View*>& cViews = root->accessContentViews();
if (m_rootSpace)
cViews.push_back(BuildSpaceViews(m_rootSpace.get()));
cViews.push_back(SetupSplashView());
root->updateSize();
m_updatePf = false;
}
m_rootView->dispatchEvents();
if (m_showSplash)
if (m_rootSpace)
m_rootSpace->think();
if (m_splash)
m_splash->think();
++m_editorFrames;
if (m_rootSpaceView && m_editorFrames <= 30)
m_rootSpaceView->setMultiplyColor(Zeus::CColor::lerp({1,1,1,0}, {1,1,1,1}, m_editorFrames / 30.0));
m_rootView->draw(gfxQ);
gfxQ->execute();
m_mainWindow->waitForRetrace();

View File

@ -24,6 +24,7 @@ class ViewManager : public Specter::IViewManager
std::unique_ptr<Specter::RootView> m_rootView;
std::unique_ptr<SplashScreen> m_splash;
std::unique_ptr<Space> m_rootSpace;
Specter::View* m_rootSpaceView = nullptr;
std::vector<HECL::SystemString> m_recentProjects;
std::vector<HECL::SystemString> m_recentFiles;
@ -32,12 +33,17 @@ class ViewManager : public Specter::IViewManager
float m_reqPf;
Specter::View* BuildSpaceViews(RUDE::Space* space);
void SetupRootView();
void SetupSplashView();
Specter::RootView* SetupRootView();
SplashScreen* SetupSplashView();
void SetupEditorView();
void SetupEditorView(Athena::io::YAMLDocReader& r);
void SetupEditorView(ConfigReader& r);
void SaveEditorView(ConfigWriter& w);
bool m_showSplash = false;
void DismissSplash();
unsigned m_editorFrames = 120;
void FadeInEditors() {m_editorFrames = 0;}
public:
ViewManager(HECL::Runtime::FileStoreManager& fileMgr, HECL::CVarManager& cvarMgr);

2
hecl

@ -1 +1 @@
Subproject commit 69bddf2a5fcd05c4c92de4601a1a55409e65ce5c
Subproject commit 02d87ba687d00d987f531e676829494678041ebe

@ -1 +1 @@
Subproject commit f7bd80bfe01d30456dfbcf2eaa3bf45c80d43a0c
Subproject commit 2bba788ee3fe5844a695f39ce06b8f5ee3e033e0