2
0
mirror of https://github.com/AxioDL/metaforce.git synced 2025-07-03 12:35:51 +00:00

New code style refactor

This commit is contained in:
Jack Andersen 2018-12-07 19:24:02 -10:00
parent 4fc3e42912
commit dcbc001cd2
54 changed files with 7939 additions and 9417 deletions

View File

@ -4,130 +4,117 @@
#include "specter/Control.hpp" #include "specter/Control.hpp"
#include "specter/Icon.hpp" #include "specter/Icon.hpp"
namespace specter namespace specter {
{
class Button : public Control class Button : public Control {
{
public: public:
enum class Style enum class Style {
{ Block,
Block, Text,
Text, };
};
private: private:
Style m_style; Style m_style;
IButtonBinding::MenuStyle m_menuStyle = IButtonBinding::MenuStyle::None; IButtonBinding::MenuStyle m_menuStyle = IButtonBinding::MenuStyle::None;
zeus::CColor m_textColor; zeus::CColor m_textColor;
zeus::CColor m_bgColor; zeus::CColor m_bgColor;
std::string m_textStr; std::string m_textStr;
std::unique_ptr<TextView> m_text; std::unique_ptr<TextView> m_text;
std::unique_ptr<IconView> m_icon; std::unique_ptr<IconView> m_icon;
SolidShaderVert m_verts[40]; SolidShaderVert m_verts[40];
VertexBufferBindingSolid m_vertsBinding; VertexBufferBindingSolid m_vertsBinding;
void _loadVerts() void _loadVerts() { m_vertsBinding.load<decltype(m_verts)>(m_verts); }
{
m_vertsBinding.load<decltype(m_verts)>(m_verts);
}
RectangleConstraint m_constraint; RectangleConstraint m_constraint;
int m_nomWidth, m_nomHeight; int m_nomWidth, m_nomHeight;
int m_textWidth, m_textIconWidth; int m_textWidth, m_textIconWidth;
struct ButtonTarget : View struct ButtonTarget : View {
{ Button& m_button;
Button& m_button;
bool m_pressed = false; bool m_pressed = false;
bool m_hovered = false; bool m_hovered = false;
void setInactive(); void setInactive();
void setHover(); void setHover();
void setPressed(); void setPressed();
void setDisabled(); void setDisabled();
void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseEnter(const boo::SWindowCoord&);
void mouseLeave(const boo::SWindowCoord&);
ButtonTarget(ViewResources& res, Button& button) : View(res, button), m_button(button) {}
};
ViewChild<std::unique_ptr<ButtonTarget>> m_buttonTarget;
struct MenuTarget : View
{
Button& m_button;
bool m_pressed = false;
bool m_hovered = false;
void setInactive();
void setHover();
void setPressed();
void setDisabled();
void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseEnter(const boo::SWindowCoord&);
void mouseLeave(const boo::SWindowCoord&);
MenuTarget(ViewResources& res, Button& button) : View(res, button), m_button(button) {}
};
ViewChild<std::unique_ptr<MenuTarget>> m_menuTarget;
ViewChild<std::unique_ptr<View>> m_modalMenu;
public:
class Resources
{
friend class ViewResources;
friend class Button;
void init(boo::IGraphicsDataFactory::Context& ctx, const IThemeData& theme);
void destroy() {}
};
~Button() {closeMenu({});}
Button(ViewResources& res, View& parentView,
IButtonBinding* controlBinding, std::string_view text, Icon* icon=nullptr,
Style style=Style::Block, const zeus::CColor& bgColor=zeus::CColor::skWhite,
RectangleConstraint constraint=RectangleConstraint());
Button(ViewResources& res, View& parentView,
IButtonBinding* controlBinding, std::string_view text, const zeus::CColor& textColor,
Icon* icon=nullptr, Style style=Style::Block, const zeus::CColor& bgColor=zeus::CColor::skWhite,
RectangleConstraint constraint=RectangleConstraint());
void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey); void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey); void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseMove(const boo::SWindowCoord&); void mouseEnter(const boo::SWindowCoord&);
void mouseLeave(const boo::SWindowCoord&); void mouseLeave(const boo::SWindowCoord&);
void think(); ButtonTarget(ViewResources& res, Button& button) : View(res, button), m_button(button) {}
void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub); };
void draw(boo::IGraphicsCommandQueue* gfxQ); ViewChild<std::unique_ptr<ButtonTarget>> m_buttonTarget;
void setText(std::string_view text, const zeus::CColor& textColor); struct MenuTarget : View {
void setText(std::string_view text); Button& m_button;
void setIcon(Icon* icon=nullptr);
std::string_view getText() const {return m_textStr;}
void colorGlyphs(const zeus::CColor& newColor);
int nominalWidth() const {return m_nomWidth;}
int nominalHeight() const {return m_nomHeight;}
void closeMenu(const boo::SWindowCoord& coord); bool m_pressed = false;
ViewChild<std::unique_ptr<View>>& getMenu() {return m_modalMenu;} bool m_hovered = false;
void setMultiplyColor(const zeus::CColor& color) void setInactive();
{ void setHover();
View::setMultiplyColor(color); void setPressed();
m_viewVertBlock.m_color = color; void setDisabled();
if (m_viewVertBlockBuf)
m_viewVertBlockBuf.access().finalAssign(m_viewVertBlock); void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
m_text->setMultiplyColor(color); void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
if (m_icon) void mouseEnter(const boo::SWindowCoord&);
m_icon->setMultiplyColor(color); void mouseLeave(const boo::SWindowCoord&);
} MenuTarget(ViewResources& res, Button& button) : View(res, button), m_button(button) {}
};
ViewChild<std::unique_ptr<MenuTarget>> m_menuTarget;
ViewChild<std::unique_ptr<View>> m_modalMenu;
public:
class Resources {
friend class ViewResources;
friend class Button;
void init(boo::IGraphicsDataFactory::Context& ctx, const IThemeData& theme);
void destroy() {}
};
~Button() { closeMenu({}); }
Button(ViewResources& res, View& parentView, IButtonBinding* controlBinding, std::string_view text,
Icon* icon = nullptr, Style style = Style::Block, const zeus::CColor& bgColor = zeus::CColor::skWhite,
RectangleConstraint constraint = RectangleConstraint());
Button(ViewResources& res, View& parentView, IButtonBinding* controlBinding, std::string_view text,
const zeus::CColor& textColor, Icon* icon = nullptr, Style style = Style::Block,
const zeus::CColor& bgColor = zeus::CColor::skWhite, RectangleConstraint constraint = RectangleConstraint());
void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseMove(const boo::SWindowCoord&);
void mouseLeave(const boo::SWindowCoord&);
void think();
void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub);
void draw(boo::IGraphicsCommandQueue* gfxQ);
void setText(std::string_view text, const zeus::CColor& textColor);
void setText(std::string_view text);
void setIcon(Icon* icon = nullptr);
std::string_view getText() const { return m_textStr; }
void colorGlyphs(const zeus::CColor& newColor);
int nominalWidth() const { return m_nomWidth; }
int nominalHeight() const { return m_nomHeight; }
void closeMenu(const boo::SWindowCoord& coord);
ViewChild<std::unique_ptr<View>>& getMenu() { return m_modalMenu; }
void setMultiplyColor(const zeus::CColor& color) {
View::setMultiplyColor(color);
m_viewVertBlock.m_color = color;
if (m_viewVertBlockBuf)
m_viewVertBlockBuf.access().finalAssign(m_viewVertBlock);
m_text->setMultiplyColor(color);
if (m_icon)
m_icon->setMultiplyColor(color);
}
}; };
} } // namespace specter

View File

@ -2,119 +2,106 @@
#include "View.hpp" #include "View.hpp"
namespace specter namespace specter {
{
class Control; class Control;
class Button; class Button;
enum class ControlType enum class ControlType { Button, Float, Int, String, CVar };
{
Button, struct IControlBinding {
Float, virtual ControlType type() const = 0;
Int, virtual std::string_view name(const Control* control) const = 0;
String, virtual std::string_view help(const Control* control) const { return {}; }
CVar
}; };
struct IControlBinding struct IButtonBinding : IControlBinding {
{ ControlType type() const { return ControlType::Button; }
virtual ControlType type() const = 0; static IButtonBinding* castTo(IControlBinding* bind) {
virtual std::string_view name(const Control* control) const=0; return bind->type() == ControlType::Button ? static_cast<IButtonBinding*>(bind) : nullptr;
virtual std::string_view help(const Control* control) const {return {};} }
/** Pressed/Released while Hovering action,
* cancellable by holding the button and releasing outside */
virtual void activated(const Button* button, const boo::SWindowCoord& coord) {}
/** Pass-through down action */
virtual void down(const Button* button, const boo::SWindowCoord& coord) {}
/** Pass-through up action */
virtual void up(const Button* button, const boo::SWindowCoord& coord) {}
/** Optional style of menu to bind to button */
enum class MenuStyle {
None, /**< No menu; normal button */
Primary, /**< Menu button replaces normal button */
Auxiliary /**< Menu button placed alongside normal button */
};
/** Informs button which MenuStyle to present to user */
virtual MenuStyle menuStyle(const specter::Button* button) const { return MenuStyle::None; }
/** Called when user requests menu, Button assumes modal ownership */
virtual std::unique_ptr<View> buildMenu(const specter::Button* button) { return std::unique_ptr<View>(); }
}; };
struct IButtonBinding : IControlBinding struct IFloatBinding : IControlBinding {
{ ControlType type() const { return ControlType::Float; }
ControlType type() const { return ControlType::Button; } static IFloatBinding* castTo(IControlBinding* bind) {
static IButtonBinding* castTo(IControlBinding* bind) return bind->type() == ControlType::Float ? static_cast<IFloatBinding*>(bind) : nullptr;
{ return bind->type() == ControlType::Button ? static_cast<IButtonBinding*>(bind) : nullptr; } }
virtual float getDefault(const Control* control) const { return 0.0; }
/** Pressed/Released while Hovering action, virtual std::pair<float, float> getBounds(const Control* control) const { return std::make_pair(FLT_MIN, FLT_MAX); }
* cancellable by holding the button and releasing outside */ virtual void changed(const Control* control, float val) = 0;
virtual void activated(const Button* button, const boo::SWindowCoord& coord) {}
/** Pass-through down action */
virtual void down(const Button* button, const boo::SWindowCoord& coord) {}
/** Pass-through up action */
virtual void up(const Button* button, const boo::SWindowCoord& coord) {}
/** Optional style of menu to bind to button */
enum class MenuStyle
{
None, /**< No menu; normal button */
Primary, /**< Menu button replaces normal button */
Auxiliary /**< Menu button placed alongside normal button */
};
/** Informs button which MenuStyle to present to user */
virtual MenuStyle menuStyle(const specter::Button* button) const {return MenuStyle::None;}
/** Called when user requests menu, Button assumes modal ownership */
virtual std::unique_ptr<View> buildMenu(const specter::Button* button) {return std::unique_ptr<View>();}
}; };
struct IFloatBinding : IControlBinding struct IIntBinding : IControlBinding {
{ ControlType type() const { return ControlType::Int; }
ControlType type() const { return ControlType::Float; } static IIntBinding* castTo(IControlBinding* bind) {
static IFloatBinding* castTo(IControlBinding* bind) return bind->type() == ControlType::Int ? static_cast<IIntBinding*>(bind) : nullptr;
{ return bind->type() == ControlType::Float ? static_cast<IFloatBinding*>(bind) : nullptr; } }
virtual float getDefault(const Control* control) const {return 0.0;} virtual int getDefault(const Control* control) const { return 0; }
virtual std::pair<float,float> getBounds(const Control* control) const {return std::make_pair(FLT_MIN, FLT_MAX);} virtual std::pair<int, int> getBounds(const Control* control) const { return std::make_pair(INT_MIN, INT_MAX); }
virtual void changed(const Control* control, float val)=0; virtual void changed(const Control* control, int val) = 0;
}; };
struct IIntBinding : IControlBinding struct IStringBinding : IControlBinding {
{ ControlType type() const { return ControlType::String; }
ControlType type() const { return ControlType::Int; } static IStringBinding* castTo(IControlBinding* bind) {
static IIntBinding* castTo(IControlBinding* bind) return bind->type() == ControlType::String ? static_cast<IStringBinding*>(bind) : nullptr;
{ return bind->type() == ControlType::Int ? static_cast<IIntBinding*>(bind) : nullptr; } }
virtual int getDefault(const Control* control) const {return 0;} virtual std::string getDefault(const Control* control) const { return ""; }
virtual std::pair<int,int> getBounds(const Control* control) const {return std::make_pair(INT_MIN, INT_MAX);} virtual void changed(const Control* control, std::string_view val) = 0;
virtual void changed(const Control* control, int val)=0;
}; };
struct IStringBinding : IControlBinding struct CVarControlBinding : IControlBinding {
{ hecl::CVar* m_cvar;
ControlType type() const { return ControlType::String; } CVarControlBinding(hecl::CVar* cvar) : m_cvar(cvar) {}
static IStringBinding* castTo(IControlBinding* bind) ControlType type() const { return ControlType::CVar; }
{ return bind->type() == ControlType::String ? static_cast<IStringBinding*>(bind) : nullptr; } static CVarControlBinding* castTo(IControlBinding* bind) {
virtual std::string getDefault(const Control* control) const {return "";} return bind->type() == ControlType::CVar ? static_cast<CVarControlBinding*>(bind) : nullptr;
virtual void changed(const Control* control, std::string_view val)=0; }
std::string_view name(const Control* control) const { return m_cvar->name(); }
std::string_view help(const Control* control) const { return m_cvar->rawHelp(); }
}; };
struct CVarControlBinding : IControlBinding class Control : public View {
{
hecl::CVar* m_cvar;
CVarControlBinding(hecl::CVar* cvar)
: m_cvar(cvar) {}
ControlType type() const { return ControlType::CVar; }
static CVarControlBinding* castTo(IControlBinding* bind)
{ return bind->type() == ControlType::CVar ? static_cast<CVarControlBinding*>(bind) : nullptr; }
std::string_view name(const Control* control) const {return m_cvar->name();}
std::string_view help(const Control* control) const {return m_cvar->rawHelp();}
};
class Control : public View
{
protected: protected:
IControlBinding* m_controlBinding = nullptr; IControlBinding* m_controlBinding = nullptr;
public: public:
Control(ViewResources& res, View& parentView, IControlBinding* controlBinding); Control(ViewResources& res, View& parentView, IControlBinding* controlBinding);
}; };
class ITextInputView : public Control, public boo::ITextInputCallback class ITextInputView : public Control, public boo::ITextInputCallback {
{
protected: protected:
static std::recursive_mutex m_textInputLk; static std::recursive_mutex m_textInputLk;
ITextInputView(ViewResources& res, View& parentView, ITextInputView(ViewResources& res, View& parentView, IControlBinding* controlBinding)
IControlBinding* controlBinding) : Control(res, parentView, controlBinding) {}
: Control(res, parentView, controlBinding) {}
public: public:
virtual void clipboardCopy() {} virtual void clipboardCopy() {}
virtual void clipboardCut() {} virtual void clipboardCut() {}
virtual void clipboardPaste() {} virtual void clipboardPaste() {}
}; };
} } // namespace specter

View File

@ -12,343 +12,286 @@
#include "PathButtons.hpp" #include "PathButtons.hpp"
#include <hecl/hecl.hpp> #include <hecl/hecl.hpp>
namespace specter namespace specter {
{
class FileBrowser : public ModalWindow, public IPathButtonsBinding class FileBrowser : public ModalWindow, public IPathButtonsBinding {
{
public: public:
enum class Type enum class Type { SaveFile, SaveDirectory, OpenFile, OpenDirectory, NewHECLProject, OpenHECLProject };
{
SaveFile,
SaveDirectory,
OpenFile,
OpenDirectory,
NewHECLProject,
OpenHECLProject
};
private: private:
Type m_type; Type m_type;
hecl::SystemString m_path; hecl::SystemString m_path;
std::vector<hecl::SystemString> m_comps; std::vector<hecl::SystemString> m_comps;
bool m_showingHidden = false; bool m_showingHidden = false;
class LeftSide : public View class LeftSide : public View {
{ friend class FileBrowser;
friend class FileBrowser; FileBrowser& m_fb;
FileBrowser& m_fb; LeftSide(FileBrowser& fb, ViewResources& res) : View(res, fb), m_fb(fb) {}
LeftSide(FileBrowser& fb, ViewResources& res) : View(res, fb), m_fb(fb) {} void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub);
void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub); void draw(boo::IGraphicsCommandQueue* gfxQ);
void draw(boo::IGraphicsCommandQueue* gfxQ); } m_left;
} m_left;
class RightSide : public View class RightSide : public View {
{ friend class FileBrowser;
friend class FileBrowser; FileBrowser& m_fb;
FileBrowser& m_fb; RightSide(FileBrowser& fb, ViewResources& res) : View(res, fb), m_fb(fb) {}
RightSide(FileBrowser& fb, ViewResources& res) : View(res, fb), m_fb(fb) {} void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub);
void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub); void draw(boo::IGraphicsCommandQueue* gfxQ);
void draw(boo::IGraphicsCommandQueue* gfxQ); } m_right;
} m_right;
ViewChild<std::unique_ptr<SplitView>> m_split; ViewChild<std::unique_ptr<SplitView>> m_split;
void okActivated(bool viaButton); void okActivated(bool viaButton);
struct OKButton : IButtonBinding struct OKButton : IButtonBinding {
{ FileBrowser& m_fb;
FileBrowser& m_fb; ViewChild<std::unique_ptr<Button>> m_button;
ViewChild<std::unique_ptr<Button>> m_button; std::string m_text;
std::string m_text; OKButton(FileBrowser& fb, ViewResources& res, std::string_view text) : m_fb(fb), m_text(text) {
OKButton(FileBrowser& fb, ViewResources& res, std::string_view text) m_button.m_view.reset(
: m_fb(fb), m_text(text) new Button(res, fb, this, text, nullptr, Button::Style::Block, zeus::CColor::skWhite,
{ RectangleConstraint(100 * res.pixelFactor(), -1, RectangleConstraint::Test::Minimum)));
m_button.m_view.reset(new Button(res, fb, this, text, nullptr, Button::Style::Block, zeus::CColor::skWhite, }
RectangleConstraint(100 * res.pixelFactor(), -1, RectangleConstraint::Test::Minimum))); std::string_view name(const Control* control) const { return m_text; }
} void activated(const Button* button, const boo::SWindowCoord&) { m_fb.okActivated(true); }
std::string_view name(const Control* control) const {return m_text;} } m_ok;
void activated(const Button* button, const boo::SWindowCoord&) {m_fb.okActivated(true);}
} m_ok;
void cancelActivated(); void cancelActivated();
struct CancelButton : IButtonBinding struct CancelButton : IButtonBinding {
{ FileBrowser& m_fb;
FileBrowser& m_fb; ViewChild<std::unique_ptr<Button>> m_button;
ViewChild<std::unique_ptr<Button>> m_button; std::string m_text;
std::string m_text; CancelButton(FileBrowser& fb, ViewResources& res, std::string_view text) : m_fb(fb), m_text(text) {
CancelButton(FileBrowser& fb, ViewResources& res, std::string_view text) m_button.m_view.reset(new Button(
: m_fb(fb), m_text(text) res, fb, this, text, nullptr, Button::Style::Block, zeus::CColor::skWhite,
{ RectangleConstraint(m_fb.m_ok.m_button.m_view->nominalWidth(), -1, RectangleConstraint::Test::Minimum)));
m_button.m_view.reset(new Button(res, fb, this, text, nullptr, Button::Style::Block, zeus::CColor::skWhite, }
RectangleConstraint(m_fb.m_ok.m_button.m_view->nominalWidth(), -1, RectangleConstraint::Test::Minimum))); std::string_view name(const Control* control) const { return m_text; }
} void activated(const Button* button, const boo::SWindowCoord&) { m_fb.cancelActivated(); }
std::string_view name(const Control* control) const {return m_text;} } m_cancel;
void activated(const Button* button, const boo::SWindowCoord&) {m_fb.cancelActivated();}
} m_cancel;
void pathButtonActivated(size_t idx); void pathButtonActivated(size_t idx);
ViewChild<std::unique_ptr<PathButtons>> m_pathButtons; ViewChild<std::unique_ptr<PathButtons>> m_pathButtons;
ViewChild<std::unique_ptr<TextField>> m_fileField; ViewChild<std::unique_ptr<TextField>> m_fileField;
struct FileFieldBind : IStringBinding struct FileFieldBind : IStringBinding {
{ FileBrowser& m_browser;
FileBrowser& m_browser; std::string m_name;
std::string m_name; FileFieldBind(FileBrowser& browser, const IViewManager& vm)
FileFieldBind(FileBrowser& browser, const IViewManager& vm) : m_browser(browser), m_name(vm.translateOr("file_name", "File Name")) {}
: m_browser(browser), m_name(vm.translateOr("file_name", "File Name")) {} std::string_view name(const Control* control) const { return m_name; }
std::string_view name(const Control* control) const {return m_name;} void changed(const Control* control, std::string_view val) {}
void changed(const Control* control, std::string_view val) } m_fileFieldBind;
{
}
} m_fileFieldBind;
std::unique_ptr<MessageWindow> m_confirmWindow; std::unique_ptr<MessageWindow> m_confirmWindow;
struct FileListingDataBind : ITableDataBinding, ITableStateBinding struct FileListingDataBind : ITableDataBinding, ITableStateBinding {
{ FileBrowser& m_fb;
FileBrowser& m_fb;
struct Entry struct Entry {
{ hecl::SystemString m_path;
hecl::SystemString m_path; std::string m_name;
std::string m_name; std::string m_type;
std::string m_type; std::string m_size;
std::string m_size;
};
std::vector<Entry> m_entries;
std::string m_nameCol;
std::string m_typeCol;
std::string m_sizeCol;
std::string m_dirStr;
std::string m_projStr;
std::string m_fileStr;
size_t columnCount() const {return 3;}
size_t rowCount() const {return m_entries.size();}
std::string_view header(size_t cIdx) const
{
switch (cIdx)
{
case 0:
return m_nameCol;
case 1:
return m_typeCol;
case 2:
return m_sizeCol;
default: break;
}
return {};
}
std::string_view cell(size_t cIdx, size_t rIdx) const
{
switch (cIdx)
{
case 0:
return m_entries.at(rIdx).m_name;
case 1:
return m_entries.at(rIdx).m_type;
case 2:
return m_entries.at(rIdx).m_size;
default: break;
}
return {};
}
float m_columnSplits[3] = {0.0f, 0.7f, 0.9f};
bool columnSplitResizeAllowed() const {return true;}
float getColumnSplit(size_t cIdx) const
{
return m_columnSplits[cIdx];
}
void setColumnSplit(size_t cIdx, float split)
{
m_columnSplits[cIdx] = split;
}
void updateListing(const hecl::DirectoryEnumerator& dEnum)
{
m_entries.clear();
m_entries.reserve(dEnum.size());
for (const hecl::DirectoryEnumerator::Entry& d : dEnum)
{
m_entries.emplace_back();
Entry& ent = m_entries.back();
ent.m_path = d.m_path;
hecl::SystemUTF8Conv nameUtf8(d.m_name);
ent.m_name = nameUtf8.str();
if (d.m_isDir)
{
if (hecl::SearchForProject(d.m_path))
ent.m_type = m_projStr;
else
ent.m_type = m_dirStr;
}
else
{
ent.m_type = m_fileStr;
ent.m_size = hecl::HumanizeNumber(d.m_fileSz, 7, nullptr, int(hecl::HNScale::AutoScale),
hecl::HNFlags::B | hecl::HNFlags::Decimal);
}
}
m_needsUpdate = false;
}
bool m_sizeSort = false;
SortDirection m_sortDir = SortDirection::Ascending;
bool m_needsUpdate = false;
SortDirection getSort(size_t& cIdx) const
{
cIdx = m_sizeSort ? 2 : 0;
return m_sortDir;
}
void setSort(size_t cIdx, SortDirection dir)
{
if (cIdx == 1)
return;
m_sizeSort = cIdx == 2;
m_sortDir = dir;
m_needsUpdate = true;
}
void setSelectedRow(size_t rIdx)
{
if (rIdx != -1)
m_fb.m_fileField.m_view->setText(m_entries.at(rIdx).m_name);
else
m_fb.m_fileField.m_view->setText("");
m_fb.m_fileField.m_view->clearErrorState();
}
void rowActivated(size_t rIdx)
{
m_fb.okActivated(false);
}
FileListingDataBind(FileBrowser& fb, const IViewManager& vm)
: m_fb(fb)
{
m_nameCol = vm.translateOr("name", "Name");
m_typeCol = vm.translateOr("type", "Type");
m_sizeCol = vm.translateOr("size", "Size");
m_dirStr = vm.translateOr("directory", "Directory");
m_projStr = vm.translateOr("hecl_project", "HECL Project");
m_fileStr = vm.translateOr("file", "File");
}
} m_fileListingBind;
ViewChild<std::unique_ptr<Table>> m_fileListing;
struct BookmarkDataBind : ITableDataBinding, ITableStateBinding
{
FileBrowser& m_fb;
BookmarkDataBind(FileBrowser& fb) : m_fb(fb) {}
struct Entry
{
hecl::SystemString m_path;
std::string m_name;
Entry(std::pair<hecl::SystemString, std::string>&& path)
: m_path(std::move(path.first)), m_name(std::move(path.second)) {}
Entry(hecl::SystemStringView path)
: m_path(path)
{
hecl::SystemUTF8Conv utf8(path);
if (utf8.str().size() == 1 && utf8.str()[0] == '/')
{
m_name = "/";
return;
}
size_t lastSlash = utf8.str().rfind('/');
if (lastSlash != std::string::npos)
m_name.assign(utf8.str().cbegin() + lastSlash + 1, utf8.str().cend());
else
m_name = utf8.str();
}
};
std::vector<Entry> m_entries;
size_t columnCount() const {return 1;}
size_t rowCount() const {return m_entries.size();}
std::string_view cell(size_t, size_t rIdx) const
{
return m_entries.at(rIdx).m_name;
}
void setSelectedRow(size_t rIdx)
{
if (rIdx != -1)
m_fb.navigateToPath(m_entries.at(rIdx).m_path);
}
void rowActivated(size_t rIdx)
{
m_fb.okActivated(true);
}
}; };
std::vector<Entry> m_entries;
BookmarkDataBind m_systemBookmarkBind; std::string m_nameCol;
std::unique_ptr<TextView> m_systemBookmarksLabel; std::string m_typeCol;
ViewChild<std::unique_ptr<Table>> m_systemBookmarks; std::string m_sizeCol;
BookmarkDataBind m_projectBookmarkBind; std::string m_dirStr;
std::unique_ptr<TextView> m_projectBookmarksLabel; std::string m_projStr;
ViewChild<std::unique_ptr<Table>> m_projectBookmarks; std::string m_fileStr;
BookmarkDataBind m_recentBookmarkBind; size_t columnCount() const { return 3; }
std::unique_ptr<TextView> m_recentBookmarksLabel; size_t rowCount() const { return m_entries.size(); }
ViewChild<std::unique_ptr<Table>> m_recentBookmarks;
std::function<void(bool, hecl::SystemStringView)> m_returnFunc; std::string_view header(size_t cIdx) const {
switch (cIdx) {
case 0:
return m_nameCol;
case 1:
return m_typeCol;
case 2:
return m_sizeCol;
default:
break;
}
return {};
}
std::string_view cell(size_t cIdx, size_t rIdx) const {
switch (cIdx) {
case 0:
return m_entries.at(rIdx).m_name;
case 1:
return m_entries.at(rIdx).m_type;
case 2:
return m_entries.at(rIdx).m_size;
default:
break;
}
return {};
}
float m_columnSplits[3] = {0.0f, 0.7f, 0.9f};
bool columnSplitResizeAllowed() const { return true; }
float getColumnSplit(size_t cIdx) const { return m_columnSplits[cIdx]; }
void setColumnSplit(size_t cIdx, float split) { m_columnSplits[cIdx] = split; }
void updateListing(const hecl::DirectoryEnumerator& dEnum) {
m_entries.clear();
m_entries.reserve(dEnum.size());
for (const hecl::DirectoryEnumerator::Entry& d : dEnum) {
m_entries.emplace_back();
Entry& ent = m_entries.back();
ent.m_path = d.m_path;
hecl::SystemUTF8Conv nameUtf8(d.m_name);
ent.m_name = nameUtf8.str();
if (d.m_isDir) {
if (hecl::SearchForProject(d.m_path))
ent.m_type = m_projStr;
else
ent.m_type = m_dirStr;
} else {
ent.m_type = m_fileStr;
ent.m_size = hecl::HumanizeNumber(d.m_fileSz, 7, nullptr, int(hecl::HNScale::AutoScale),
hecl::HNFlags::B | hecl::HNFlags::Decimal);
}
}
m_needsUpdate = false;
}
bool m_sizeSort = false;
SortDirection m_sortDir = SortDirection::Ascending;
bool m_needsUpdate = false;
SortDirection getSort(size_t& cIdx) const {
cIdx = m_sizeSort ? 2 : 0;
return m_sortDir;
}
void setSort(size_t cIdx, SortDirection dir) {
if (cIdx == 1)
return;
m_sizeSort = cIdx == 2;
m_sortDir = dir;
m_needsUpdate = true;
}
void setSelectedRow(size_t rIdx) {
if (rIdx != -1)
m_fb.m_fileField.m_view->setText(m_entries.at(rIdx).m_name);
else
m_fb.m_fileField.m_view->setText("");
m_fb.m_fileField.m_view->clearErrorState();
}
void rowActivated(size_t rIdx) { m_fb.okActivated(false); }
FileListingDataBind(FileBrowser& fb, const IViewManager& vm) : m_fb(fb) {
m_nameCol = vm.translateOr("name", "Name");
m_typeCol = vm.translateOr("type", "Type");
m_sizeCol = vm.translateOr("size", "Size");
m_dirStr = vm.translateOr("directory", "Directory");
m_projStr = vm.translateOr("hecl_project", "HECL Project");
m_fileStr = vm.translateOr("file", "File");
}
} m_fileListingBind;
ViewChild<std::unique_ptr<Table>> m_fileListing;
struct BookmarkDataBind : ITableDataBinding, ITableStateBinding {
FileBrowser& m_fb;
BookmarkDataBind(FileBrowser& fb) : m_fb(fb) {}
struct Entry {
hecl::SystemString m_path;
std::string m_name;
Entry(std::pair<hecl::SystemString, std::string>&& path)
: m_path(std::move(path.first)), m_name(std::move(path.second)) {}
Entry(hecl::SystemStringView path) : m_path(path) {
hecl::SystemUTF8Conv utf8(path);
if (utf8.str().size() == 1 && utf8.str()[0] == '/') {
m_name = "/";
return;
}
size_t lastSlash = utf8.str().rfind('/');
if (lastSlash != std::string::npos)
m_name.assign(utf8.str().cbegin() + lastSlash + 1, utf8.str().cend());
else
m_name = utf8.str();
}
};
std::vector<Entry> m_entries;
size_t columnCount() const { return 1; }
size_t rowCount() const { return m_entries.size(); }
std::string_view cell(size_t, size_t rIdx) const { return m_entries.at(rIdx).m_name; }
void setSelectedRow(size_t rIdx) {
if (rIdx != -1)
m_fb.navigateToPath(m_entries.at(rIdx).m_path);
}
void rowActivated(size_t rIdx) { m_fb.okActivated(true); }
};
BookmarkDataBind m_systemBookmarkBind;
std::unique_ptr<TextView> m_systemBookmarksLabel;
ViewChild<std::unique_ptr<Table>> m_systemBookmarks;
BookmarkDataBind m_projectBookmarkBind;
std::unique_ptr<TextView> m_projectBookmarksLabel;
ViewChild<std::unique_ptr<Table>> m_projectBookmarks;
BookmarkDataBind m_recentBookmarkBind;
std::unique_ptr<TextView> m_recentBookmarksLabel;
ViewChild<std::unique_ptr<Table>> m_recentBookmarks;
std::function<void(bool, hecl::SystemStringView)> m_returnFunc;
public: public:
FileBrowser(ViewResources& res, View& parentView, std::string_view title, Type type, FileBrowser(ViewResources& res, View& parentView, std::string_view title, Type type,
std::function<void(bool, hecl::SystemStringView)> returnFunc) std::function<void(bool, hecl::SystemStringView)> returnFunc)
: FileBrowser(res, parentView, title, type, hecl::GetcwdStr(), returnFunc) {} : FileBrowser(res, parentView, title, type, hecl::GetcwdStr(), returnFunc) {}
FileBrowser(ViewResources& res, View& parentView, std::string_view title, Type type, FileBrowser(ViewResources& res, View& parentView, std::string_view title, Type type,
hecl::SystemStringView initialPath, hecl::SystemStringView initialPath, std::function<void(bool, hecl::SystemStringView)> returnFunc);
std::function<void(bool, hecl::SystemStringView)> returnFunc);
static std::vector<hecl::SystemString> PathComponents(hecl::SystemStringView path); static std::vector<hecl::SystemString> PathComponents(hecl::SystemStringView path);
static void SyncBookmarkSelections(Table& table, BookmarkDataBind& binding, static void SyncBookmarkSelections(Table& table, BookmarkDataBind& binding, const hecl::SystemString& sel);
const hecl::SystemString& sel);
void navigateToPath(hecl::SystemStringView path); void navigateToPath(hecl::SystemStringView path);
bool showingHidden() const {return m_showingHidden;} bool showingHidden() const { return m_showingHidden; }
void setShowingHidden(bool showingHidden) void setShowingHidden(bool showingHidden) {
{ m_showingHidden = showingHidden;
m_showingHidden = showingHidden; navigateToPath(m_path);
navigateToPath(m_path); }
} void updateContentOpacity(float opacity);
void updateContentOpacity(float opacity);
void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey); void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey); void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseMove(const boo::SWindowCoord&); void mouseMove(const boo::SWindowCoord&);
void mouseLeave(const boo::SWindowCoord&); void mouseLeave(const boo::SWindowCoord&);
void scroll(const boo::SWindowCoord&, const boo::SScrollDelta&); void scroll(const boo::SWindowCoord&, const boo::SScrollDelta&);
void touchDown(const boo::STouchCoord&, uintptr_t); void touchDown(const boo::STouchCoord&, uintptr_t);
void touchUp(const boo::STouchCoord&, uintptr_t); void touchUp(const boo::STouchCoord&, uintptr_t);
void touchMove(const boo::STouchCoord&, uintptr_t); void touchMove(const boo::STouchCoord&, uintptr_t);
void charKeyDown(unsigned long, boo::EModifierKey, bool); void charKeyDown(unsigned long, boo::EModifierKey, bool);
void specialKeyDown(boo::ESpecialKey, boo::EModifierKey, bool); void specialKeyDown(boo::ESpecialKey, boo::EModifierKey, bool);
void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub); void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub);
void think(); void think();
void draw(boo::IGraphicsCommandQueue* gfxQ); void draw(boo::IGraphicsCommandQueue* gfxQ);
}; };
} } // namespace specter

View File

@ -9,194 +9,188 @@
#include <athena/FileWriter.hpp> #include <athena/FileWriter.hpp>
#include <athena/DNA.hpp> #include <athena/DNA.hpp>
namespace specter namespace specter {
{ class FontTag {
class FontTag friend class FontCache;
{ uint64_t m_hash = 0;
friend class FontCache; FontTag(std::string_view name, bool subpixel, float points, unsigned dpi);
uint64_t m_hash = 0;
FontTag(std::string_view name, bool subpixel, float points, unsigned dpi);
public: public:
FontTag() = default; FontTag() = default;
operator bool() const {return m_hash != 0;} operator bool() const { return m_hash != 0; }
uint64_t hash() const {return m_hash;} uint64_t hash() const { return m_hash; }
bool operator==(const FontTag& other) const {return m_hash == other.m_hash;} bool operator==(const FontTag& other) const { return m_hash == other.m_hash; }
}; };
} } // namespace specter
namespace std namespace std {
{ template <>
template <> struct hash<specter::FontTag> struct hash<specter::FontTag> {
{ size_t operator()(const specter::FontTag& handle) const noexcept { return size_t(handle.hash()); }
size_t operator() (const specter::FontTag& handle) const noexcept
{return size_t(handle.hash());}
}; };
} } // namespace std
namespace specter namespace specter {
{
class FreeTypeGZipMemFace {
FT_Library m_lib;
FT_StreamRec m_comp = {};
FT_StreamRec m_decomp = {};
FT_Face m_face = nullptr;
class FreeTypeGZipMemFace
{
FT_Library m_lib;
FT_StreamRec m_comp = {};
FT_StreamRec m_decomp = {};
FT_Face m_face = nullptr;
public: public:
FreeTypeGZipMemFace(FT_Library lib, const uint8_t* data, size_t sz); FreeTypeGZipMemFace(FT_Library lib, const uint8_t* data, size_t sz);
FreeTypeGZipMemFace(const FreeTypeGZipMemFace& other) = delete; FreeTypeGZipMemFace(const FreeTypeGZipMemFace& other) = delete;
FreeTypeGZipMemFace& operator=(const FreeTypeGZipMemFace& other) = delete; FreeTypeGZipMemFace& operator=(const FreeTypeGZipMemFace& other) = delete;
~FreeTypeGZipMemFace() {close();} ~FreeTypeGZipMemFace() { close(); }
void open(); void open();
void close(); void close();
operator FT_Face() {open(); return m_face;} operator FT_Face() {
open();
return m_face;
}
}; };
using FCharFilter = std::pair<std::string, std::function<bool(uint32_t)>>; using FCharFilter = std::pair<std::string, std::function<bool(uint32_t)>>;
class FontAtlas class FontAtlas {
{ FT_Face m_face;
FT_Face m_face; std::vector<uint8_t> m_texmap;
std::vector<uint8_t> m_texmap; boo::ObjToken<boo::ITextureSA> m_tex;
boo::ObjToken<boo::ITextureSA> m_tex; uint32_t m_dpi;
uint32_t m_dpi; FT_Fixed m_ftXscale;
FT_Fixed m_ftXscale; FT_UShort m_ftXPpem;
FT_UShort m_ftXPpem; FT_Pos m_lineHeight;
FT_Pos m_lineHeight; unsigned m_finalHeight;
unsigned m_finalHeight; unsigned m_fullTexmapLayers;
unsigned m_fullTexmapLayers; bool m_subpixel;
bool m_subpixel; bool m_ready = false;
bool m_ready = false;
public: public:
struct Glyph struct Glyph {
{ atUint32 m_unicodePoint;
atUint32 m_unicodePoint; atUint32 m_glyphIdx;
atUint32 m_glyphIdx; atUint32 m_layerIdx;
atUint32 m_layerIdx; float m_layerFloat;
float m_layerFloat; float m_uv[4];
float m_uv[4]; atInt32 m_leftPadding;
atInt32 m_leftPadding; atInt32 m_advance;
atInt32 m_advance; atInt32 m_width;
atInt32 m_width; atInt32 m_height;
atInt32 m_height; atInt32 m_verticalOffset;
atInt32 m_verticalOffset; };
};
private: private:
std::vector<Glyph> m_glyphs; std::vector<Glyph> m_glyphs;
std::unordered_map<atUint16, std::vector<std::pair<atUint16, atInt16>>> m_kernAdjs; std::unordered_map<atUint16, std::vector<std::pair<atUint16, atInt16>>> m_kernAdjs;
struct TT_KernHead : athena::io::DNA<athena::Big> struct TT_KernHead : athena::io::DNA<athena::Big> {
{ AT_DECL_DNA
AT_DECL_DNA Value<atUint32> length;
Value<atUint32> length; Value<atUint16> coverage;
Value<atUint16> coverage; };
};
struct TT_KernSubHead : athena::io::DNA<athena::Big> struct TT_KernSubHead : athena::io::DNA<athena::Big> {
{ AT_DECL_DNA
AT_DECL_DNA Value<atUint16> nPairs;
Value<atUint16> nPairs; Value<atUint16> searchRange;
Value<atUint16> searchRange; Value<atUint16> entrySelector;
Value<atUint16> entrySelector; Value<atUint16> rangeShift;
Value<atUint16> rangeShift; };
};
struct TT_KernPair : athena::io::DNA<athena::Big> struct TT_KernPair : athena::io::DNA<athena::Big> {
{ AT_DECL_DNA
AT_DECL_DNA Value<atUint16> left;
Value<atUint16> left; Value<atUint16> right;
Value<atUint16> right; Value<atInt16> value;
Value<atInt16> value; };
};
void buildKernTable(FT_Face face); void buildKernTable(FT_Face face);
std::unordered_map<atUint32, size_t> m_glyphLookup; std::unordered_map<atUint32, size_t> m_glyphLookup;
public: public:
FontAtlas(FT_Face face, uint32_t dpi, FontAtlas(FT_Face face, uint32_t dpi, bool subpixel, FCharFilter& filter, athena::io::FileWriter& writer);
bool subpixel, FCharFilter& filter, athena::io::FileWriter& writer); FontAtlas(FT_Face face, uint32_t dpi, bool subpixel, FCharFilter& filter, athena::io::FileReader& reader);
FontAtlas(FT_Face face, uint32_t dpi, FontAtlas(const FontAtlas& other) = delete;
bool subpixel, FCharFilter& filter, athena::io::FileReader& reader); FontAtlas& operator=(const FontAtlas& other) = delete;
FontAtlas(const FontAtlas& other) = delete;
FontAtlas& operator=(const FontAtlas& other) = delete;
uint32_t dpi() const {return m_dpi;} uint32_t dpi() const { return m_dpi; }
FT_Fixed FT_Xscale() const {return m_ftXscale;} FT_Fixed FT_Xscale() const { return m_ftXscale; }
FT_UShort FT_XPPem() const {return m_ftXPpem;} FT_UShort FT_XPPem() const { return m_ftXPpem; }
FT_Pos FT_LineHeight() const {return m_lineHeight;} FT_Pos FT_LineHeight() const { return m_lineHeight; }
bool isReady() const { return m_ready; } bool isReady() const { return m_ready; }
boo::ObjToken<boo::ITextureSA> texture(boo::IGraphicsDataFactory* gf) const; boo::ObjToken<boo::ITextureSA> texture(boo::IGraphicsDataFactory* gf) const;
bool subpixel() const {return m_subpixel;} bool subpixel() const { return m_subpixel; }
const Glyph* lookupGlyph(atUint32 charcode) const const Glyph* lookupGlyph(atUint32 charcode) const {
{ auto search = m_glyphLookup.find(charcode);
auto search = m_glyphLookup.find(charcode); if (search == m_glyphLookup.end())
if (search == m_glyphLookup.end()) return nullptr;
return nullptr; return &m_glyphs[search->second];
return &m_glyphs[search->second]; }
} atInt16 lookupKern(atUint32 leftIdx, atUint32 rightIdx) const {
atInt16 lookupKern(atUint32 leftIdx, atUint32 rightIdx) const auto pairSearch = m_kernAdjs.find(leftIdx);
{ if (pairSearch == m_kernAdjs.cend())
auto pairSearch = m_kernAdjs.find(leftIdx); return 0;
if (pairSearch == m_kernAdjs.cend()) for (const std::pair<atUint16, atInt16>& p : pairSearch->second)
return 0; if (p.first == rightIdx)
for (const std::pair<atUint16, atInt16>& p : pairSearch->second) return p.second;
if (p.first == rightIdx) return 0;
return p.second; }
return 0;
}
}; };
extern const FCharFilter AllCharFilter; extern const FCharFilter AllCharFilter;
extern const FCharFilter LatinCharFilter; extern const FCharFilter LatinCharFilter;
extern const FCharFilter LatinAndJapaneseCharFilter; extern const FCharFilter LatinAndJapaneseCharFilter;
class FontCache class FontCache {
{ const hecl::Runtime::FileStoreManager& m_fileMgr;
const hecl::Runtime::FileStoreManager& m_fileMgr; hecl::SystemString m_cacheRoot;
hecl::SystemString m_cacheRoot; struct Library {
struct Library FT_Library m_lib;
{ Library();
FT_Library m_lib; ~Library();
Library(); operator FT_Library() { return m_lib; }
~Library(); } m_fontLib;
operator FT_Library() {return m_lib;} FreeTypeGZipMemFace m_regFace;
} m_fontLib; FreeTypeGZipMemFace m_monoFace;
FreeTypeGZipMemFace m_regFace; FreeTypeGZipMemFace m_curvesFace;
FreeTypeGZipMemFace m_monoFace;
FreeTypeGZipMemFace m_curvesFace; std::unordered_map<FontTag, std::unique_ptr<FontAtlas>> m_cachedAtlases;
std::unordered_map<FontTag, std::unique_ptr<FontAtlas>> m_cachedAtlases;
public: public:
FontCache(const hecl::Runtime::FileStoreManager& fileMgr); FontCache(const hecl::Runtime::FileStoreManager& fileMgr);
FontCache(const FontCache& other) = delete; FontCache(const FontCache& other) = delete;
FontCache& operator=(const FontCache& other) = delete; FontCache& operator=(const FontCache& other) = delete;
FontTag prepCustomFont(std::string_view name, FT_Face face, FontTag prepCustomFont(std::string_view name, FT_Face face, FCharFilter filter = AllCharFilter, bool subpixel = false,
FCharFilter filter=AllCharFilter, bool subpixel=false, float points = 10.0, uint32_t dpi = 72);
float points=10.0, uint32_t dpi=72);
FontTag prepMainFont(FCharFilter filter=AllCharFilter, FontTag prepMainFont(FCharFilter filter = AllCharFilter, bool subpixel = false, float points = 10.0,
bool subpixel=false, float points=10.0, uint32_t dpi=72) uint32_t dpi = 72) {
{return prepCustomFont("droidsans-permissive", m_regFace, filter, subpixel, points, dpi);} return prepCustomFont("droidsans-permissive", m_regFace, filter, subpixel, points, dpi);
}
FontTag prepMonoFont(FCharFilter filter=AllCharFilter, FontTag prepMonoFont(FCharFilter filter = AllCharFilter, bool subpixel = false, float points = 10.0,
bool subpixel=false, float points=10.0, uint32_t dpi=72) uint32_t dpi = 72) {
{return prepCustomFont("bmonofont", m_monoFace, filter, subpixel, points, dpi);} return prepCustomFont("bmonofont", m_monoFace, filter, subpixel, points, dpi);
}
FontTag prepCurvesFont(FCharFilter filter=AllCharFilter, FontTag prepCurvesFont(FCharFilter filter = AllCharFilter, bool subpixel = false, float points = 10.0,
bool subpixel=false, float points=10.0, uint32_t dpi=72) uint32_t dpi = 72) {
{return prepCustomFont("spectercurves", m_curvesFace, filter, subpixel, points, dpi);} return prepCustomFont("spectercurves", m_curvesFace, filter, subpixel, points, dpi);
}
void closeBuiltinFonts() {m_regFace.close(); m_monoFace.close(); m_curvesFace.close();} void closeBuiltinFonts() {
m_regFace.close();
m_monoFace.close();
m_curvesFace.close();
}
const FontAtlas& lookupAtlas(FontTag tag) const; const FontAtlas& lookupAtlas(FontTag tag) const;
void destroyAtlases() {m_cachedAtlases.clear();} void destroyAtlases() { m_cachedAtlases.clear(); }
}; };
} } // namespace specter

View File

@ -2,17 +2,14 @@
#include "View.hpp" #include "View.hpp"
namespace specter namespace specter {
{
struct IMenuNode struct IMenuNode {
{ virtual boo::ITexture* icon() const { return nullptr; }
virtual boo::ITexture* icon() const {return nullptr;} virtual const std::string* text() const { return nullptr; }
virtual const std::string* text() const {return nullptr;} virtual size_t subNodeCount() const { return 0; }
virtual size_t subNodeCount() const {return 0;} virtual IMenuNode* subNode(size_t idx) { return nullptr; }
virtual IMenuNode* subNode(size_t idx) {return nullptr;} virtual void activated(const boo::SWindowCoord& coord) {}
virtual void activated(const boo::SWindowCoord& coord) {}
}; };
} } // namespace specter

View File

@ -4,31 +4,27 @@
#include "SplitView.hpp" #include "SplitView.hpp"
#include <hecl/hecl.hpp> #include <hecl/hecl.hpp>
namespace specter namespace specter {
{
struct ISpaceController; struct ISpaceController;
struct IViewManager struct IViewManager {
{
public: public:
virtual const Translator* getTranslator() const {return nullptr;} virtual const Translator* getTranslator() const { return nullptr; }
virtual std::string_view translateOr(std::string_view key, std::string_view vor) const virtual std::string_view translateOr(std::string_view key, std::string_view vor) const {
{ const Translator* trans = getTranslator();
const Translator* trans = getTranslator(); if (trans)
if (trans) return trans->translateOr(key, vor);
return trans->translateOr(key, vor); return vor;
return vor; }
}
virtual void deferSpaceSplit(ISpaceController* split, SplitView::Axis axis, int thisSlot, virtual void deferSpaceSplit(ISpaceController* split, SplitView::Axis axis, int thisSlot,
const boo::SWindowCoord& coord) {} const boo::SWindowCoord& coord) {}
virtual const std::vector<hecl::SystemString>* recentProjects() const {return nullptr;} virtual const std::vector<hecl::SystemString>* recentProjects() const { return nullptr; }
virtual void pushRecentProject(hecl::SystemStringView path) {} virtual void pushRecentProject(hecl::SystemStringView path) {}
virtual const std::vector<hecl::SystemString>* recentFiles() const {return nullptr;} virtual const std::vector<hecl::SystemString>* recentFiles() const { return nullptr; }
virtual void pushRecentFile(hecl::SystemStringView path) {} virtual void pushRecentFile(hecl::SystemStringView path) {}
}; };
} } // namespace specter

View File

@ -2,71 +2,63 @@
#include "View.hpp" #include "View.hpp"
namespace specter namespace specter {
{
struct Icon struct Icon {
{ boo::ObjToken<boo::ITexture> m_tex;
boo::ObjToken<boo::ITexture> m_tex; zeus::CVector2f m_uvCoords[4];
zeus::CVector2f m_uvCoords[4]; Icon() = default;
Icon() = default; Icon(const boo::ObjToken<boo::ITexture>& tex, float rect[4]) : m_tex(tex) {
Icon(const boo::ObjToken<boo::ITexture>& tex, float rect[4]) m_uvCoords[0][0] = rect[0];
: m_tex(tex) m_uvCoords[0][1] = -rect[3];
{
m_uvCoords[0][0] = rect[0];
m_uvCoords[0][1] = -rect[3];
m_uvCoords[1][0] = rect[0]; m_uvCoords[1][0] = rect[0];
m_uvCoords[1][1] = -rect[1]; m_uvCoords[1][1] = -rect[1];
m_uvCoords[2][0] = rect[2]; m_uvCoords[2][0] = rect[2];
m_uvCoords[2][1] = -rect[3]; m_uvCoords[2][1] = -rect[3];
m_uvCoords[3][0] = rect[2]; m_uvCoords[3][0] = rect[2];
m_uvCoords[3][1] = -rect[1]; m_uvCoords[3][1] = -rect[1];
} }
}; };
template <size_t COLS, size_t ROWS> template <size_t COLS, size_t ROWS>
class IconAtlas class IconAtlas {
{ boo::ObjToken<boo::ITextureS> m_tex;
boo::ObjToken<boo::ITextureS> m_tex; Icon m_icons[COLS][ROWS];
Icon m_icons[COLS][ROWS];
Icon MakeIcon(float x, float y) {
float rect[] = {x / float(COLS), y / float(ROWS), x / float(COLS) + 1.f / float(COLS),
y / float(ROWS) + 1.f / float(ROWS)};
return Icon(m_tex.get(), rect);
}
Icon MakeIcon(float x, float y)
{
float rect[] = {x / float(COLS), y / float(ROWS),
x / float(COLS) + 1.f / float(COLS), y / float(ROWS) + 1.f / float(ROWS)};
return Icon(m_tex.get(), rect);
}
public: public:
IconAtlas() = default; IconAtlas() = default;
operator bool() const {return m_tex;} operator bool() const { return m_tex; }
void initializeAtlas(const boo::ObjToken<boo::ITextureS>& tex) void initializeAtlas(const boo::ObjToken<boo::ITextureS>& tex) {
{ m_tex = tex;
m_tex = tex; for (int c = 0; c < COLS; ++c)
for (int c=0 ; c<COLS ; ++c) for (int r = 0; r < ROWS; ++r)
for (int r=0 ; r<ROWS ; ++r) m_icons[c][r] = MakeIcon(c, r);
m_icons[c][r] = MakeIcon(c, r); }
} void destroyAtlas() {
void destroyAtlas() for (int c = 0; c < COLS; ++c)
{ for (int r = 0; r < ROWS; ++r)
for (int c=0 ; c<COLS ; ++c) m_icons[c][r].m_tex.reset();
for (int r=0 ; r<ROWS ; ++r) m_tex.reset();
m_icons[c][r].m_tex.reset(); }
m_tex.reset(); Icon& getIcon(size_t c, size_t r) { return m_icons[c][r]; }
}
Icon& getIcon(size_t c, size_t r) {return m_icons[c][r];}
}; };
class IconView : public View class IconView : public View {
{ VertexBufferBindingTex m_vertexBinding;
VertexBufferBindingTex m_vertexBinding;
public: public:
IconView(ViewResources& res, View& parentView, Icon& icon); IconView(ViewResources& res, View& parentView, Icon& icon);
void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub); void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub);
void draw(boo::IGraphicsCommandQueue* gfxQ); void draw(boo::IGraphicsCommandQueue* gfxQ);
}; };
} } // namespace specter

View File

@ -5,89 +5,82 @@
#include "ScrollView.hpp" #include "ScrollView.hpp"
#include "IMenuNode.hpp" #include "IMenuNode.hpp"
namespace specter namespace specter {
{
class Menu : public View class Menu : public View {
{ IMenuNode* m_rootNode;
IMenuNode* m_rootNode; IMenuNode* m_thisNode;
IMenuNode* m_thisNode; std::unique_ptr<Menu> m_subMenu;
std::unique_ptr<Menu> m_subMenu; std::unique_ptr<TextView> m_headText;
std::unique_ptr<TextView> m_headText;
int m_cWidth, m_cHeight, m_cTop; int m_cWidth, m_cHeight, m_cTop;
SolidShaderVert m_verts[8]; SolidShaderVert m_verts[8];
VertexBufferBindingSolid m_vertsBinding; VertexBufferBindingSolid m_vertsBinding;
void setVerts(int width, int height, float pf); void setVerts(int width, int height, float pf);
struct ContentView : View struct ContentView : View {
{ Menu& m_menu;
Menu& m_menu; ContentView(ViewResources& res, Menu& menu);
ContentView(ViewResources& res, Menu& menu);
boo::SWindowRect m_scissorRect; boo::SWindowRect m_scissorRect;
SolidShaderVert m_hlVerts[4]; SolidShaderVert m_hlVerts[4];
VertexBufferBindingSolid m_hlVertsBinding; VertexBufferBindingSolid m_hlVertsBinding;
size_t m_highlightedItem = -1; size_t m_highlightedItem = -1;
void setHighlightedItem(size_t idx); void setHighlightedItem(size_t idx);
void unsetHighlightedItem(size_t idx) void unsetHighlightedItem(size_t idx) {
{ if (m_highlightedItem == idx)
if (m_highlightedItem == idx) setHighlightedItem(-1);
setHighlightedItem(-1); }
}
void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseMove(const boo::SWindowCoord&);
void mouseLeave(const boo::SWindowCoord&);
void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub,
const boo::SWindowRect& scissor);
void draw(boo::IGraphicsCommandQueue* gfxQ);
int nominalWidth() const {return m_menu.m_cWidth;}
int nominalHeight() const {return m_menu.m_cHeight;}
};
std::unique_ptr<ContentView> m_content;
ViewChild<std::unique_ptr<ScrollView>> m_scroll;
struct ItemView : View
{
Menu& m_menu;
std::unique_ptr<TextView> m_textView;
size_t m_idx;
IMenuNode* m_node;
ItemView(ViewResources& res, Menu& menu, std::string_view text, size_t idx, IMenuNode* node);
void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseEnter(const boo::SWindowCoord&);
void mouseLeave(const boo::SWindowCoord&);
void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub);
void draw(boo::IGraphicsCommandQueue* gfxQ);
};
std::vector<ViewChild<std::unique_ptr<ItemView>>> m_items;
IMenuNode* m_deferredActivation = nullptr;
Menu(ViewResources& res, View& parentView, IMenuNode* rootNode, IMenuNode* thisNode);
public:
Menu(ViewResources& res, View& parentView, IMenuNode* rootNode);
void reset(IMenuNode* rootNode);
void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey); void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey); void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseMove(const boo::SWindowCoord&); void mouseMove(const boo::SWindowCoord&);
void mouseLeave(const boo::SWindowCoord&); void mouseLeave(const boo::SWindowCoord&);
void scroll(const boo::SWindowCoord&, const boo::SScrollDelta&);
void think(); void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub, const boo::SWindowRect& scissor);
void draw(boo::IGraphicsCommandQueue* gfxQ);
int nominalWidth() const { return m_menu.m_cWidth; }
int nominalHeight() const { return m_menu.m_cHeight; }
};
std::unique_ptr<ContentView> m_content;
ViewChild<std::unique_ptr<ScrollView>> m_scroll;
struct ItemView : View {
Menu& m_menu;
std::unique_ptr<TextView> m_textView;
size_t m_idx;
IMenuNode* m_node;
ItemView(ViewResources& res, Menu& menu, std::string_view text, size_t idx, IMenuNode* node);
void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseEnter(const boo::SWindowCoord&);
void mouseLeave(const boo::SWindowCoord&);
void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub); void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub);
void draw(boo::IGraphicsCommandQueue* gfxQ); void draw(boo::IGraphicsCommandQueue* gfxQ);
};
std::vector<ViewChild<std::unique_ptr<ItemView>>> m_items;
IMenuNode* m_deferredActivation = nullptr;
Menu(ViewResources& res, View& parentView, IMenuNode* rootNode, IMenuNode* thisNode);
public:
Menu(ViewResources& res, View& parentView, IMenuNode* rootNode);
void reset(IMenuNode* rootNode);
void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseMove(const boo::SWindowCoord&);
void mouseLeave(const boo::SWindowCoord&);
void scroll(const boo::SWindowCoord&, const boo::SScrollDelta&);
void think();
void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub);
void draw(boo::IGraphicsCommandQueue* gfxQ);
}; };
} } // namespace specter

View File

@ -4,73 +4,56 @@
#include "MultiLineTextView.hpp" #include "MultiLineTextView.hpp"
#include "Button.hpp" #include "Button.hpp"
namespace specter namespace specter {
{
class MessageWindow : public ModalWindow class MessageWindow : public ModalWindow {
{
public: public:
enum class Type enum class Type { InfoOk, ErrorOk, ConfirmOkCancel };
{
InfoOk,
ErrorOk,
ConfirmOkCancel
};
private: private:
Type m_type; Type m_type;
std::function<void(bool ok)> m_func; std::function<void(bool ok)> m_func;
std::unique_ptr<MultiLineTextView> m_text; std::unique_ptr<MultiLineTextView> m_text;
struct OKBinding : IButtonBinding struct OKBinding : IButtonBinding {
{ MessageWindow& m_mw;
MessageWindow& m_mw; std::string m_name;
std::string m_name; OKBinding(MessageWindow& mw, std::string_view name) : m_mw(mw), m_name(name) {}
OKBinding(MessageWindow& mw, std::string_view name) : m_mw(mw), m_name(name) {} std::string_view name(const Control* control) const { return m_name; }
std::string_view name(const Control* control) const {return m_name;} void activated(const Button* button, const boo::SWindowCoord& coord) { m_mw.m_func(true); }
void activated(const Button* button, const boo::SWindowCoord& coord) } m_okBind;
{ ViewChild<std::unique_ptr<Button>> m_ok;
m_mw.m_func(true);
}
} m_okBind;
ViewChild<std::unique_ptr<Button>> m_ok;
struct CancelBinding : IButtonBinding struct CancelBinding : IButtonBinding {
{ MessageWindow& m_mw;
MessageWindow& m_mw; std::string m_name;
std::string m_name; CancelBinding(MessageWindow& mw, std::string_view name) : m_mw(mw), m_name(name) {}
CancelBinding(MessageWindow& mw, std::string_view name) : m_mw(mw), m_name(name) {} std::string_view name(const Control* control) const { return m_name; }
std::string_view name(const Control* control) const {return m_name;} void activated(const Button* button, const boo::SWindowCoord& coord) { m_mw.m_func(false); }
void activated(const Button* button, const boo::SWindowCoord& coord) } m_cancelBind;
{ ViewChild<std::unique_ptr<Button>> m_cancel;
m_mw.m_func(false);
}
} m_cancelBind;
ViewChild<std::unique_ptr<Button>> m_cancel;
public: public:
MessageWindow(ViewResources& res, View& parentView, MessageWindow(ViewResources& res, View& parentView, Type type, std::string_view message,
Type type, std::string_view message, std::function<void(bool ok)> func); std::function<void(bool ok)> func);
void updateContentOpacity(float opacity) void updateContentOpacity(float opacity) {
{ zeus::CColor color = zeus::CColor::lerp({1, 1, 1, 0}, {1, 1, 1, 1}, opacity);
zeus::CColor color = zeus::CColor::lerp({1,1,1,0}, {1,1,1,1}, opacity); ModalWindow::setMultiplyColor(color);
ModalWindow::setMultiplyColor(color); m_text->setMultiplyColor(color);
m_text->setMultiplyColor(color); m_ok.m_view->setMultiplyColor(color);
m_ok.m_view->setMultiplyColor(color); m_cancel.m_view->setMultiplyColor(color);
m_cancel.m_view->setMultiplyColor(color); }
}
void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey); void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey); void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseMove(const boo::SWindowCoord&); void mouseMove(const boo::SWindowCoord&);
void mouseEnter(const boo::SWindowCoord&); void mouseEnter(const boo::SWindowCoord&);
void mouseLeave(const boo::SWindowCoord&); void mouseLeave(const boo::SWindowCoord&);
void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub); void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub);
void draw(boo::IGraphicsCommandQueue* gfxQ); void draw(boo::IGraphicsCommandQueue* gfxQ);
}; };
} } // namespace specter

View File

@ -3,82 +3,66 @@
#include <specter/View.hpp> #include <specter/View.hpp>
#include <specter/MultiLineTextView.hpp> #include <specter/MultiLineTextView.hpp>
namespace specter namespace specter {
{ class ModalWindow : public View {
class ModalWindow : public View
{
public: public:
enum class Phase enum class Phase { BuildIn, ResWait, Showing, BuildOut, Done };
{
BuildIn,
ResWait,
Showing,
BuildOut,
Done
};
private: private:
int m_frame = 0; int m_frame = 0;
int m_contentStartFrame = 0; int m_contentStartFrame = 0;
float m_lineTime = 0.0; float m_lineTime = 0.0;
Phase m_phase = Phase::BuildIn; Phase m_phase = Phase::BuildIn;
int m_width = 0; int m_width = 0;
int m_height = 0; int m_height = 0;
RectangleConstraint m_constraint; RectangleConstraint m_constraint;
zeus::CColor m_windowBg; zeus::CColor m_windowBg;
zeus::CColor m_windowBgClear; zeus::CColor m_windowBgClear;
zeus::CColor m_line1; zeus::CColor m_line1;
zeus::CColor m_line2; zeus::CColor m_line2;
zeus::CColor m_line2Clear; zeus::CColor m_line2Clear;
ViewBlock m_viewBlock; ViewBlock m_viewBlock;
hecl::UniformBufferPool<ViewBlock>::Token m_viewBlockBuf; hecl::UniformBufferPool<ViewBlock>::Token m_viewBlockBuf;
union union {
{ struct {
struct SolidShaderVert lineVerts[22];
{ SolidShaderVert fillVerts[16];
SolidShaderVert lineVerts[22]; } m_verts;
SolidShaderVert fillVerts[16]; SolidShaderVert _m_verts[38];
} m_verts; };
SolidShaderVert _m_verts[38];
};
void setLineVerts(int width, int height, float pf, float t); void setLineVerts(int width, int height, float pf, float t);
void setLineVertsOut(int width, int height, float pf, float t); void setLineVertsOut(int width, int height, float pf, float t);
void setLineColors(float t); void setLineColors(float t);
void setLineColorsOut(float t); void setLineColorsOut(float t);
void setFillVerts(int width, int height, float pf); void setFillVerts(int width, int height, float pf);
void setFillColors(float t); void setFillColors(float t);
VertexBufferBindingSolid m_vertsBinding; VertexBufferBindingSolid m_vertsBinding;
void _loadVerts() void _loadVerts() { m_vertsBinding.load<decltype(_m_verts)>(_m_verts); }
{
m_vertsBinding.load<decltype(_m_verts)>(_m_verts);
}
std::unique_ptr<TextView> m_cornersOutline[4]; std::unique_ptr<TextView> m_cornersOutline[4];
std::unique_ptr<TextView> m_cornersFilled[4]; std::unique_ptr<TextView> m_cornersFilled[4];
protected: protected:
virtual void updateContentOpacity(float opacity) {} virtual void updateContentOpacity(float opacity) {}
RectangleConstraint& constraint() {return m_constraint;} RectangleConstraint& constraint() { return m_constraint; }
public: public:
ModalWindow(ViewResources& res, View& parentView, const RectangleConstraint& constraint, const zeus::CColor& bgColor); ModalWindow(ViewResources& res, View& parentView, const RectangleConstraint& constraint, const zeus::CColor& bgColor);
ModalWindow(ViewResources& res, View& parentView, const RectangleConstraint& constraint); ModalWindow(ViewResources& res, View& parentView, const RectangleConstraint& constraint);
void think(); void think();
bool skipBuildInAnimation(); bool skipBuildInAnimation();
void close(bool skipAnimation=false); void close(bool skipAnimation = false);
bool closed() const {return m_phase >= Phase::BuildOut;} bool closed() const { return m_phase >= Phase::BuildOut; }
ModalWindow::Phase phase() const {return m_phase;} ModalWindow::Phase phase() const { return m_phase; }
void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub); void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub);
void draw(boo::IGraphicsCommandQueue* gfxQ); void draw(boo::IGraphicsCommandQueue* gfxQ);
}; };
} } // namespace specter

View File

@ -4,50 +4,43 @@
#include "TextView.hpp" #include "TextView.hpp"
#include "FontCache.hpp" #include "FontCache.hpp"
namespace specter namespace specter {
{
class MultiLineTextView : public View class MultiLineTextView : public View {
{ ViewResources& m_viewSystem;
ViewResources& m_viewSystem; std::vector<std::unique_ptr<TextView>> m_lines;
std::vector<std::unique_ptr<TextView>> m_lines; const FontAtlas& m_fontAtlas;
const FontAtlas& m_fontAtlas; TextView::Alignment m_align;
TextView::Alignment m_align; size_t m_lineCapacity;
size_t m_lineCapacity; float m_lineHeight;
float m_lineHeight; int m_width;
int m_width; std::string LineWrap(std::string_view str, int wrap);
std::string LineWrap(std::string_view str, int wrap); std::wstring LineWrap(std::wstring_view str, int wrap);
std::wstring LineWrap(std::wstring_view str, int wrap);
public: public:
MultiLineTextView(ViewResources& res, View& parentView, const FontAtlas& font, MultiLineTextView(ViewResources& res, View& parentView, const FontAtlas& font,
TextView::Alignment align=TextView::Alignment::Left, TextView::Alignment align = TextView::Alignment::Left, size_t lineCapacity = 256,
size_t lineCapacity=256, float lineHeight=1.0); float lineHeight = 1.0);
MultiLineTextView(ViewResources& res, View& parentView, FontTag font, MultiLineTextView(ViewResources& res, View& parentView, FontTag font,
TextView::Alignment align=TextView::Alignment::Left, TextView::Alignment align = TextView::Alignment::Left, size_t lineCapacity = 256,
size_t lineCapacity=256, float lineHeight=1.0); float lineHeight = 1.0);
void typesetGlyphs(std::string_view str, void typesetGlyphs(std::string_view str, const zeus::CColor& defaultColor = zeus::CColor::skWhite, unsigned wrap = 0);
const zeus::CColor& defaultColor=zeus::CColor::skWhite, void typesetGlyphs(std::wstring_view str, const zeus::CColor& defaultColor = zeus::CColor::skWhite,
unsigned wrap=0); unsigned wrap = 0);
void typesetGlyphs(std::wstring_view str,
const zeus::CColor& defaultColor=zeus::CColor::skWhite,
unsigned wrap=0);
void colorGlyphs(const zeus::CColor& newColor); void colorGlyphs(const zeus::CColor& newColor);
void setMultiplyColor(const zeus::CColor& color) void setMultiplyColor(const zeus::CColor& color) {
{ for (std::unique_ptr<TextView>& l : m_lines)
for (std::unique_ptr<TextView>& l : m_lines) l->setMultiplyColor(color);
l->setMultiplyColor(color); }
}
void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub); void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub);
void draw(boo::IGraphicsCommandQueue* gfxQ); void draw(boo::IGraphicsCommandQueue* gfxQ);
int nominalWidth() const {return m_width;} int nominalWidth() const { return m_width; }
int nominalHeight() const {return (int(m_lineHeight * m_fontAtlas.FT_LineHeight()) >> 6) * m_lines.size();} int nominalHeight() const { return (int(m_lineHeight * m_fontAtlas.FT_LineHeight()) >> 6) * m_lines.size(); }
}; };
} } // namespace specter

View File

@ -1,2 +1 @@
#pragma once #pragma once

View File

@ -1,2 +1 @@
#pragma once #pragma once

View File

@ -2,51 +2,48 @@
#include "specter/TextView.hpp" #include "specter/TextView.hpp"
namespace specter namespace specter {
{
class ViewResources; class ViewResources;
class NumericField : public View class NumericField : public View {
{ std::string m_textStr;
std::string m_textStr; std::unique_ptr<TextView> m_text;
std::unique_ptr<TextView> m_text; SolidShaderVert m_verts[28];
SolidShaderVert m_verts[28];
ViewBlock m_bBlock; ViewBlock m_bBlock;
boo::IGraphicsBufferD* m_bBlockBuf; boo::IGraphicsBufferD* m_bBlockBuf;
boo::IGraphicsBufferD* m_bVertsBuf; boo::IGraphicsBufferD* m_bVertsBuf;
boo::IShaderDataBinding* m_bShaderBinding; boo::IShaderDataBinding* m_bShaderBinding;
int m_nomWidth, m_nomHeight; int m_nomWidth, m_nomHeight;
bool m_pressed = false; bool m_pressed = false;
bool m_hovered = false; bool m_hovered = false;
void setInactive();
void setHover();
void setPressed();
void setDisabled();
void setInactive();
void setHover();
void setPressed();
void setDisabled();
public: public:
class Resources class Resources {
{ friend class ViewResources;
friend class ViewResources; friend class Button;
friend class Button;
void init(boo::IGraphicsDataFactory* factory, const IThemeData& theme); void init(boo::IGraphicsDataFactory* factory, const IThemeData& theme);
}; };
NumericField(ViewResources& res, View& parentView, std::string_view text); NumericField(ViewResources& res, View& parentView, std::string_view text);
void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey); void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey); void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseEnter(const boo::SWindowCoord&); void mouseEnter(const boo::SWindowCoord&);
void mouseLeave(const boo::SWindowCoord&); void mouseLeave(const boo::SWindowCoord&);
void resized(const boo::SWindowRect& rootView, const boo::SWindowRect& sub); void resized(const boo::SWindowRect& rootView, const boo::SWindowRect& sub);
void draw(boo::IGraphicsCommandQueue* gfxQ); void draw(boo::IGraphicsCommandQueue* gfxQ);
void setText(std::string_view text); void setText(std::string_view text);
int nominalWidth() const {return m_nomWidth;} int nominalWidth() const { return m_nomWidth; }
int nominalHeight() const {return m_nomHeight;} int nominalHeight() const { return m_nomHeight; }
}; };
} } // namespace specter

View File

@ -1,42 +1,36 @@
#pragma once #pragma once
namespace specter namespace specter {
{ class Outliner {
class Outliner class Node : public View {
{ struct INodeController {
class Node : public View virtual boo::ITexture* icon() const { return nullptr; }
{ virtual const std::string* text() const { return nullptr; }
struct INodeController virtual size_t subNodeCount() const { return 0; }
{ virtual INodeController* subNode(size_t idx) { return nullptr; }
virtual boo::ITexture* icon() const { return nullptr; } virtual void activated(const boo::SWindowCoord& coord) {}
virtual const std::string* text() const { return nullptr; }
virtual size_t subNodeCount() const { return 0; }
virtual INodeController* subNode(size_t idx) { return nullptr; }
virtual void activated(const boo::SWindowCoord& coord) {}
};
std::string m_description;
std::vector<std::unique_ptr<Node>> m_children;
bool m_collapsible;
bool m_collapsed;
public:
class Resources
{
friend class ViewResources;
void init(boo::IGraphicsDataFactory* factory, const IThemeData& theme);
};
Node(ViewResources& res, View& parentView, std::string_view description);
void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseEnter(const boo::SWindowCoord&);
void mouseLeave(const boo::SWindowCoord&);
void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub);
void draw(boo::IGraphicsCommandQueue* gfxQ);
void think();
}; };
};
}
std::string m_description;
std::vector<std::unique_ptr<Node>> m_children;
bool m_collapsible;
bool m_collapsed;
public:
class Resources {
friend class ViewResources;
void init(boo::IGraphicsDataFactory* factory, const IThemeData& theme);
};
Node(ViewResources& res, View& parentView, std::string_view description);
void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseEnter(const boo::SWindowCoord&);
void mouseLeave(const boo::SWindowCoord&);
void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub);
void draw(boo::IGraphicsCommandQueue* gfxQ);
void think();
};
};
} // namespace specter

View File

@ -1,2 +1 @@
#pragma once #pragma once

View File

@ -3,74 +3,63 @@
#include "Button.hpp" #include "Button.hpp"
#include "ScrollView.hpp" #include "ScrollView.hpp"
namespace specter namespace specter {
{
struct IPathButtonsBinding struct IPathButtonsBinding {
{ virtual void pathButtonActivated(size_t idx) = 0;
virtual void pathButtonActivated(size_t idx)=0;
}; };
class PathButtons : public ScrollView class PathButtons : public ScrollView {
{ struct ContentView : public View {
struct ContentView : public View PathButtons& m_pb;
{ boo::SWindowRect m_scissorRect;
PathButtons& m_pb;
boo::SWindowRect m_scissorRect;
void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey); void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey); void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseMove(const boo::SWindowCoord&); void mouseMove(const boo::SWindowCoord&);
void mouseLeave(const boo::SWindowCoord&); void mouseLeave(const boo::SWindowCoord&);
int nominalWidth() const int nominalWidth() const {
{ int ret = 0;
int ret = 0; for (PathButton& b : m_pb.m_pathButtons)
for (PathButton& b : m_pb.m_pathButtons) ret += b.m_button.m_view->nominalWidth() + 2;
ret += b.m_button.m_view->nominalWidth() + 2; return ret;
return ret; }
} int nominalHeight() const {
int nominalHeight() const return m_pb.m_pathButtons.size() ? m_pb.m_pathButtons[0].m_button.m_view->nominalHeight() : 0;
{ }
return m_pb.m_pathButtons.size() ? m_pb.m_pathButtons[0].m_button.m_view->nominalHeight() : 0;
}
void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub, const boo::SWindowRect& scissor); void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub, const boo::SWindowRect& scissor);
void draw(boo::IGraphicsCommandQueue* gfxQ); void draw(boo::IGraphicsCommandQueue* gfxQ);
ContentView(ViewResources& res, PathButtons& pb) ContentView(ViewResources& res, PathButtons& pb) : View(res, pb), m_pb(pb) {}
: View(res, pb), m_pb(pb) {} };
}; ViewChild<std::unique_ptr<ContentView>> m_contentView;
ViewChild<std::unique_ptr<ContentView>> m_contentView;
int m_pathButtonPending = -1; int m_pathButtonPending = -1;
IPathButtonsBinding& m_binding; IPathButtonsBinding& m_binding;
bool m_fillContainer; bool m_fillContainer;
struct PathButton final : IButtonBinding struct PathButton final : IButtonBinding {
{ PathButtons& m_pb;
PathButtons& m_pb; size_t m_idx;
size_t m_idx; ViewChild<std::unique_ptr<Button>> m_button;
ViewChild<std::unique_ptr<Button>> m_button; PathButton(PathButtons& pb, ViewResources& res, size_t idx, const hecl::SystemString& str) : m_pb(pb), m_idx(idx) {
PathButton(PathButtons& pb, ViewResources& res, size_t idx, const hecl::SystemString& str) m_button.m_view.reset(new Button(res, pb, this, hecl::SystemUTF8Conv(str).str()));
: m_pb(pb), m_idx(idx) }
{ std::string_view name(const Control* control) const { return m_button.m_view->getText(); }
m_button.m_view.reset(new Button(res, pb, this, hecl::SystemUTF8Conv(str).str())); void activated(const Button* button, const boo::SWindowCoord&) { m_pb.m_pathButtonPending = m_idx; }
} };
std::string_view name(const Control* control) const {return m_button.m_view->getText();} friend struct PathButton;
void activated(const Button* button, const boo::SWindowCoord&) {m_pb.m_pathButtonPending = m_idx;} std::vector<PathButton> m_pathButtons;
};
friend struct PathButton;
std::vector<PathButton> m_pathButtons;
public: public:
PathButtons(ViewResources& res, View& parentView, IPathButtonsBinding& binding, bool fillContainer=false); PathButtons(ViewResources& res, View& parentView, IPathButtonsBinding& binding, bool fillContainer = false);
void setButtons(const std::vector<hecl::SystemString>& comps); void setButtons(const std::vector<hecl::SystemString>& comps);
void setMultiplyColor(const zeus::CColor& color); void setMultiplyColor(const zeus::CColor& color);
/* Fill all available space in container when requested */ /* Fill all available space in container when requested */
void containerResized(const boo::SWindowRect& root, const boo::SWindowRect& sub); void containerResized(const boo::SWindowRect& root, const boo::SWindowRect& sub);
}; };
} } // namespace specter

View File

@ -12,242 +12,215 @@
#include "optional.hpp" #include "optional.hpp"
#include "boo/boo.hpp" #include "boo/boo.hpp"
namespace specter namespace specter {
{
class RootView : public View class RootView : public View {
{ boo::IWindow* m_window = nullptr;
boo::IWindow* m_window = nullptr; boo::ObjToken<boo::ITextureR> m_renderTex;
boo::ObjToken<boo::ITextureR> m_renderTex; boo::SWindowRect m_rootRect = {};
boo::SWindowRect m_rootRect = {}; bool m_resizeRTDirty = false;
bool m_resizeRTDirty = false; bool m_destroyed = false;
bool m_destroyed = false; IViewManager& m_viewMan;
IViewManager& m_viewMan; ViewResources* m_viewRes;
ViewResources* m_viewRes; ITextInputView* m_activeTextView = nullptr;
ITextInputView* m_activeTextView = nullptr; View* m_activeDragView = nullptr;
View* m_activeDragView = nullptr; Button* m_activeMenuButton = nullptr;
Button* m_activeMenuButton = nullptr;
ViewChild<std::unique_ptr<View>> m_rightClickMenu; ViewChild<std::unique_ptr<View>> m_rightClickMenu;
boo::SWindowRect m_rightClickMenuRootAndLoc; boo::SWindowRect m_rightClickMenuRootAndLoc;
SplitView* m_hoverSplitDragView = nullptr; SplitView* m_hoverSplitDragView = nullptr;
bool m_activeSplitDragView = false; bool m_activeSplitDragView = false;
SplitView* recursiveTestSplitHover(SplitView* sv, const boo::SWindowCoord& coord) const; SplitView* recursiveTestSplitHover(SplitView* sv, const boo::SWindowCoord& coord) const;
boo::DeferredWindowEvents<RootView> m_events; boo::DeferredWindowEvents<RootView> m_events;
struct SplitMenuSystem : IMenuNode struct SplitMenuSystem : IMenuNode {
{ RootView& m_rv;
RootView& m_rv; std::string m_text;
std::string m_text;
SplitView* m_splitView = nullptr; SplitView* m_splitView = nullptr;
enum class Phase enum class Phase {
{ Inactive,
Inactive, InteractiveSplit,
InteractiveSplit, InteractiveJoin,
InteractiveJoin, } m_phase = Phase::Inactive;
} m_phase = Phase::Inactive; int m_interactiveSlot = 0;
int m_interactiveSlot = 0; float m_interactiveSplit = 0.5;
float m_interactiveSplit = 0.5; bool m_interactiveDown = false;
bool m_interactiveDown = false;
VertexBufferBindingSolid m_vertsBinding; VertexBufferBindingSolid m_vertsBinding;
ViewBlock m_viewBlock; ViewBlock m_viewBlock;
hecl::UniformBufferPool<ViewBlock>::Token m_viewVertBlockBuf; hecl::UniformBufferPool<ViewBlock>::Token m_viewVertBlockBuf;
SolidShaderVert m_verts[32]; SolidShaderVert m_verts[32];
void setArrowVerts(const boo::SWindowRect& rect, SplitView::ArrowDir dir); void setArrowVerts(const boo::SWindowRect& rect, SplitView::ArrowDir dir);
void setLineVerts(const boo::SWindowRect& rect, float split, SplitView::Axis axis); void setLineVerts(const boo::SWindowRect& rect, float split, SplitView::Axis axis);
void mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mods);
void mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mods);
void mouseMove(const boo::SWindowCoord& coord);
void mouseLeave(const boo::SWindowCoord& coord);
void resized();
void draw(boo::IGraphicsCommandQueue* gfxQ);
SplitMenuSystem(RootView& rv, boo::IGraphicsDataFactory::Context& ctx);
const std::string* text() const {return &m_text;}
size_t subNodeCount() const {return 2;}
IMenuNode* subNode(size_t idx)
{
if (idx)
return &m_joinActionNode;
else
return &m_splitActionNode;
}
boo::SWindowCoord m_deferredCoord;
bool m_deferredSplit = false;
bool m_deferredJoin = false;
struct SplitActionNode : IMenuNode
{
SplitMenuSystem& m_smn;
std::string m_text;
SplitActionNode(SplitMenuSystem& smn);
const std::string* text() const {return &m_text;}
void activated(const boo::SWindowCoord& coord)
{
m_smn.m_deferredSplit = true;
m_smn.m_deferredCoord = coord;
}
} m_splitActionNode;
struct JoinActionNode : IMenuNode
{
SplitMenuSystem& m_smn;
std::string m_text;
JoinActionNode(SplitMenuSystem& smn);
const std::string* text() const {return &m_text;}
void activated(const boo::SWindowCoord& coord)
{
m_smn.m_deferredJoin = true;
m_smn.m_deferredCoord = coord;
}
} m_joinActionNode;
};
std::experimental::optional<SplitMenuSystem> m_splitMenuSystem;
public:
RootView(IViewManager& viewMan, ViewResources& res, boo::IWindow* window);
~RootView();
void destroyed();
bool isDestroyed() const {return m_destroyed;}
void resized(const boo::SWindowRect& rect, bool) { resized(rect, rect); }
void resized(const boo::SWindowRect& rootView, const boo::SWindowRect& sub);
void mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mods); void mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mods);
void mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mods); void mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mods);
void mouseMove(const boo::SWindowCoord& coord); void mouseMove(const boo::SWindowCoord& coord);
void mouseEnter(const boo::SWindowCoord& coord);
void mouseLeave(const boo::SWindowCoord& coord); void mouseLeave(const boo::SWindowCoord& coord);
void scroll(const boo::SWindowCoord& coord, const boo::SScrollDelta& scroll);
void touchDown(const boo::STouchCoord& coord, uintptr_t tid); void resized();
void touchUp(const boo::STouchCoord& coord, uintptr_t tid);
void touchMove(const boo::STouchCoord& coord, uintptr_t tid);
void charKeyDown(unsigned long charCode, boo::EModifierKey mods, bool isRepeat);
void charKeyUp(unsigned long charCode, boo::EModifierKey mods);
void specialKeyDown(boo::ESpecialKey key, boo::EModifierKey mods, bool isRepeat);
void specialKeyUp(boo::ESpecialKey key, boo::EModifierKey mods);
void modKeyDown(boo::EModifierKey mod, bool isRepeat);
void modKeyUp(boo::EModifierKey mod);
boo::ITextInputCallback* getTextInputCallback() {return m_activeTextView;}
void internalThink();
void dispatchEvents() {m_events.dispatchEvents();}
void draw(boo::IGraphicsCommandQueue* gfxQ); void draw(boo::IGraphicsCommandQueue* gfxQ);
const boo::SWindowRect& rootRect() const {return m_rootRect;}
boo::IWindow* window() const {return m_window;} SplitMenuSystem(RootView& rv, boo::IGraphicsDataFactory::Context& ctx);
IViewManager& viewManager() const {return m_viewMan;} const std::string* text() const { return &m_text; }
ViewResources& viewRes() const {return *m_viewRes;} size_t subNodeCount() const { return 2; }
const IThemeData& themeData() const {return *m_viewRes->m_theme;} IMenuNode* subNode(size_t idx) {
const boo::ObjToken<boo::ITextureR>& renderTex() const {return m_renderTex;} if (idx)
return &m_joinActionNode;
std::vector<View*>& accessContentViews() {return m_views;} else
return &m_splitActionNode;
void adoptRightClickMenu(std::unique_ptr<View>&& menu, const boo::SWindowCoord& coord)
{
m_rightClickMenu.m_view = std::move(menu);
m_rightClickMenuRootAndLoc = subRect();
m_rightClickMenuRootAndLoc.location[0] = coord.pixel[0];
m_rightClickMenuRootAndLoc.location[1] = coord.pixel[1];
updateSize();
}
View* getRightClickMenu() {return m_rightClickMenu.m_view.get();}
void setActiveTextView(ITextInputView* textView)
{
if (m_activeTextView)
m_activeTextView->setActive(false);
m_activeTextView = textView;
if (textView)
textView->setActive(true);
}
void setActiveDragView(View* dragView)
{
m_activeDragView = dragView;
}
void unsetActiveDragView(View* dragView)
{
if (dragView == m_activeDragView)
m_activeDragView = nullptr;
}
void setActiveMenuButton(Button* button)
{
m_activeMenuButton = button;
}
void unsetActiveMenuButton(Button* button)
{
if (button == m_activeMenuButton)
m_activeMenuButton = nullptr;
} }
void startSplitDrag(SplitView* sv, const boo::SWindowCoord& coord) boo::SWindowCoord m_deferredCoord;
{ bool m_deferredSplit = false;
m_hoverSplitDragView = sv; bool m_deferredJoin = false;
m_activeSplitDragView = true;
sv->startDragSplit(coord);
}
bool m_hSplitHover = false; struct SplitActionNode : IMenuNode {
void setHorizontalSplitHover(bool hover) SplitMenuSystem& m_smn;
{ std::string m_text;
m_hSplitHover = hover; SplitActionNode(SplitMenuSystem& smn);
_updateCursor(); const std::string* text() const { return &m_text; }
} void activated(const boo::SWindowCoord& coord) {
bool m_vSplitHover = false; m_smn.m_deferredSplit = true;
void setVerticalSplitHover(bool hover) m_smn.m_deferredCoord = coord;
{ }
m_vSplitHover = hover; } m_splitActionNode;
_updateCursor(); struct JoinActionNode : IMenuNode {
} SplitMenuSystem& m_smn;
bool m_textFieldHover = false; std::string m_text;
void setTextFieldHover(bool hover) JoinActionNode(SplitMenuSystem& smn);
{ const std::string* text() const { return &m_text; }
m_textFieldHover = hover; void activated(const boo::SWindowCoord& coord) {
_updateCursor(); m_smn.m_deferredJoin = true;
} m_smn.m_deferredCoord = coord;
bool m_spaceCornerHover = false; }
void setSpaceCornerHover(bool hover) } m_joinActionNode;
{ };
m_spaceCornerHover = hover; std::experimental::optional<SplitMenuSystem> m_splitMenuSystem;
_updateCursor();
}
void resetTooltip(ViewResources& res); public:
void displayTooltip(std::string_view name, std::string_view help); RootView(IViewManager& viewMan, ViewResources& res, boo::IWindow* window);
~RootView();
void beginInteractiveJoin(SplitView* sv, const boo::SWindowCoord& coord) void destroyed();
{ bool isDestroyed() const { return m_destroyed; }
m_splitMenuSystem->m_phase = SplitMenuSystem::Phase::InteractiveJoin;
m_splitMenuSystem->m_splitView = sv; void resized(const boo::SWindowRect& rect, bool) { resized(rect, rect); }
m_splitMenuSystem->mouseMove(coord); void resized(const boo::SWindowRect& rootView, const boo::SWindowRect& sub);
} void mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mods);
void mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mods);
void mouseMove(const boo::SWindowCoord& coord);
void mouseEnter(const boo::SWindowCoord& coord);
void mouseLeave(const boo::SWindowCoord& coord);
void scroll(const boo::SWindowCoord& coord, const boo::SScrollDelta& scroll);
void touchDown(const boo::STouchCoord& coord, uintptr_t tid);
void touchUp(const boo::STouchCoord& coord, uintptr_t tid);
void touchMove(const boo::STouchCoord& coord, uintptr_t tid);
void charKeyDown(unsigned long charCode, boo::EModifierKey mods, bool isRepeat);
void charKeyUp(unsigned long charCode, boo::EModifierKey mods);
void specialKeyDown(boo::ESpecialKey key, boo::EModifierKey mods, bool isRepeat);
void specialKeyUp(boo::ESpecialKey key, boo::EModifierKey mods);
void modKeyDown(boo::EModifierKey mod, bool isRepeat);
void modKeyUp(boo::EModifierKey mod);
boo::ITextInputCallback* getTextInputCallback() { return m_activeTextView; }
void internalThink();
void dispatchEvents() { m_events.dispatchEvents(); }
void draw(boo::IGraphicsCommandQueue* gfxQ);
const boo::SWindowRect& rootRect() const { return m_rootRect; }
boo::IWindow* window() const { return m_window; }
IViewManager& viewManager() const { return m_viewMan; }
ViewResources& viewRes() const { return *m_viewRes; }
const IThemeData& themeData() const { return *m_viewRes->m_theme; }
const boo::ObjToken<boo::ITextureR>& renderTex() const { return m_renderTex; }
std::vector<View*>& accessContentViews() { return m_views; }
void adoptRightClickMenu(std::unique_ptr<View>&& menu, const boo::SWindowCoord& coord) {
m_rightClickMenu.m_view = std::move(menu);
m_rightClickMenuRootAndLoc = subRect();
m_rightClickMenuRootAndLoc.location[0] = coord.pixel[0];
m_rightClickMenuRootAndLoc.location[1] = coord.pixel[1];
updateSize();
}
View* getRightClickMenu() { return m_rightClickMenu.m_view.get(); }
void setActiveTextView(ITextInputView* textView) {
if (m_activeTextView)
m_activeTextView->setActive(false);
m_activeTextView = textView;
if (textView)
textView->setActive(true);
}
void setActiveDragView(View* dragView) { m_activeDragView = dragView; }
void unsetActiveDragView(View* dragView) {
if (dragView == m_activeDragView)
m_activeDragView = nullptr;
}
void setActiveMenuButton(Button* button) { m_activeMenuButton = button; }
void unsetActiveMenuButton(Button* button) {
if (button == m_activeMenuButton)
m_activeMenuButton = nullptr;
}
void startSplitDrag(SplitView* sv, const boo::SWindowCoord& coord) {
m_hoverSplitDragView = sv;
m_activeSplitDragView = true;
sv->startDragSplit(coord);
}
bool m_hSplitHover = false;
void setHorizontalSplitHover(bool hover) {
m_hSplitHover = hover;
_updateCursor();
}
bool m_vSplitHover = false;
void setVerticalSplitHover(bool hover) {
m_vSplitHover = hover;
_updateCursor();
}
bool m_textFieldHover = false;
void setTextFieldHover(bool hover) {
m_textFieldHover = hover;
_updateCursor();
}
bool m_spaceCornerHover = false;
void setSpaceCornerHover(bool hover) {
m_spaceCornerHover = hover;
_updateCursor();
}
void resetTooltip(ViewResources& res);
void displayTooltip(std::string_view name, std::string_view help);
void beginInteractiveJoin(SplitView* sv, const boo::SWindowCoord& coord) {
m_splitMenuSystem->m_phase = SplitMenuSystem::Phase::InteractiveJoin;
m_splitMenuSystem->m_splitView = sv;
m_splitMenuSystem->mouseMove(coord);
}
private: private:
void _updateCursor() void _updateCursor() {
{ if (m_spaceCornerHover)
if (m_spaceCornerHover) m_window->setCursor(boo::EMouseCursor::Crosshairs);
m_window->setCursor(boo::EMouseCursor::Crosshairs); else if (m_vSplitHover)
else if (m_vSplitHover) m_window->setCursor(boo::EMouseCursor::HorizontalArrow);
m_window->setCursor(boo::EMouseCursor::HorizontalArrow); else if (m_hSplitHover)
else if (m_hSplitHover) m_window->setCursor(boo::EMouseCursor::VerticalArrow);
m_window->setCursor(boo::EMouseCursor::VerticalArrow); else if (m_textFieldHover)
else if (m_textFieldHover) m_window->setCursor(boo::EMouseCursor::IBeam);
m_window->setCursor(boo::EMouseCursor::IBeam); else
else m_window->setCursor(boo::EMouseCursor::Pointer);
m_window->setCursor(boo::EMouseCursor::Pointer); }
}
std::vector<View*> m_views; std::vector<View*> m_views;
std::unique_ptr<Tooltip> m_tooltip; std::unique_ptr<Tooltip> m_tooltip;
}; };
} } // namespace specter

View File

@ -3,98 +3,78 @@
#include "Button.hpp" #include "Button.hpp"
#include "IViewManager.hpp" #include "IViewManager.hpp"
namespace specter namespace specter {
{
class ViewResources; class ViewResources;
class Button; class Button;
class ScrollView : public View class ScrollView : public View {
{
public: public:
enum class Style enum class Style { Plain, ThinIndicator, SideButtons };
{
Plain,
ThinIndicator,
SideButtons
};
private: private:
Style m_style; Style m_style;
ScissorViewChild<View*> m_contentView; ScissorViewChild<View*> m_contentView;
int m_scroll[2] = {}; int m_scroll[2] = {};
int m_targetScroll[2] = {}; int m_targetScroll[2] = {};
size_t m_consecutiveIdx = 0; size_t m_consecutiveIdx = 0;
double m_consecutiveScroll[16][2] = {}; double m_consecutiveScroll[16][2] = {};
bool m_drawInd = false; bool m_drawInd = false;
bool m_drawSideButtons = false; bool m_drawSideButtons = false;
SolidShaderVert m_verts[4]; SolidShaderVert m_verts[4];
VertexBufferBindingSolid m_vertsBinding; VertexBufferBindingSolid m_vertsBinding;
enum class SideButtonState enum class SideButtonState { None, ScrollLeft, ScrollRight } m_sideButtonState = SideButtonState::None;
{ struct SideButtonBinding : IButtonBinding {
None, ScrollView& m_sv;
ScrollLeft, std::string m_leftName, m_rightName;
ScrollRight SideButtonBinding(ScrollView& sv, IViewManager& vm)
} m_sideButtonState = SideButtonState::None; : m_sv(sv)
struct SideButtonBinding : IButtonBinding , m_leftName(vm.translateOr("scroll_left", "Scroll Left"))
{ , m_rightName(vm.translateOr("scroll_right", "Scroll Right")) {}
ScrollView& m_sv; std::string_view name(const Control* control) const {
std::string m_leftName, m_rightName; return (control == reinterpret_cast<Control*>(m_sv.m_sideButtons[0].m_view.get())) ? m_leftName.c_str()
SideButtonBinding(ScrollView& sv, IViewManager& vm) : m_rightName.c_str();
: m_sv(sv), }
m_leftName(vm.translateOr("scroll_left", "Scroll Left")), void down(const Button* button, const boo::SWindowCoord& coord) {
m_rightName(vm.translateOr("scroll_right", "Scroll Right")) {} if (button == m_sv.m_sideButtons[0].m_view.get())
std::string_view name(const Control* control) const m_sv.m_sideButtonState = SideButtonState::ScrollRight;
{ else
return (control == reinterpret_cast<Control*>(m_sv.m_sideButtons[0].m_view.get())) ? m_sv.m_sideButtonState = SideButtonState::ScrollLeft;
m_leftName.c_str() : m_rightName.c_str(); }
} void up(const Button* button, const boo::SWindowCoord& coord) { m_sv.m_sideButtonState = SideButtonState::None; }
void down(const Button* button, const boo::SWindowCoord& coord) } m_sideButtonBind;
{ ViewChild<std::unique_ptr<Button>> m_sideButtons[2];
if (button == m_sv.m_sideButtons[0].m_view.get())
m_sv.m_sideButtonState = SideButtonState::ScrollRight;
else
m_sv.m_sideButtonState = SideButtonState::ScrollLeft;
}
void up(const Button* button, const boo::SWindowCoord& coord)
{
m_sv.m_sideButtonState = SideButtonState::None;
}
} m_sideButtonBind;
ViewChild<std::unique_ptr<Button>> m_sideButtons[2];
bool _scroll(const boo::SScrollDelta& scroll); bool _scroll(const boo::SScrollDelta& scroll);
int scrollAreaWidth() const; int scrollAreaWidth() const;
public: public:
ScrollView(ViewResources& res, View& parentView, Style style); ScrollView(ViewResources& res, View& parentView, Style style);
void setContentView(View* v) void setContentView(View* v) {
{ m_contentView.m_view = v;
m_contentView.m_view = v; updateSize();
updateSize(); }
}
void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey); void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey); void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseMove(const boo::SWindowCoord&); void mouseMove(const boo::SWindowCoord&);
void mouseEnter(const boo::SWindowCoord&); void mouseEnter(const boo::SWindowCoord&);
void mouseLeave(const boo::SWindowCoord&); void mouseLeave(const boo::SWindowCoord&);
void scroll(const boo::SWindowCoord& coord, const boo::SScrollDelta& scroll); void scroll(const boo::SWindowCoord& coord, const boo::SScrollDelta& scroll);
int getScrollX() const {return m_scroll[0];} int getScrollX() const { return m_scroll[0]; }
int getScrollY() const {return m_scroll[1];} int getScrollY() const { return m_scroll[1]; }
int nominalWidth() const {return subRect().size[0];} int nominalWidth() const { return subRect().size[0]; }
int nominalHeight() const {return subRect().size[1];} int nominalHeight() const { return subRect().size[1]; }
void setMultiplyColor(const zeus::CColor& color); void setMultiplyColor(const zeus::CColor& color);
void think(); void think();
void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub); void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub);
void draw(boo::IGraphicsCommandQueue* gfxQ); void draw(boo::IGraphicsCommandQueue* gfxQ);
}; };
} } // namespace specter

View File

@ -4,79 +4,72 @@
#include "Toolbar.hpp" #include "Toolbar.hpp"
#include "SplitView.hpp" #include "SplitView.hpp"
namespace specter namespace specter {
{
class Space; class Space;
struct ISplitSpaceController; struct ISplitSpaceController;
struct ISpaceController struct ISpaceController {
{ virtual bool spaceSplitAllowed() const { return false; }
virtual bool spaceSplitAllowed() const {return false;} virtual ISplitSpaceController* spaceSplit(SplitView::Axis axis, int thisSlot) { return nullptr; }
virtual ISplitSpaceController* spaceSplit(SplitView::Axis axis, int thisSlot) {return nullptr;}
}; };
struct ISplitSpaceController struct ISplitSpaceController {
{ virtual SplitView* splitView() = 0;
virtual SplitView* splitView()=0; virtual void updateSplit(float split) = 0;
virtual void updateSplit(float split)=0; virtual void joinViews(SplitView* thisSplit, int thisSlot, SplitView* otherSplit, int otherSlot) = 0;
virtual void joinViews(SplitView* thisSplit, int thisSlot, SplitView* otherSplit, int otherSlot)=0;
}; };
class Space : public View class Space : public View {
{ friend class RootView;
friend class RootView; ISpaceController& m_controller;
ISpaceController& m_controller; Toolbar::Position m_tbPos;
Toolbar::Position m_tbPos; ViewChild<std::unique_ptr<Toolbar>> m_toolbar;
ViewChild<std::unique_ptr<Toolbar>> m_toolbar; ViewChild<View*> m_contentView;
ViewChild<View*> m_contentView;
bool m_cornerDrag = false; bool m_cornerDrag = false;
int m_cornerDragPoint[2]; int m_cornerDragPoint[2];
struct CornerView : View struct CornerView : View {
{ Space& m_space;
Space& m_space; VertexBufferBindingSolid m_vertexBinding;
VertexBufferBindingSolid m_vertexBinding; bool m_flip;
bool m_flip; CornerView(ViewResources& res, Space& space, const zeus::CColor& triColor);
CornerView(ViewResources& res, Space& space, const zeus::CColor& triColor);
void mouseEnter(const boo::SWindowCoord&);
void mouseLeave(const boo::SWindowCoord&);
void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
using View::resized;
void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub, bool flip);
void draw(boo::IGraphicsCommandQueue* gfxQ);
};
friend struct CornerView;
ViewChild<std::unique_ptr<CornerView>> m_cornerView;
public:
Space(ViewResources& res, View& parentView, ISpaceController& controller,
Toolbar::Position toolbarPos, unsigned tbUnits);
View* setContentView(View* view);
Toolbar* toolbar() {return m_toolbar.m_view.get();}
void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseMove(const boo::SWindowCoord&);
void mouseEnter(const boo::SWindowCoord&); void mouseEnter(const boo::SWindowCoord&);
void mouseLeave(const boo::SWindowCoord&); void mouseLeave(const boo::SWindowCoord&);
void resized(const boo::SWindowRect& rootView, const boo::SWindowRect& sub); void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
using View::resized;
void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub, bool flip);
void draw(boo::IGraphicsCommandQueue* gfxQ); void draw(boo::IGraphicsCommandQueue* gfxQ);
};
friend struct CornerView;
ViewChild<std::unique_ptr<CornerView>> m_cornerView;
SplitView* findSplitViewOnSide(SplitView::Axis axis, int side); public:
Space(ViewResources& res, View& parentView, ISpaceController& controller, Toolbar::Position toolbarPos,
unsigned tbUnits);
View* setContentView(View* view);
Toolbar* toolbar() { return m_toolbar.m_view.get(); }
void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseMove(const boo::SWindowCoord&);
void mouseEnter(const boo::SWindowCoord&);
void mouseLeave(const boo::SWindowCoord&);
void resized(const boo::SWindowRect& rootView, const boo::SWindowRect& sub);
void draw(boo::IGraphicsCommandQueue* gfxQ);
void setMultiplyColor(const zeus::CColor& color) SplitView* findSplitViewOnSide(SplitView::Axis axis, int side);
{
View::setMultiplyColor(color);
if (m_contentView.m_view)
m_contentView.m_view->setMultiplyColor(color);
if (m_toolbar.m_view)
m_toolbar.m_view->setMultiplyColor(color);
}
bool isSpace() const { return true; } void setMultiplyColor(const zeus::CColor& color) {
View::setMultiplyColor(color);
if (m_contentView.m_view)
m_contentView.m_view->setMultiplyColor(color);
if (m_toolbar.m_view)
m_toolbar.m_view->setMultiplyColor(color);
}
bool isSpace() const { return true; }
}; };
inline Space* View::castToSpace() { return isSpace() ? static_cast<Space*>(this) : nullptr; } inline Space* View::castToSpace() { return isSpace() ? static_cast<Space*>(this) : nullptr; }
} } // namespace specter

View File

@ -2,119 +2,104 @@
#include "specter/View.hpp" #include "specter/View.hpp"
namespace specter namespace specter {
{
struct ISplitSpaceController; struct ISplitSpaceController;
class SplitView : public View class SplitView : public View {
{ friend class RootView;
friend class RootView; friend class Space;
friend class Space;
public: public:
class Resources class Resources {
{ friend class ViewResources;
friend class ViewResources; friend class SplitView;
friend class SplitView; boo::ObjToken<boo::ITextureS> m_shadingTex;
boo::ObjToken<boo::ITextureS> m_shadingTex;
void init(boo::IGraphicsDataFactory::Context& ctx, const IThemeData& theme); void init(boo::IGraphicsDataFactory::Context& ctx, const IThemeData& theme);
void destroy() { m_shadingTex.reset(); } void destroy() { m_shadingTex.reset(); }
}; };
enum class ArrowDir enum class ArrowDir { Up, Down, Left, Right };
{
Up, enum class Axis { Horizontal, Vertical };
Down,
Left,
Right
};
enum class Axis
{
Horizontal,
Vertical
};
private: private:
ISplitSpaceController* m_controller; ISplitSpaceController* m_controller;
Axis m_axis; Axis m_axis;
float m_slide = 0.5; float m_slide = 0.5;
void _setSplit(float slide); void _setSplit(float slide);
bool m_dragging = false; bool m_dragging = false;
ViewChild<View*> m_views[2]; ViewChild<View*> m_views[2];
ViewBlock m_splitBlock; ViewBlock m_splitBlock;
hecl::UniformBufferPool<ViewBlock>::Token m_splitBlockBuf; hecl::UniformBufferPool<ViewBlock>::Token m_splitBlockBuf;
TexShaderVert m_splitVerts[4]; TexShaderVert m_splitVerts[4];
int m_clearanceA, m_clearanceB; int m_clearanceA, m_clearanceB;
void setHorizontalVerts(int width) void setHorizontalVerts(int width) {
{ m_splitVerts[0].m_pos.assign(0, 2, 0);
m_splitVerts[0].m_pos.assign(0, 2, 0); m_splitVerts[0].m_uv.assign(0, 0);
m_splitVerts[0].m_uv.assign(0, 0); m_splitVerts[1].m_pos.assign(0, -1, 0);
m_splitVerts[1].m_pos.assign(0, -1, 0); m_splitVerts[1].m_uv.assign(1, 0);
m_splitVerts[1].m_uv.assign(1, 0); m_splitVerts[2].m_pos.assign(width, 2, 0);
m_splitVerts[2].m_pos.assign(width, 2, 0); m_splitVerts[2].m_uv.assign(0, 0);
m_splitVerts[2].m_uv.assign(0, 0); m_splitVerts[3].m_pos.assign(width, -1, 0);
m_splitVerts[3].m_pos.assign(width, -1, 0); m_splitVerts[3].m_uv.assign(1, 0);
m_splitVerts[3].m_uv.assign(1, 0); }
}
void setVerticalVerts(int height) void setVerticalVerts(int height) {
{ m_splitVerts[0].m_pos.assign(-1, height, 0);
m_splitVerts[0].m_pos.assign(-1, height, 0); m_splitVerts[0].m_uv.assign(0, 0);
m_splitVerts[0].m_uv.assign(0, 0); m_splitVerts[1].m_pos.assign(-1, 0, 0);
m_splitVerts[1].m_pos.assign(-1, 0, 0); m_splitVerts[1].m_uv.assign(0, 0);
m_splitVerts[1].m_uv.assign(0, 0); m_splitVerts[2].m_pos.assign(2, height, 0);
m_splitVerts[2].m_pos.assign(2, height, 0); m_splitVerts[2].m_uv.assign(1, 0);
m_splitVerts[2].m_uv.assign(1, 0); m_splitVerts[3].m_pos.assign(2, 0, 0);
m_splitVerts[3].m_pos.assign(2, 0, 0); m_splitVerts[3].m_uv.assign(1, 0);
m_splitVerts[3].m_uv.assign(1, 0); }
}
VertexBufferBindingTex m_splitVertsBinding; VertexBufferBindingTex m_splitVertsBinding;
public: public:
SplitView(ViewResources& res, View& parentView, ISplitSpaceController* controller, SplitView(ViewResources& res, View& parentView, ISplitSpaceController* controller, Axis axis, float split,
Axis axis, float split, int clearanceA=-1, int clearanceB=-1); int clearanceA = -1, int clearanceB = -1);
View* setContentView(int slot, View* view); View* setContentView(int slot, View* view);
void setSplit(float split); void setSplit(float split);
void setAxis(Axis axis); void setAxis(Axis axis);
Axis axis() const {return m_axis;} Axis axis() const { return m_axis; }
float split() const {return m_slide;} float split() const { return m_slide; }
bool testSplitHover(const boo::SWindowCoord& coord); bool testSplitHover(const boo::SWindowCoord& coord);
bool testJoinArrowHover(const boo::SWindowCoord& coord, int& origSlotOut, bool testJoinArrowHover(const boo::SWindowCoord& coord, int& origSlotOut, SplitView*& splitOut, int& slotOut,
SplitView*& splitOut, int& slotOut, boo::SWindowRect& rectOut, ArrowDir& dirOut, int forceSlot = -1);
boo::SWindowRect& rectOut, ArrowDir& dirOut, int forceSlot=-1); void getJoinArrowHover(int slot, boo::SWindowRect& rectOut, ArrowDir& dirOut);
void getJoinArrowHover(int slot, boo::SWindowRect& rectOut, ArrowDir& dirOut); bool testSplitLineHover(const boo::SWindowCoord& coord, int& slotOut, boo::SWindowRect& rectOut, float& splitOut,
bool testSplitLineHover(const boo::SWindowCoord& coord, int& slotOut, boo::SWindowRect& rectOut, float& splitOut, Axis& axisOut); Axis& axisOut);
void getSplitLineHover(int slot, boo::SWindowRect& rectOut, Axis& axisOut); void getSplitLineHover(int slot, boo::SWindowRect& rectOut, Axis& axisOut);
void startDragSplit(const boo::SWindowCoord& coord); void startDragSplit(const boo::SWindowCoord& coord);
void endDragSplit(); void endDragSplit();
void moveDragSplit(const boo::SWindowCoord& coord); void moveDragSplit(const boo::SWindowCoord& coord);
void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey); void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey); void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseMove(const boo::SWindowCoord&); void mouseMove(const boo::SWindowCoord&);
void mouseEnter(const boo::SWindowCoord&); void mouseEnter(const boo::SWindowCoord&);
void mouseLeave(const boo::SWindowCoord&); void mouseLeave(const boo::SWindowCoord&);
void resized(const boo::SWindowRect& rootView, const boo::SWindowRect& sub); void resized(const boo::SWindowRect& rootView, const boo::SWindowRect& sub);
void draw(boo::IGraphicsCommandQueue* gfxQ); void draw(boo::IGraphicsCommandQueue* gfxQ);
void setMultiplyColor(const zeus::CColor& color) void setMultiplyColor(const zeus::CColor& color) {
{ View::setMultiplyColor(color);
View::setMultiplyColor(color); m_splitBlock.m_color = color;
m_splitBlock.m_color = color; m_splitBlockBuf.access().finalAssign(m_splitBlock);
m_splitBlockBuf.access().finalAssign(m_splitBlock);
if (m_views[0].m_view) if (m_views[0].m_view)
m_views[0].m_view->setMultiplyColor(color); m_views[0].m_view->setMultiplyColor(color);
if (m_views[1].m_view) if (m_views[1].m_view)
m_views[1].m_view->setMultiplyColor(color); m_views[1].m_view->setMultiplyColor(color);
} }
bool isSplitView() const { return true; } bool isSplitView() const { return true; }
}; };
inline SplitView* View::castToSplitView() { return isSplitView() ? static_cast<SplitView*>(this) : nullptr; } inline SplitView* View::castToSplitView() { return isSplitView() ? static_cast<SplitView*>(this) : nullptr; }
} } // namespace specter

View File

@ -5,139 +5,128 @@
#include "TextView.hpp" #include "TextView.hpp"
#include <array> #include <array>
namespace specter namespace specter {
{
#define SPECTER_TABLE_MAX_ROWS 128ul #define SPECTER_TABLE_MAX_ROWS 128ul
enum class SortDirection enum class SortDirection { None, Ascending, Descending };
{
None, struct ITableDataBinding {
Ascending, virtual size_t columnCount() const = 0;
Descending virtual size_t rowCount() const = 0;
virtual std::string_view header(size_t cIdx) const { return {}; }
virtual std::string_view cell(size_t cIdx, size_t rIdx) const { return {}; }
}; };
struct ITableDataBinding struct ITableStateBinding {
{ virtual float getColumnSplit(size_t cIdx) const { return -1.0; }
virtual size_t columnCount() const=0; virtual bool columnSplitResizeAllowed() const { return false; }
virtual size_t rowCount() const=0; virtual void setColumnSplit(size_t cIdx, float split) {}
virtual std::string_view header(size_t cIdx) const { return {}; } virtual SortDirection getSort(size_t& cIdx) const {
virtual std::string_view cell(size_t cIdx, size_t rIdx) const { return {}; } cIdx = 0;
return SortDirection::None;
}
virtual void setSort(size_t cIdx, SortDirection dir) {}
virtual void setSelectedRow(size_t rIdx) {}
virtual void rowActivated(size_t rIdx) {}
}; };
struct ITableStateBinding class Table : public View {
{ ITableDataBinding* m_data;
virtual float getColumnSplit(size_t cIdx) const {return -1.0;} ITableStateBinding* m_state;
virtual bool columnSplitResizeAllowed() const {return false;}
virtual void setColumnSplit(size_t cIdx, float split) {}
virtual SortDirection getSort(size_t& cIdx) const {cIdx = 0; return SortDirection::None;}
virtual void setSort(size_t cIdx, SortDirection dir) {}
virtual void setSelectedRow(size_t rIdx) {}
virtual void rowActivated(size_t rIdx) {}
};
class Table : public View size_t m_maxColumns;
{ size_t m_rows = 0;
ITableDataBinding* m_data; size_t m_columns = 0;
ITableStateBinding* m_state; size_t m_selectedRow = -1;
size_t m_deferredActivation = -1;
size_t m_clickFrames = 15;
size_t m_maxColumns; struct CellView : public View {
size_t m_rows = 0; Table& m_t;
size_t m_columns = 0; std::unique_ptr<TextView> m_text;
size_t m_selectedRow = -1; size_t m_c, m_r;
size_t m_deferredActivation = -1; boo::SWindowRect m_scissorRect;
size_t m_clickFrames = 15; uint64_t m_textHash = 0;
CellView(Table& t, ViewResources& res);
struct CellView : public View bool m_selected = false;
{ void select();
Table& m_t; void deselect();
std::unique_ptr<TextView> m_text; void reset();
size_t m_c, m_r; bool reset(size_t c);
boo::SWindowRect m_scissorRect; bool reset(size_t c, size_t r);
uint64_t m_textHash = 0;
CellView(Table& t, ViewResources& res);
bool m_selected = false;
void select();
void deselect();
void reset();
bool reset(size_t c);
bool reset(size_t c, size_t r);
void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseEnter(const boo::SWindowCoord&);
void mouseLeave(const boo::SWindowCoord&);
void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub,
const boo::SWindowRect& scissor);
void draw(boo::IGraphicsCommandQueue* gfxQ);
};
std::vector<ViewChild<std::unique_ptr<CellView>>> m_headerViews;
using ColumnPool = std::array<std::array<ViewChild<std::unique_ptr<CellView>>, SPECTER_TABLE_MAX_ROWS>, 2>;
std::vector<ColumnPool> m_cellPools;
size_t m_ensuredRows = 0;
std::vector<ColumnPool>& ensureCellPools(size_t rows, size_t cols, ViewResources& res);
size_t m_activePool = -1;
bool m_header = false;
std::vector<boo::SWindowRect> m_hCellRects;
size_t m_hDraggingIdx = 0;
std::unique_ptr<SolidShaderVert[]> m_hVerts;
VertexBufferBindingSolid m_vertsBinding;
void _setHeaderVerts(const boo::SWindowRect& rect);
std::vector<boo::SWindowRect> getCellRects(const boo::SWindowRect& tableRect) const;
ViewChild<std::unique_ptr<ScrollView>> m_scroll;
struct RowsView : public View
{
Table& m_t;
std::unique_ptr<SolidShaderVert[]> m_verts;
VertexBufferBindingSolid m_vertsBinding;
size_t m_visibleStart = 0;
size_t m_visibleRows = 0;
boo::SWindowRect m_scissorRect;
void _setRowVerts(const boo::SWindowRect& rowsRect, const boo::SWindowRect& scissor);
RowsView(Table& t, ViewResources& res);
int nominalHeight() const;
int nominalWidth() const {return m_t.m_scroll.m_view->nominalWidth();}
void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseMove(const boo::SWindowCoord&);
void mouseLeave(const boo::SWindowCoord&);
void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub,
const boo::SWindowRect& scissor);
void draw(boo::IGraphicsCommandQueue* gfxQ);
} m_rowsView;
bool m_headerNeedsUpdate = false;
bool m_inSelectRow = false;
void _updateData();
public:
Table(ViewResources& res, View& parentView, ITableDataBinding* data,
ITableStateBinding* state=nullptr, size_t maxColumns=8);
void cycleSortColumn(size_t c);
void selectRow(size_t r);
void setMultiplyColor(const zeus::CColor& color);
void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey); void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey); void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseMove(const boo::SWindowCoord&);
void mouseEnter(const boo::SWindowCoord&); void mouseEnter(const boo::SWindowCoord&);
void mouseLeave(const boo::SWindowCoord&); void mouseLeave(const boo::SWindowCoord&);
void scroll(const boo::SWindowCoord&, const boo::SScrollDelta&); void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub, const boo::SWindowRect& scissor);
void think();
void updateData();
void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub);
void draw(boo::IGraphicsCommandQueue* gfxQ); void draw(boo::IGraphicsCommandQueue* gfxQ);
};
std::vector<ViewChild<std::unique_ptr<CellView>>> m_headerViews;
using ColumnPool = std::array<std::array<ViewChild<std::unique_ptr<CellView>>, SPECTER_TABLE_MAX_ROWS>, 2>;
std::vector<ColumnPool> m_cellPools;
size_t m_ensuredRows = 0;
std::vector<ColumnPool>& ensureCellPools(size_t rows, size_t cols, ViewResources& res);
size_t m_activePool = -1;
bool m_header = false;
std::vector<boo::SWindowRect> m_hCellRects;
size_t m_hDraggingIdx = 0;
std::unique_ptr<SolidShaderVert[]> m_hVerts;
VertexBufferBindingSolid m_vertsBinding;
void _setHeaderVerts(const boo::SWindowRect& rect);
std::vector<boo::SWindowRect> getCellRects(const boo::SWindowRect& tableRect) const;
ViewChild<std::unique_ptr<ScrollView>> m_scroll;
struct RowsView : public View {
Table& m_t;
std::unique_ptr<SolidShaderVert[]> m_verts;
VertexBufferBindingSolid m_vertsBinding;
size_t m_visibleStart = 0;
size_t m_visibleRows = 0;
boo::SWindowRect m_scissorRect;
void _setRowVerts(const boo::SWindowRect& rowsRect, const boo::SWindowRect& scissor);
RowsView(Table& t, ViewResources& res);
int nominalHeight() const;
int nominalWidth() const { return m_t.m_scroll.m_view->nominalWidth(); }
void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseMove(const boo::SWindowCoord&);
void mouseLeave(const boo::SWindowCoord&);
void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub, const boo::SWindowRect& scissor);
void draw(boo::IGraphicsCommandQueue* gfxQ);
} m_rowsView;
bool m_headerNeedsUpdate = false;
bool m_inSelectRow = false;
void _updateData();
public:
Table(ViewResources& res, View& parentView, ITableDataBinding* data, ITableStateBinding* state = nullptr,
size_t maxColumns = 8);
void cycleSortColumn(size_t c);
void selectRow(size_t r);
void setMultiplyColor(const zeus::CColor& color);
void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseMove(const boo::SWindowCoord&);
void mouseEnter(const boo::SWindowCoord&);
void mouseLeave(const boo::SWindowCoord&);
void scroll(const boo::SWindowCoord&, const boo::SScrollDelta&);
void think();
void updateData();
void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub);
void draw(boo::IGraphicsCommandQueue* gfxQ);
}; };
} } // namespace specter

View File

@ -4,135 +4,123 @@
#include "TextView.hpp" #include "TextView.hpp"
#include <boo/IWindow.hpp> #include <boo/IWindow.hpp>
namespace specter namespace specter {
{
class TextField : public ITextInputView class TextField : public ITextInputView {
{ bool m_hasTextSet = false;
bool m_hasTextSet = false; bool m_hasMarkSet = false;
bool m_hasMarkSet = false; std::string m_textStr;
std::string m_textStr; std::string m_deferredTextStr;
std::string m_deferredTextStr; std::string m_deferredMarkStr;
std::string m_deferredMarkStr; std::unique_ptr<TextView> m_text;
std::unique_ptr<TextView> m_text; std::unique_ptr<TextView> m_errText;
std::unique_ptr<TextView> m_errText;
SolidShaderVert m_verts[41]; SolidShaderVert m_verts[41];
VertexBufferBindingSolid m_vertsBinding; VertexBufferBindingSolid m_vertsBinding;
int m_nomWidth = 0; int m_nomWidth = 0;
int m_nomHeight = 0; int m_nomHeight = 0;
bool m_hasSelectionClear = false; bool m_hasSelectionClear = false;
bool m_hasSelectionSet = false; bool m_hasSelectionSet = false;
bool m_hasCursorSet = false; bool m_hasCursorSet = false;
size_t m_selectionStart = 0; size_t m_selectionStart = 0;
size_t m_deferredSelectionStart = 0; size_t m_deferredSelectionStart = 0;
size_t m_selectionCount = 0; size_t m_selectionCount = 0;
size_t m_deferredSelectionCount = 0; size_t m_deferredSelectionCount = 0;
size_t m_markReplStart = 0; size_t m_markReplStart = 0;
size_t m_deferredMarkReplStart = 0; size_t m_deferredMarkReplStart = 0;
size_t m_markReplCount = 0; size_t m_markReplCount = 0;
size_t m_deferredMarkReplCount = 0; size_t m_deferredMarkReplCount = 0;
size_t m_markSelStart = 0; size_t m_markSelStart = 0;
size_t m_deferredMarkSelStart = 0; size_t m_deferredMarkSelStart = 0;
size_t m_markSelCount = 0; size_t m_markSelCount = 0;
size_t m_deferredMarkSelCount = 0; size_t m_deferredMarkSelCount = 0;
size_t m_cursorPos = 0; size_t m_cursorPos = 0;
size_t m_deferredCursorPos = SIZE_MAX; size_t m_deferredCursorPos = SIZE_MAX;
size_t m_cursorFrames = 0; size_t m_cursorFrames = 0;
size_t m_clickFrames = 15; size_t m_clickFrames = 15;
size_t m_clickFrames2 = 15; size_t m_clickFrames2 = 15;
size_t m_errorFrames = 360; size_t m_errorFrames = 360;
size_t m_dragStart = 0; size_t m_dragStart = 0;
size_t m_dragging = 0; size_t m_dragging = 0;
bool m_active = false; bool m_active = false;
bool m_error = false; bool m_error = false;
enum class BGState enum class BGState { Inactive, Hover, Disabled } m_bgState = BGState::Inactive;
{ void setInactive();
Inactive, void setHover();
Hover, void setDisabled();
Disabled void refreshBg();
} m_bgState = BGState::Inactive;
void setInactive();
void setHover();
void setDisabled();
void refreshBg();
public: public:
TextField(ViewResources& res, View& parentView, IStringBinding* strBind); TextField(ViewResources& res, View& parentView, IStringBinding* strBind);
std::string_view getText() const {return m_textStr;} std::string_view getText() const { return m_textStr; }
void setText(std::string_view str); void setText(std::string_view str);
void clipboardCopy(); void clipboardCopy();
void clipboardCut(); void clipboardCut();
void clipboardPaste(); void clipboardPaste();
void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey); void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey); void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseMove(const boo::SWindowCoord&); void mouseMove(const boo::SWindowCoord&);
void mouseEnter(const boo::SWindowCoord&); void mouseEnter(const boo::SWindowCoord&);
void mouseLeave(const boo::SWindowCoord&); void mouseLeave(const boo::SWindowCoord&);
void specialKeyDown(boo::ESpecialKey, boo::EModifierKey, bool); void specialKeyDown(boo::ESpecialKey, boo::EModifierKey, bool);
bool hasMarkedText() const; bool hasMarkedText() const;
std::pair<int,int> markedRange() const; std::pair<int, int> markedRange() const;
std::pair<int,int> selectedRange() const; std::pair<int, int> selectedRange() const;
void setMarkedText(std::string_view str, void setMarkedText(std::string_view str, const std::pair<int, int>& selectedRange,
const std::pair<int,int>& selectedRange, const std::pair<int, int>& replacementRange);
const std::pair<int,int>& replacementRange); void unmarkText();
void unmarkText();
std::string substringForRange(const std::pair<int,int>& range, std::string substringForRange(const std::pair<int, int>& range, std::pair<int, int>& actualRange) const;
std::pair<int,int>& actualRange) const; void insertText(std::string_view str, const std::pair<int, int>& range);
void insertText(std::string_view str, const std::pair<int,int>& range); int characterIndexAtPoint(const boo::SWindowCoord& point) const;
int characterIndexAtPoint(const boo::SWindowCoord& point) const; boo::SWindowRect rectForCharacterRange(const std::pair<int, int>& range, std::pair<int, int>& actualRange) const;
boo::SWindowRect rectForCharacterRange(const std::pair<int,int>& range,
std::pair<int,int>& actualRange) const;
void think(); void think();
void resized(const boo::SWindowRect& rootView, const boo::SWindowRect& sub); void resized(const boo::SWindowRect& rootView, const boo::SWindowRect& sub);
void draw(boo::IGraphicsCommandQueue* gfxQ); void draw(boo::IGraphicsCommandQueue* gfxQ);
int nominalWidth() const {return m_nomWidth;} int nominalWidth() const { return m_nomWidth; }
int nominalHeight() const {return m_nomHeight;} int nominalHeight() const { return m_nomHeight; }
void setActive(bool active); void setActive(bool active);
void setCursorPos(size_t pos); void setCursorPos(size_t pos);
void setErrorState(std::string_view message); void setErrorState(std::string_view message);
void clearErrorState(); void clearErrorState();
void setSelectionRange(size_t start, size_t count); void setSelectionRange(size_t start, size_t count);
void clearSelectionRange(); void clearSelectionRange();
void setMultiplyColor(const zeus::CColor& color) void setMultiplyColor(const zeus::CColor& color) {
{ View::setMultiplyColor(color);
View::setMultiplyColor(color); m_viewVertBlock.m_color = color;
m_viewVertBlock.m_color = color; if (m_viewVertBlockBuf)
if (m_viewVertBlockBuf) m_viewVertBlockBuf.access().finalAssign(m_viewVertBlock);
m_viewVertBlockBuf.access().finalAssign(m_viewVertBlock); m_text->setMultiplyColor(color);
m_text->setMultiplyColor(color); if (m_errText)
if (m_errText) m_errText->setMultiplyColor(color);
m_errText->setMultiplyColor(color); }
}
private: private:
void _setCursorPos(); void _setCursorPos();
void _reallySetCursorPos(size_t pos); void _reallySetCursorPos(size_t pos);
void _setSelectionRange(); void _setSelectionRange();
void _reallySetSelectionRange(size_t start, size_t len); void _reallySetSelectionRange(size_t start, size_t len);
void _reallySetMarkRange(size_t start, size_t len); void _reallySetMarkRange(size_t start, size_t len);
void _clearSelectionRange(); void _clearSelectionRange();
void _setText(); void _setText();
void _setMarkedText(); void _setMarkedText();
}; };
} } // namespace specter

View File

@ -5,128 +5,112 @@
#include "FontCache.hpp" #include "FontCache.hpp"
namespace specter namespace specter {
{
class ViewResources; class ViewResources;
class TextView : public View class TextView : public View {
{
public: public:
enum class Alignment enum class Alignment { Left, Center, Right };
{ struct RenderGlyph {
Left, zeus::CVector3f m_pos[4];
Center, zeus::CMatrix4f m_mv;
Right zeus::CVector3f m_uv[4];
}; zeus::CColor m_color;
struct RenderGlyph // char _dummy[48];
{
zeus::CVector3f m_pos[4];
zeus::CMatrix4f m_mv;
zeus::CVector3f m_uv[4];
zeus::CColor m_color;
//char _dummy[48];
RenderGlyph& operator=(const RenderGlyph& other) RenderGlyph& operator=(const RenderGlyph& other) {
{ m_pos[0] = other.m_pos[0];
m_pos[0] = other.m_pos[0]; m_pos[1] = other.m_pos[1];
m_pos[1] = other.m_pos[1]; m_pos[2] = other.m_pos[2];
m_pos[2] = other.m_pos[2]; m_pos[3] = other.m_pos[3];
m_pos[3] = other.m_pos[3]; m_mv = other.m_mv;
m_mv = other.m_mv; m_uv[0] = other.m_uv[0];
m_uv[0] = other.m_uv[0]; m_uv[1] = other.m_uv[1];
m_uv[1] = other.m_uv[1]; m_uv[2] = other.m_uv[2];
m_uv[2] = other.m_uv[2]; m_uv[3] = other.m_uv[3];
m_uv[3] = other.m_uv[3]; m_color = other.m_color;
m_color = other.m_color; return *this;
return *this; }
}
RenderGlyph(int& adv, const FontAtlas::Glyph& glyph, const zeus::CColor& defaultColor); RenderGlyph(int& adv, const FontAtlas::Glyph& glyph, const zeus::CColor& defaultColor);
}; };
struct RenderGlyphInfo struct RenderGlyphInfo {
{ uint32_t m_char;
uint32_t m_char; std::pair<int, int> m_dims;
std::pair<int,int> m_dims; int m_adv;
int m_adv; bool m_space = false;
bool m_space = false;
RenderGlyphInfo(uint32_t ch, int width, int height, int adv) RenderGlyphInfo(uint32_t ch, int width, int height, int adv)
: m_char(ch), m_dims(width, height), m_adv(adv), m_space(iswspace(ch) != 0) {} : m_char(ch), m_dims(width, height), m_adv(adv), m_space(iswspace(ch) != 0) {}
}; };
private: private:
size_t m_capacity; size_t m_capacity;
size_t m_curSize = 0; size_t m_curSize = 0;
hecl::VertexBufferPool<RenderGlyph>::Token m_glyphBuf; hecl::VertexBufferPool<RenderGlyph>::Token m_glyphBuf;
boo::ObjToken<boo::IShaderDataBinding> m_shaderBinding; boo::ObjToken<boo::IShaderDataBinding> m_shaderBinding;
const FontAtlas& m_fontAtlas; const FontAtlas& m_fontAtlas;
Alignment m_align; Alignment m_align;
int m_width = 0; int m_width = 0;
friend class MultiLineTextView;
static int DoKern(FT_Pos val, const FontAtlas& atlas);
void _commitResources(size_t capacity);
public:
class Resources {
friend class ViewResources;
friend class TextView;
friend class MultiLineTextView; friend class MultiLineTextView;
static int DoKern(FT_Pos val, const FontAtlas& atlas);
void _commitResources(size_t capacity); hecl::VertexBufferPool<RenderGlyph> m_glyphPool;
public: void updateBuffers() { m_glyphPool.updateBuffers(); }
class Resources
{
friend class ViewResources;
friend class TextView;
friend class MultiLineTextView;
hecl::VertexBufferPool<RenderGlyph> m_glyphPool; FontCache* m_fcache = nullptr;
boo::ObjToken<boo::IShaderPipeline> m_regular;
boo::ObjToken<boo::IShaderPipeline> m_subpixel;
void updateBuffers() void init(boo::IGraphicsDataFactory::Context& ctx, FontCache* fcache);
{
m_glyphPool.updateBuffers();
}
FontCache* m_fcache = nullptr; void destroy() {
boo::ObjToken<boo::IShaderPipeline> m_regular; m_glyphPool.doDestroy();
boo::ObjToken<boo::IShaderPipeline> m_subpixel; m_regular.reset();
m_subpixel.reset();
}
};
void init(boo::IGraphicsDataFactory::Context& ctx, FontCache* fcache); TextView(ViewResources& res, View& parentView, const FontAtlas& font, Alignment align = Alignment::Left,
size_t capacity = 256);
TextView(ViewResources& res, View& parentView, FontTag font, Alignment align = Alignment::Left,
size_t capacity = 256);
void destroy() std::vector<RenderGlyph>& accessGlyphs() { return m_glyphs; }
{ const std::vector<RenderGlyph>& accessGlyphs() const { return m_glyphs; }
m_glyphPool.doDestroy();
m_regular.reset();
m_subpixel.reset();
}
};
TextView(ViewResources& res, View& parentView, const FontAtlas& font, Alignment align=Alignment::Left, size_t capacity=256); void typesetGlyphs(std::string_view str, const zeus::CColor& defaultColor = zeus::CColor::skWhite);
TextView(ViewResources& res, View& parentView, FontTag font, Alignment align=Alignment::Left, size_t capacity=256); void typesetGlyphs(std::wstring_view str, const zeus::CColor& defaultColor = zeus::CColor::skWhite);
void invalidateGlyphs();
std::vector<RenderGlyph>& accessGlyphs() {return m_glyphs;} void colorGlyphs(const zeus::CColor& newColor);
const std::vector<RenderGlyph>& accessGlyphs() const {return m_glyphs;} void colorGlyphsTypeOn(const zeus::CColor& newColor, float startInterval = 0.2, float fadeTime = 0.5);
void think();
void typesetGlyphs(std::string_view str, void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub);
const zeus::CColor& defaultColor=zeus::CColor::skWhite); void draw(boo::IGraphicsCommandQueue* gfxQ);
void typesetGlyphs(std::wstring_view str,
const zeus::CColor& defaultColor=zeus::CColor::skWhite);
void invalidateGlyphs();
void colorGlyphs(const zeus::CColor& newColor); int nominalWidth() const { return m_width; }
void colorGlyphsTypeOn(const zeus::CColor& newColor, float startInterval=0.2, float fadeTime=0.5); int nominalHeight() const { return m_fontAtlas.FT_LineHeight() >> 6; }
void think();
void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub); std::pair<int, int> queryGlyphDimensions(size_t pos) const;
void draw(boo::IGraphicsCommandQueue* gfxQ); size_t reverseSelectGlyph(int x) const;
int queryReverseAdvance(size_t idx) const;
int nominalWidth() const {return m_width;} std::pair<size_t, size_t> queryWholeWordRange(size_t idx) const;
int nominalHeight() const {return m_fontAtlas.FT_LineHeight() >> 6;}
std::pair<int,int> queryGlyphDimensions(size_t pos) const;
size_t reverseSelectGlyph(int x) const;
int queryReverseAdvance(size_t idx) const;
std::pair<size_t,size_t> queryWholeWordRange(size_t idx) const;
private: private:
std::vector<RenderGlyph> m_glyphs; std::vector<RenderGlyph> m_glyphs;
std::vector<RenderGlyphInfo> m_glyphInfo; std::vector<RenderGlyphInfo> m_glyphInfo;
}; };
} } // namespace specter

View File

@ -2,75 +2,62 @@
#include "specter/View.hpp" #include "specter/View.hpp"
namespace specter namespace specter {
{
#define SPECTER_TOOLBAR_GAUGE 28 #define SPECTER_TOOLBAR_GAUGE 28
class Toolbar : public View class Toolbar : public View {
{
public: public:
class Resources class Resources {
{ friend class ViewResources;
friend class ViewResources; friend class Toolbar;
friend class Toolbar; boo::ObjToken<boo::ITextureS> m_shadingTex;
boo::ObjToken<boo::ITextureS> m_shadingTex;
void init(boo::IGraphicsDataFactory::Context& ctx, const IThemeData& theme); void init(boo::IGraphicsDataFactory::Context& ctx, const IThemeData& theme);
void destroy() { m_shadingTex.reset(); } void destroy() { m_shadingTex.reset(); }
}; };
enum class Position { None, Bottom, Top };
enum class Position
{
None,
Bottom,
Top
};
private: private:
unsigned m_units; unsigned m_units;
std::vector<std::vector<ViewChild<View*>>> m_children; std::vector<std::vector<ViewChild<View*>>> m_children;
ViewBlock m_tbBlock; ViewBlock m_tbBlock;
hecl::UniformBufferPool<ViewBlock>::Token m_tbBlockBuf; hecl::UniformBufferPool<ViewBlock>::Token m_tbBlockBuf;
TexShaderVert m_tbVerts[10]; TexShaderVert m_tbVerts[10];
int m_nomGauge = 25; int m_nomGauge = 25;
int m_padding = 10; int m_padding = 10;
void setHorizontalVerts(int width); void setHorizontalVerts(int width);
void setVerticalVerts(int height); void setVerticalVerts(int height);
VertexBufferBindingTex m_vertsBinding; VertexBufferBindingTex m_vertsBinding;
public: public:
Toolbar(ViewResources& res, View& parentView, Position toolbarPos, unsigned units); Toolbar(ViewResources& res, View& parentView, Position toolbarPos, unsigned units);
void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey); void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey); void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseMove(const boo::SWindowCoord&); void mouseMove(const boo::SWindowCoord&);
void mouseEnter(const boo::SWindowCoord&); void mouseEnter(const boo::SWindowCoord&);
void mouseLeave(const boo::SWindowCoord&coord); void mouseLeave(const boo::SWindowCoord& coord);
void resized(const boo::SWindowRect& rootView, const boo::SWindowRect& sub); void resized(const boo::SWindowRect& rootView, const boo::SWindowRect& sub);
void draw(boo::IGraphicsCommandQueue* gfxQ); void draw(boo::IGraphicsCommandQueue* gfxQ);
int nominalHeight() const int nominalHeight() const { return m_nomGauge; }
{
return m_nomGauge;
}
void clear() void clear() {
{ for (std::vector<ViewChild<View*>>& u : m_children)
for (std::vector<ViewChild<View*>>& u : m_children) u.clear();
u.clear(); }
} void push_back(View* v, unsigned unit);
void push_back(View* v, unsigned unit);
void setMultiplyColor(const zeus::CColor& color) void setMultiplyColor(const zeus::CColor& color) {
{ View::setMultiplyColor(color);
View::setMultiplyColor(color); for (std::vector<ViewChild<View*>>& u : m_children)
for (std::vector<ViewChild<View*>>& u : m_children) for (ViewChild<View*>& c : u)
for (ViewChild<View*>& c : u) if (c.m_view)
if (c.m_view) c.m_view->setMultiplyColor(color);
c.m_view->setMultiplyColor(color); }
}
}; };
} } // namespace specter

View File

@ -3,37 +3,34 @@
#include "specter/View.hpp" #include "specter/View.hpp"
#include "specter/MultiLineTextView.hpp" #include "specter/MultiLineTextView.hpp"
namespace specter namespace specter {
{
class Tooltip : public View class Tooltip : public View {
{ ViewBlock m_ttBlock;
ViewBlock m_ttBlock; hecl::UniformBufferPool<ViewBlock>::Token m_ttBlockBuf;
hecl::UniformBufferPool<ViewBlock>::Token m_ttBlockBuf; SolidShaderVert m_ttVerts[16];
SolidShaderVert m_ttVerts[16]; int m_nomWidth = 25;
int m_nomWidth = 25; int m_nomHeight = 25;
int m_nomHeight = 25;
void setVerts(int width, int height, float pf); void setVerts(int width, int height, float pf);
VertexBufferBindingSolid m_vertsBinding; VertexBufferBindingSolid m_vertsBinding;
std::string m_titleStr; std::string m_titleStr;
std::unique_ptr<TextView> m_title; std::unique_ptr<TextView> m_title;
std::string m_messageStr; std::string m_messageStr;
std::unique_ptr<MultiLineTextView> m_message; std::unique_ptr<MultiLineTextView> m_message;
std::unique_ptr<TextView> m_cornersOutline[4];
std::unique_ptr<TextView> m_cornersFilled[4];
std::unique_ptr<TextView> m_cornersOutline[4];
std::unique_ptr<TextView> m_cornersFilled[4];
public: public:
Tooltip(ViewResources& res, View& parentView, std::string_view title, Tooltip(ViewResources& res, View& parentView, std::string_view title, std::string_view message);
std::string_view message); void resized(const boo::SWindowRect& rootView, const boo::SWindowRect& sub);
void resized(const boo::SWindowRect& rootView, const boo::SWindowRect& sub); void draw(boo::IGraphicsCommandQueue* gfxQ);
void draw(boo::IGraphicsCommandQueue* gfxQ);
int nominalWidth() const {return m_nomWidth;} int nominalWidth() const { return m_nomWidth; }
int nominalHeight() const {return m_nomHeight;} int nominalHeight() const { return m_nomHeight; }
}; };
} } // namespace specter

View File

@ -3,32 +3,29 @@
#include <string> #include <string>
#include <athena/DNAYaml.hpp> #include <athena/DNAYaml.hpp>
namespace specter namespace specter {
{
class Locale {
std::string_view m_name;
std::string_view m_fullName;
std::unique_ptr<athena::io::YAMLNode> m_rootNode;
const athena::io::YAMLNode* m_langNode;
class Locale
{
std::string_view m_name;
std::string_view m_fullName;
std::unique_ptr<athena::io::YAMLNode> m_rootNode;
const athena::io::YAMLNode* m_langNode;
public: public:
Locale(std::string_view name, std::string_view fullName, Locale(std::string_view name, std::string_view fullName, const unsigned char* yamlSource, size_t yamlLength);
const unsigned char* yamlSource, size_t yamlLength); std::string_view name() const { return m_name; }
std::string_view name() const {return m_name;} std::string_view fullName() const { return m_fullName; }
std::string_view fullName() const {return m_fullName;} const athena::io::YAMLNode* rootNode() const { return m_langNode; }
const athena::io::YAMLNode* rootNode() const {return m_langNode;}
}; };
class Translator class Translator {
{ const Locale* m_targetLocale;
const Locale* m_targetLocale;
public: public:
Translator(const Locale* targetLocale) {setLocale(targetLocale);} Translator(const Locale* targetLocale) { setLocale(targetLocale); }
void setLocale(const Locale* targetLocale); void setLocale(const Locale* targetLocale);
std::string_view translate(std::string_view key) const; std::string_view translate(std::string_view key) const;
std::string_view translateOr(std::string_view key, std::string_view vor) const; std::string_view translateOr(std::string_view key, std::string_view vor) const;
}; };
} } // namespace specter

View File

@ -10,393 +10,334 @@
#include "hecl/UniformBufferPool.hpp" #include "hecl/UniformBufferPool.hpp"
#include "hecl/VertexBufferPool.hpp" #include "hecl/VertexBufferPool.hpp"
namespace specter namespace specter {
{
class IThemeData; class IThemeData;
class ViewResources; class ViewResources;
class RootView; class RootView;
extern zeus::CMatrix4f g_PlatformMatrix; extern zeus::CMatrix4f g_PlatformMatrix;
class RectangleConstraint class RectangleConstraint {
{
public: public:
enum class Test enum class Test { Fixed, Minimum, Maximum };
{
Fixed,
Minimum,
Maximum
};
private: private:
int m_x, m_y; int m_x, m_y;
Test m_xtest, m_ytest; Test m_xtest, m_ytest;
public: public:
RectangleConstraint(int x=-1, int y=-1, Test xtest=Test::Fixed, Test ytest=Test::Fixed) RectangleConstraint(int x = -1, int y = -1, Test xtest = Test::Fixed, Test ytest = Test::Fixed)
: m_x(x), m_y(y), m_xtest(xtest), m_ytest(ytest) {} : m_x(x), m_y(y), m_xtest(xtest), m_ytest(ytest) {}
std::pair<int,int> solve(int x, int y) const std::pair<int, int> solve(int x, int y) const {
{ std::pair<int, int> ret;
std::pair<int,int> ret;
if (m_x < 0) if (m_x < 0)
ret.first = x; ret.first = x;
else else {
{ switch (m_xtest) {
switch (m_xtest) case Test::Fixed:
{ ret.first = m_x;
case Test::Fixed: break;
ret.first = m_x; case Test::Minimum:
break; ret.first = std::max(m_x, x);
case Test::Minimum: break;
ret.first = std::max(m_x, x); case Test::Maximum:
break; ret.first = std::min(m_x, x);
case Test::Maximum: break;
ret.first = std::min(m_x, x); }
break;
}
}
if (m_y < 0)
ret.second = y;
else
{
switch (m_ytest)
{
case Test::Fixed:
ret.second = m_y;
break;
case Test::Minimum:
ret.second = std::max(m_y, y);
break;
case Test::Maximum:
ret.second = std::min(m_y, y);
break;
}
}
return ret;
} }
if (m_y < 0)
ret.second = y;
else {
switch (m_ytest) {
case Test::Fixed:
ret.second = m_y;
break;
case Test::Minimum:
ret.second = std::max(m_y, y);
break;
case Test::Maximum:
ret.second = std::min(m_y, y);
break;
}
}
return ret;
}
}; };
class Space; class Space;
class SplitView; class SplitView;
class View class View {
{
public: public:
struct SolidShaderVert struct SolidShaderVert {
{ zeus::CVector3f m_pos;
zeus::CVector3f m_pos; zeus::CColor m_color = zeus::CColor::skClear;
zeus::CColor m_color = zeus::CColor::skClear; };
}; struct TexShaderVert {
struct TexShaderVert zeus::CVector3f m_pos;
{ zeus::CVector2f m_uv;
zeus::CVector3f m_pos; };
zeus::CVector2f m_uv; struct ViewBlock {
}; zeus::CMatrix4f m_mv;
struct ViewBlock zeus::CColor m_color = zeus::CColor::skWhite;
{ void setViewRect(const boo::SWindowRect& root, const boo::SWindowRect& sub) {
zeus::CMatrix4f m_mv; m_mv[0][0] = 2.0f / root.size[0];
zeus::CColor m_color = zeus::CColor::skWhite; m_mv[1][1] = 2.0f / root.size[1];
void setViewRect(const boo::SWindowRect& root, const boo::SWindowRect& sub) m_mv[3][0] = sub.location[0] * m_mv[0][0] - 1.0f;
{ m_mv[3][1] = sub.location[1] * m_mv[1][1] - 1.0f;
m_mv[0][0] = 2.0f / root.size[0]; }
m_mv[1][1] = 2.0f / root.size[1]; void finalAssign(const ViewBlock& other) {
m_mv[3][0] = sub.location[0] * m_mv[0][0] - 1.0f; m_mv = g_PlatformMatrix * other.m_mv;
m_mv[3][1] = sub.location[1] * m_mv[1][1] - 1.0f; m_color = other.m_color;
} }
void finalAssign(const ViewBlock& other) };
{
m_mv = g_PlatformMatrix * other.m_mv;
m_color = other.m_color;
}
};
template <typename VertStruct> template <typename VertStruct>
struct VertexBufferBinding struct VertexBufferBinding {
{ typename hecl::VertexBufferPool<VertStruct>::Token m_vertsBuf;
typename hecl::VertexBufferPool<VertStruct>::Token m_vertsBuf; boo::ObjToken<boo::IShaderDataBinding> m_shaderBinding;
boo::ObjToken<boo::IShaderDataBinding> m_shaderBinding;
void load(const VertStruct* data, size_t count) void load(const VertStruct* data, size_t count) {
{ if (m_vertsBuf) {
if (m_vertsBuf) VertStruct* out = m_vertsBuf.access();
{ for (size_t i = 0; i < count; ++i)
VertStruct* out = m_vertsBuf.access(); out[i] = data[i];
for (size_t i=0; i<count; ++i) }
out[i] = data[i]; }
} template <typename VertArray>
} void load(const VertArray data) {
template <typename VertArray> static_assert(std::is_same<std::remove_all_extents_t<VertArray>, VertStruct>::value, "mismatched type");
void load(const VertArray data) if (m_vertsBuf) {
{ constexpr size_t count = sizeof(VertArray) / sizeof(VertStruct);
static_assert(std::is_same<std::remove_all_extents_t<VertArray>, VertStruct* out = m_vertsBuf.access();
VertStruct>::value, "mismatched type"); for (size_t i = 0; i < count; ++i)
if (m_vertsBuf) out[i] = data[i];
{ }
constexpr size_t count = sizeof(VertArray) / sizeof(VertStruct); }
VertStruct* out = m_vertsBuf.access();
for (size_t i=0; i<count; ++i)
out[i] = data[i];
}
}
operator const boo::ObjToken<boo::IShaderDataBinding>&() { return m_shaderBinding; } operator const boo::ObjToken<boo::IShaderDataBinding>&() { return m_shaderBinding; }
}; };
struct VertexBufferBindingSolid : VertexBufferBinding<SolidShaderVert> struct VertexBufferBindingSolid : VertexBufferBinding<SolidShaderVert> {
{ void init(boo::IGraphicsDataFactory::Context& ctx, ViewResources& res, size_t count,
void init(boo::IGraphicsDataFactory::Context& ctx, const hecl::UniformBufferPool<ViewBlock>::Token& viewBlockBuf);
ViewResources& res, size_t count, };
const hecl::UniformBufferPool<ViewBlock>::Token& viewBlockBuf); struct VertexBufferBindingTex : VertexBufferBinding<TexShaderVert> {
}; void init(boo::IGraphicsDataFactory::Context& ctx, ViewResources& res, size_t count,
struct VertexBufferBindingTex : VertexBufferBinding<TexShaderVert> const hecl::UniformBufferPool<ViewBlock>::Token& viewBlockBuf,
{ const boo::ObjToken<boo::ITexture>& texture);
void init(boo::IGraphicsDataFactory::Context& ctx, };
ViewResources& res, size_t count,
const hecl::UniformBufferPool<ViewBlock>::Token& viewBlockBuf,
const boo::ObjToken<boo::ITexture>& texture);
};
private: private:
RootView& m_rootView; RootView& m_rootView;
View& m_parentView; View& m_parentView;
boo::SWindowRect m_subRect; boo::SWindowRect m_subRect;
VertexBufferBindingSolid m_bgVertsBinding; VertexBufferBindingSolid m_bgVertsBinding;
SolidShaderVert m_bgRect[4]; SolidShaderVert m_bgRect[4];
friend class RootView; friend class RootView;
View(ViewResources& res); View(ViewResources& res);
protected: protected:
ViewBlock m_viewVertBlock; ViewBlock m_viewVertBlock;
hecl::UniformBufferPool<ViewBlock>::Token m_viewVertBlockBuf; hecl::UniformBufferPool<ViewBlock>::Token m_viewVertBlockBuf;
public: public:
struct Resources struct Resources {
{ hecl::UniformBufferPool<ViewBlock> m_bufPool;
hecl::UniformBufferPool<ViewBlock> m_bufPool; hecl::VertexBufferPool<SolidShaderVert> m_solidPool;
hecl::VertexBufferPool<SolidShaderVert> m_solidPool; hecl::VertexBufferPool<TexShaderVert> m_texPool;
hecl::VertexBufferPool<TexShaderVert> m_texPool;
void updateBuffers() void updateBuffers() {
{ m_bufPool.updateBuffers();
m_bufPool.updateBuffers(); m_solidPool.updateBuffers();
m_solidPool.updateBuffers(); m_texPool.updateBuffers();
m_texPool.updateBuffers(); }
}
boo::ObjToken<boo::IShaderPipeline> m_solidShader; boo::ObjToken<boo::IShaderPipeline> m_solidShader;
boo::ObjToken<boo::IShaderPipeline> m_texShader; boo::ObjToken<boo::IShaderPipeline> m_texShader;
void init(boo::IGraphicsDataFactory::Context& ctx, const IThemeData& theme); void init(boo::IGraphicsDataFactory::Context& ctx, const IThemeData& theme);
void destroy() void destroy() {
{ m_bufPool.doDestroy();
m_bufPool.doDestroy(); m_solidPool.doDestroy();
m_solidPool.doDestroy(); m_texPool.doDestroy();
m_texPool.doDestroy();
m_solidShader.reset(); m_solidShader.reset();
m_texShader.reset(); m_texShader.reset();
} }
}; };
protected: protected:
View(ViewResources& res, View& parentView); View(ViewResources& res, View& parentView);
void buildResources(boo::IGraphicsDataFactory::Context& ctx, ViewResources& res); void buildResources(boo::IGraphicsDataFactory::Context& ctx, ViewResources& res);
void commitResources(ViewResources& res, const boo::FactoryCommitFunc& commitFunc); void commitResources(ViewResources& res, const boo::FactoryCommitFunc& commitFunc);
public: public:
virtual ~View() {} virtual ~View() {}
View() = delete; View() = delete;
View(const View& other) = delete; View(const View& other) = delete;
View& operator=(const View& other) = delete; View& operator=(const View& other) = delete;
View& parentView() {return m_parentView;} View& parentView() { return m_parentView; }
RootView& rootView() {return m_rootView;} RootView& rootView() { return m_rootView; }
const RootView& rootView() const {return m_rootView;} const RootView& rootView() const { return m_rootView; }
const boo::SWindowRect& subRect() const {return m_subRect;} const boo::SWindowRect& subRect() const { return m_subRect; }
int width() const {return m_subRect.size[0];} int width() const { return m_subRect.size[0]; }
int height() const {return m_subRect.size[1];} int height() const { return m_subRect.size[1]; }
void updateSize(); void updateSize();
void setBackground(const zeus::CColor& color) void setBackground(const zeus::CColor& color) {
{ for (int i = 0; i < 4; ++i)
for (int i=0 ; i<4 ; ++i) m_bgRect[i].m_color = color;
m_bgRect[i].m_color = color; m_bgVertsBinding.load<decltype(m_bgRect)>(m_bgRect);
m_bgVertsBinding.load<decltype(m_bgRect)>(m_bgRect); }
}
virtual void setMultiplyColor(const zeus::CColor& color) virtual void setMultiplyColor(const zeus::CColor& color) {
{ m_viewVertBlock.m_color = color;
m_viewVertBlock.m_color = color; if (m_viewVertBlockBuf)
if (m_viewVertBlockBuf) m_viewVertBlockBuf.access().finalAssign(m_viewVertBlock);
m_viewVertBlockBuf.access().finalAssign(m_viewVertBlock); }
}
virtual int nominalWidth() const {return 0;} virtual int nominalWidth() const { return 0; }
virtual int nominalHeight() const {return 0;} virtual int nominalHeight() const { return 0; }
virtual void setActive(bool) {} virtual void setActive(bool) {}
virtual void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey) {} virtual void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey) {}
virtual void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey) {} virtual void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey) {}
virtual void mouseMove(const boo::SWindowCoord&) {} virtual void mouseMove(const boo::SWindowCoord&) {}
virtual void mouseEnter(const boo::SWindowCoord&) {} virtual void mouseEnter(const boo::SWindowCoord&) {}
virtual void mouseLeave(const boo::SWindowCoord&) {} virtual void mouseLeave(const boo::SWindowCoord&) {}
virtual void scroll(const boo::SWindowCoord&, const boo::SScrollDelta&) {} virtual void scroll(const boo::SWindowCoord&, const boo::SScrollDelta&) {}
virtual void touchDown(const boo::STouchCoord&, uintptr_t) {} virtual void touchDown(const boo::STouchCoord&, uintptr_t) {}
virtual void touchUp(const boo::STouchCoord&, uintptr_t) {} virtual void touchUp(const boo::STouchCoord&, uintptr_t) {}
virtual void touchMove(const boo::STouchCoord&, uintptr_t) {} virtual void touchMove(const boo::STouchCoord&, uintptr_t) {}
virtual void charKeyDown(unsigned long, boo::EModifierKey, bool) {} virtual void charKeyDown(unsigned long, boo::EModifierKey, bool) {}
virtual void charKeyUp(unsigned long, boo::EModifierKey) {} virtual void charKeyUp(unsigned long, boo::EModifierKey) {}
virtual void specialKeyDown(boo::ESpecialKey, boo::EModifierKey, bool) {} virtual void specialKeyDown(boo::ESpecialKey, boo::EModifierKey, bool) {}
virtual void specialKeyUp(boo::ESpecialKey, boo::EModifierKey) {} virtual void specialKeyUp(boo::ESpecialKey, boo::EModifierKey) {}
virtual void modKeyDown(boo::EModifierKey, bool) {} virtual void modKeyDown(boo::EModifierKey, bool) {}
virtual void modKeyUp(boo::EModifierKey) {} virtual void modKeyUp(boo::EModifierKey) {}
virtual void containerResized(const boo::SWindowRect& root, const boo::SWindowRect& sub) {} virtual void containerResized(const boo::SWindowRect& root, const boo::SWindowRect& sub) {}
virtual void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub); virtual void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub);
virtual void resized(const ViewBlock& vb, const boo::SWindowRect& sub); virtual void resized(const ViewBlock& vb, const boo::SWindowRect& sub);
virtual void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub, virtual void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub, const boo::SWindowRect& scissor) {
const boo::SWindowRect& scissor) {resized(root, sub);} resized(root, sub);
virtual void think() {} }
virtual void draw(boo::IGraphicsCommandQueue* gfxQ); virtual void think() {}
virtual void draw(boo::IGraphicsCommandQueue* gfxQ);
virtual bool isSpace() const { return false; } virtual bool isSpace() const { return false; }
virtual bool isSplitView() const { return false; } virtual bool isSplitView() const { return false; }
Space* castToSpace(); Space* castToSpace();
SplitView* castToSplitView(); SplitView* castToSplitView();
}; };
template <class ViewPtrType> template <class ViewPtrType>
struct ViewChild struct ViewChild {
{ ViewPtrType m_view = ViewPtrType();
ViewPtrType m_view = ViewPtrType(); bool m_mouseIn = false;
bool m_mouseIn = false; int m_mouseDown = 0;
int m_mouseDown = 0;
bool mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) bool mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
{ if (!m_view)
if (!m_view) return false;
return false; if (m_view->subRect().coordInRect(coord)) {
if (m_view->subRect().coordInRect(coord)) if ((m_mouseDown & 1 << int(button)) == 0) {
{ m_view->mouseDown(coord, button, mod);
if ((m_mouseDown & 1 << int(button)) == 0) m_mouseDown |= 1 << int(button);
{ }
m_view->mouseDown(coord, button, mod); return true;
m_mouseDown |= 1 << int(button);
}
return true;
}
return false;
} }
return false;
}
void mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) void mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
{ if (!m_view)
if (!m_view) return;
return; if ((m_mouseDown & 1 << int(button)) != 0) {
if ((m_mouseDown & 1 << int(button)) != 0) m_view->mouseUp(coord, button, mod);
{ m_mouseDown &= ~(1 << int(button));
m_view->mouseUp(coord, button, mod);
m_mouseDown &= ~(1 << int(button));
}
} }
}
void mouseMove(const boo::SWindowCoord& coord) void mouseMove(const boo::SWindowCoord& coord) {
{ if (!m_view)
if (!m_view) return;
return; if (m_view->subRect().coordInRect(coord)) {
if (m_view->subRect().coordInRect(coord)) if (!m_mouseIn) {
{ m_view->mouseEnter(coord);
if (!m_mouseIn) m_mouseIn = true;
{ }
m_view->mouseEnter(coord); m_view->mouseMove(coord);
m_mouseIn = true; } else {
} if (m_mouseIn) {
m_view->mouseMove(coord); m_view->mouseLeave(coord);
} m_mouseIn = false;
else }
{
if (m_mouseIn)
{
m_view->mouseLeave(coord);
m_mouseIn = false;
}
}
} }
}
void mouseEnter(const boo::SWindowCoord& coord) void mouseEnter(const boo::SWindowCoord& coord) {
{ if (!m_view)
if (!m_view) return;
return; }
}
void mouseLeave(const boo::SWindowCoord& coord) void mouseLeave(const boo::SWindowCoord& coord) {
{ if (!m_view)
if (!m_view) return;
return; if (m_mouseIn) {
if (m_mouseIn) m_view->mouseLeave(coord);
{ m_mouseIn = false;
m_view->mouseLeave(coord);
m_mouseIn = false;
}
} }
}
void scroll(const boo::SWindowCoord& coord, const boo::SScrollDelta& scroll) void scroll(const boo::SWindowCoord& coord, const boo::SScrollDelta& scroll) {
{ if (!m_view)
if (!m_view) return;
return; if (m_mouseIn)
if (m_mouseIn) m_view->scroll(coord, scroll);
m_view->scroll(coord, scroll); }
}
}; };
template <class ViewPtrType> template <class ViewPtrType>
struct ScissorViewChild : ViewChild<ViewPtrType> struct ScissorViewChild : ViewChild<ViewPtrType> {
{ using base = ViewChild<ViewPtrType>;
using base = ViewChild<ViewPtrType>; boo::SWindowRect m_scissorRect;
boo::SWindowRect m_scissorRect;
bool mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) bool mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
{ if (!base::m_view)
if (!base::m_view) return false;
return false; if (base::m_view->subRect().coordInRect(coord) && m_scissorRect.coordInRect(coord)) {
if (base::m_view->subRect().coordInRect(coord) && if ((base::m_mouseDown & 1 << int(button)) == 0) {
m_scissorRect.coordInRect(coord)) base::m_view->mouseDown(coord, button, mod);
{ base::m_mouseDown |= 1 << int(button);
if ((base::m_mouseDown & 1 << int(button)) == 0) }
{ return true;
base::m_view->mouseDown(coord, button, mod);
base::m_mouseDown |= 1 << int(button);
}
return true;
}
return false;
} }
return false;
}
void mouseMove(const boo::SWindowCoord& coord) void mouseMove(const boo::SWindowCoord& coord) {
{ if (!base::m_view)
if (!base::m_view) return;
return; if (base::m_view->subRect().coordInRect(coord) && m_scissorRect.coordInRect(coord)) {
if (base::m_view->subRect().coordInRect(coord) && if (!base::m_mouseIn) {
m_scissorRect.coordInRect(coord)) base::m_view->mouseEnter(coord);
{ base::m_mouseIn = true;
if (!base::m_mouseIn) }
{ base::m_view->mouseMove(coord);
base::m_view->mouseEnter(coord); } else {
base::m_mouseIn = true; if (base::m_mouseIn) {
} base::m_view->mouseLeave(coord);
base::m_view->mouseMove(coord); base::m_mouseIn = false;
} }
else
{
if (base::m_mouseIn)
{
base::m_view->mouseLeave(coord);
base::m_mouseIn = false;
}
}
} }
}
}; };
} } // namespace specter

View File

@ -7,213 +7,204 @@
#include <thread> #include <thread>
namespace specter namespace specter {
{ class IThemeData {
class IThemeData
{
public: public:
virtual const zeus::CColor& uiText() const = 0; virtual const zeus::CColor& uiText() const = 0;
virtual const zeus::CColor& uiAltText() const = 0; virtual const zeus::CColor& uiAltText() const = 0;
virtual const zeus::CColor& fieldText() const = 0; virtual const zeus::CColor& fieldText() const = 0;
virtual const zeus::CColor& fieldMarkedText() const = 0; virtual const zeus::CColor& fieldMarkedText() const = 0;
virtual const zeus::CColor& selectedFieldText() const = 0; virtual const zeus::CColor& selectedFieldText() const = 0;
virtual const zeus::CColor& viewportBackground() const = 0; virtual const zeus::CColor& viewportBackground() const = 0;
virtual const zeus::CColor& toolbarBackground() const = 0; virtual const zeus::CColor& toolbarBackground() const = 0;
virtual const zeus::CColor& tooltipBackground() const = 0; virtual const zeus::CColor& tooltipBackground() const = 0;
virtual const zeus::CColor& spaceBackground() const = 0; virtual const zeus::CColor& spaceBackground() const = 0;
virtual const zeus::CColor& splashBackground() const = 0; virtual const zeus::CColor& splashBackground() const = 0;
virtual const zeus::CColor& splashErrorBackground() const = 0; virtual const zeus::CColor& splashErrorBackground() const = 0;
virtual const zeus::CColor& splash1() const = 0; virtual const zeus::CColor& splash1() const = 0;
virtual const zeus::CColor& splash2() const = 0; virtual const zeus::CColor& splash2() const = 0;
virtual const zeus::CColor& button1Inactive() const = 0; virtual const zeus::CColor& button1Inactive() const = 0;
virtual const zeus::CColor& button2Inactive() const = 0; virtual const zeus::CColor& button2Inactive() const = 0;
virtual const zeus::CColor& button1Hover() const = 0; virtual const zeus::CColor& button1Hover() const = 0;
virtual const zeus::CColor& button2Hover() const = 0; virtual const zeus::CColor& button2Hover() const = 0;
virtual const zeus::CColor& button1Press() const = 0; virtual const zeus::CColor& button1Press() const = 0;
virtual const zeus::CColor& button2Press() const = 0; virtual const zeus::CColor& button2Press() const = 0;
virtual const zeus::CColor& button1Disabled() const = 0; virtual const zeus::CColor& button1Disabled() const = 0;
virtual const zeus::CColor& button2Disabled() const = 0; virtual const zeus::CColor& button2Disabled() const = 0;
virtual const zeus::CColor& textfield1Inactive() const = 0; virtual const zeus::CColor& textfield1Inactive() const = 0;
virtual const zeus::CColor& textfield2Inactive() const = 0; virtual const zeus::CColor& textfield2Inactive() const = 0;
virtual const zeus::CColor& textfield1Hover() const = 0; virtual const zeus::CColor& textfield1Hover() const = 0;
virtual const zeus::CColor& textfield2Hover() const = 0; virtual const zeus::CColor& textfield2Hover() const = 0;
virtual const zeus::CColor& textfield1Disabled() const = 0; virtual const zeus::CColor& textfield1Disabled() const = 0;
virtual const zeus::CColor& textfield2Disabled() const = 0; virtual const zeus::CColor& textfield2Disabled() const = 0;
virtual const zeus::CColor& textfieldSelection() const = 0; virtual const zeus::CColor& textfieldSelection() const = 0;
virtual const zeus::CColor& textfieldMarkSelection() const = 0; virtual const zeus::CColor& textfieldMarkSelection() const = 0;
virtual const zeus::CColor& tableCellBg1() const = 0; virtual const zeus::CColor& tableCellBg1() const = 0;
virtual const zeus::CColor& tableCellBg2() const = 0; virtual const zeus::CColor& tableCellBg2() const = 0;
virtual const zeus::CColor& tableCellBgSelected() const = 0; virtual const zeus::CColor& tableCellBgSelected() const = 0;
virtual const zeus::CColor& scrollIndicator() const = 0; virtual const zeus::CColor& scrollIndicator() const = 0;
virtual const zeus::CColor& spaceTriangleShading1() const = 0; virtual const zeus::CColor& spaceTriangleShading1() const = 0;
virtual const zeus::CColor& spaceTriangleShading2() const = 0; virtual const zeus::CColor& spaceTriangleShading2() const = 0;
}; };
class DefaultThemeData : public IThemeData class DefaultThemeData : public IThemeData {
{ zeus::CColor m_uiText = zeus::CColor::skWhite;
zeus::CColor m_uiText = zeus::CColor::skWhite; zeus::CColor m_uiAltText = zeus::CColor::skGrey;
zeus::CColor m_uiAltText = zeus::CColor::skGrey; zeus::CColor m_fieldText = zeus::CColor::skBlack;
zeus::CColor m_fieldText = zeus::CColor::skBlack; zeus::CColor m_fieldMarkedText = {0.25, 0.25, 0.25, 1.0};
zeus::CColor m_fieldMarkedText = {0.25, 0.25, 0.25, 1.0}; zeus::CColor m_selectedFieldText = zeus::CColor::skWhite;
zeus::CColor m_selectedFieldText = zeus::CColor::skWhite;
zeus::CColor m_vpBg = {0.2, 0.2, 0.2, 1.0}; zeus::CColor m_vpBg = {0.2, 0.2, 0.2, 1.0};
zeus::CColor m_tbBg = {0.2, 0.2, 0.2, 0.9}; zeus::CColor m_tbBg = {0.2, 0.2, 0.2, 0.9};
zeus::CColor m_tooltipBg = {0.1, 0.1, 0.1, 0.85}; zeus::CColor m_tooltipBg = {0.1, 0.1, 0.1, 0.85};
zeus::CColor m_spaceBg = {0.075, 0.075, 0.075, 0.85}; zeus::CColor m_spaceBg = {0.075, 0.075, 0.075, 0.85};
zeus::CColor m_splashBg = {0.075, 0.075, 0.075, 0.85}; zeus::CColor m_splashBg = {0.075, 0.075, 0.075, 0.85};
zeus::CColor m_splashErrorBg = {0.1, 0.01, 0.01, 0.85}; zeus::CColor m_splashErrorBg = {0.1, 0.01, 0.01, 0.85};
zeus::CColor m_splash1 = {1.0, 1.0, 1.0, 1.0}; zeus::CColor m_splash1 = {1.0, 1.0, 1.0, 1.0};
zeus::CColor m_splash2 = {0.3, 0.3, 0.3, 1.0}; zeus::CColor m_splash2 = {0.3, 0.3, 0.3, 1.0};
zeus::CColor m_button1Inactive = {0.2823, 0.2823, 0.2823, 1.0}; zeus::CColor m_button1Inactive = {0.2823, 0.2823, 0.2823, 1.0};
zeus::CColor m_button2Inactive = {0.1725, 0.1725, 0.1725, 1.0}; zeus::CColor m_button2Inactive = {0.1725, 0.1725, 0.1725, 1.0};
zeus::CColor m_button1Hover = {0.3523, 0.3523, 0.3523, 1.0}; zeus::CColor m_button1Hover = {0.3523, 0.3523, 0.3523, 1.0};
zeus::CColor m_button2Hover = {0.2425, 0.2425, 0.2425, 1.0}; zeus::CColor m_button2Hover = {0.2425, 0.2425, 0.2425, 1.0};
zeus::CColor m_button1Press = {0.1725, 0.1725, 0.1725, 1.0}; zeus::CColor m_button1Press = {0.1725, 0.1725, 0.1725, 1.0};
zeus::CColor m_button2Press = {0.2823, 0.2823, 0.2823, 1.0}; zeus::CColor m_button2Press = {0.2823, 0.2823, 0.2823, 1.0};
zeus::CColor m_button1Disabled = {0.2823, 0.2823, 0.2823, 0.5}; zeus::CColor m_button1Disabled = {0.2823, 0.2823, 0.2823, 0.5};
zeus::CColor m_button2Disabled = {0.1725, 0.1725, 0.1725, 0.5}; zeus::CColor m_button2Disabled = {0.1725, 0.1725, 0.1725, 0.5};
zeus::CColor m_textfield2Inactive = {0.7823, 0.7823, 0.7823, 1.0}; zeus::CColor m_textfield2Inactive = {0.7823, 0.7823, 0.7823, 1.0};
zeus::CColor m_textfield1Inactive = {0.5725, 0.5725, 0.5725, 1.0}; zeus::CColor m_textfield1Inactive = {0.5725, 0.5725, 0.5725, 1.0};
zeus::CColor m_textfield2Hover = {0.8523, 0.8523, 0.8523, 1.0}; zeus::CColor m_textfield2Hover = {0.8523, 0.8523, 0.8523, 1.0};
zeus::CColor m_textfield1Hover = {0.6425, 0.6425, 0.6425, 1.0}; zeus::CColor m_textfield1Hover = {0.6425, 0.6425, 0.6425, 1.0};
zeus::CColor m_textfield2Disabled = {0.7823, 0.7823, 0.7823, 0.5}; zeus::CColor m_textfield2Disabled = {0.7823, 0.7823, 0.7823, 0.5};
zeus::CColor m_textfield1Disabled = {0.5725, 0.5725, 0.5725, 0.5}; zeus::CColor m_textfield1Disabled = {0.5725, 0.5725, 0.5725, 0.5};
zeus::CColor m_textfieldSelection = {0.2725, 0.2725, 0.2725, 1.0}; zeus::CColor m_textfieldSelection = {0.2725, 0.2725, 0.2725, 1.0};
zeus::CColor m_textfieldMarkSelection = {1.0, 1.0, 0.2725, 1.0}; zeus::CColor m_textfieldMarkSelection = {1.0, 1.0, 0.2725, 1.0};
zeus::CColor m_tableCellBg1 = {0.1725, 0.1725, 0.1725, 0.75}; zeus::CColor m_tableCellBg1 = {0.1725, 0.1725, 0.1725, 0.75};
zeus::CColor m_tableCellBg2 = {0.2425, 0.2425, 0.2425, 0.75}; zeus::CColor m_tableCellBg2 = {0.2425, 0.2425, 0.2425, 0.75};
zeus::CColor m_tableCellBgSelected = {0.6425, 0.6425, 0.6425, 1.0}; zeus::CColor m_tableCellBgSelected = {0.6425, 0.6425, 0.6425, 1.0};
zeus::CColor m_scrollIndicator = {0.2823, 0.2823, 0.2823, 1.0}; zeus::CColor m_scrollIndicator = {0.2823, 0.2823, 0.2823, 1.0};
zeus::CColor m_spaceTriangleShading1 = {0.6425, 0.6425, 0.6425, 1.0}; zeus::CColor m_spaceTriangleShading1 = {0.6425, 0.6425, 0.6425, 1.0};
zeus::CColor m_spaceTriangleShading2 = {0.5725, 0.5725, 0.5725, 1.0}; zeus::CColor m_spaceTriangleShading2 = {0.5725, 0.5725, 0.5725, 1.0};
public: public:
virtual const zeus::CColor& uiText() const { return m_uiText; } virtual const zeus::CColor& uiText() const { return m_uiText; }
virtual const zeus::CColor& uiAltText() const { return m_uiAltText; } virtual const zeus::CColor& uiAltText() const { return m_uiAltText; }
virtual const zeus::CColor& fieldText() const { return m_fieldText; } virtual const zeus::CColor& fieldText() const { return m_fieldText; }
virtual const zeus::CColor& fieldMarkedText() const { return m_fieldMarkedText; } virtual const zeus::CColor& fieldMarkedText() const { return m_fieldMarkedText; }
virtual const zeus::CColor& selectedFieldText() const { return m_selectedFieldText; } virtual const zeus::CColor& selectedFieldText() const { return m_selectedFieldText; }
virtual const zeus::CColor& viewportBackground() const { return m_vpBg; } virtual const zeus::CColor& viewportBackground() const { return m_vpBg; }
virtual const zeus::CColor& toolbarBackground() const { return m_tbBg; } virtual const zeus::CColor& toolbarBackground() const { return m_tbBg; }
virtual const zeus::CColor& tooltipBackground() const { return m_tooltipBg; } virtual const zeus::CColor& tooltipBackground() const { return m_tooltipBg; }
virtual const zeus::CColor& spaceBackground() const { return m_spaceBg; } virtual const zeus::CColor& spaceBackground() const { return m_spaceBg; }
virtual const zeus::CColor& splashBackground() const { return m_splashBg; } virtual const zeus::CColor& splashBackground() const { return m_splashBg; }
virtual const zeus::CColor& splashErrorBackground() const { return m_splashErrorBg; } virtual const zeus::CColor& splashErrorBackground() const { return m_splashErrorBg; }
virtual const zeus::CColor& splash1() const { return m_splash1; } virtual const zeus::CColor& splash1() const { return m_splash1; }
virtual const zeus::CColor& splash2() const { return m_splash2; } virtual const zeus::CColor& splash2() const { return m_splash2; }
virtual const zeus::CColor& button1Inactive() const { return m_button1Inactive; } virtual const zeus::CColor& button1Inactive() const { return m_button1Inactive; }
virtual const zeus::CColor& button2Inactive() const { return m_button2Inactive; } virtual const zeus::CColor& button2Inactive() const { return m_button2Inactive; }
virtual const zeus::CColor& button1Hover() const { return m_button1Hover; } virtual const zeus::CColor& button1Hover() const { return m_button1Hover; }
virtual const zeus::CColor& button2Hover() const { return m_button2Hover; } virtual const zeus::CColor& button2Hover() const { return m_button2Hover; }
virtual const zeus::CColor& button1Press() const { return m_button1Press; } virtual const zeus::CColor& button1Press() const { return m_button1Press; }
virtual const zeus::CColor& button2Press() const { return m_button2Press; } virtual const zeus::CColor& button2Press() const { return m_button2Press; }
virtual const zeus::CColor& button1Disabled() const { return m_button1Disabled; } virtual const zeus::CColor& button1Disabled() const { return m_button1Disabled; }
virtual const zeus::CColor& button2Disabled() const { return m_button2Disabled; } virtual const zeus::CColor& button2Disabled() const { return m_button2Disabled; }
virtual const zeus::CColor& textfield1Inactive() const { return m_textfield1Inactive; } virtual const zeus::CColor& textfield1Inactive() const { return m_textfield1Inactive; }
virtual const zeus::CColor& textfield2Inactive() const { return m_textfield2Inactive; } virtual const zeus::CColor& textfield2Inactive() const { return m_textfield2Inactive; }
virtual const zeus::CColor& textfield1Hover() const { return m_textfield1Hover; } virtual const zeus::CColor& textfield1Hover() const { return m_textfield1Hover; }
virtual const zeus::CColor& textfield2Hover() const { return m_textfield2Hover; } virtual const zeus::CColor& textfield2Hover() const { return m_textfield2Hover; }
virtual const zeus::CColor& textfield1Disabled() const { return m_textfield1Disabled; } virtual const zeus::CColor& textfield1Disabled() const { return m_textfield1Disabled; }
virtual const zeus::CColor& textfield2Disabled() const { return m_textfield2Disabled; } virtual const zeus::CColor& textfield2Disabled() const { return m_textfield2Disabled; }
virtual const zeus::CColor& textfieldSelection() const { return m_textfieldSelection; } virtual const zeus::CColor& textfieldSelection() const { return m_textfieldSelection; }
virtual const zeus::CColor& textfieldMarkSelection() const { return m_textfieldMarkSelection; } virtual const zeus::CColor& textfieldMarkSelection() const { return m_textfieldMarkSelection; }
virtual const zeus::CColor& tableCellBg1() const { return m_tableCellBg1; } virtual const zeus::CColor& tableCellBg1() const { return m_tableCellBg1; }
virtual const zeus::CColor& tableCellBg2() const { return m_tableCellBg2; } virtual const zeus::CColor& tableCellBg2() const { return m_tableCellBg2; }
virtual const zeus::CColor& tableCellBgSelected() const { return m_tableCellBgSelected; } virtual const zeus::CColor& tableCellBgSelected() const { return m_tableCellBgSelected; }
virtual const zeus::CColor& scrollIndicator() const { return m_scrollIndicator; } virtual const zeus::CColor& scrollIndicator() const { return m_scrollIndicator; }
virtual const zeus::CColor& spaceTriangleShading1() const { return m_spaceTriangleShading1; } virtual const zeus::CColor& spaceTriangleShading1() const { return m_spaceTriangleShading1; }
virtual const zeus::CColor& spaceTriangleShading2() const { return m_spaceTriangleShading2; } virtual const zeus::CColor& spaceTriangleShading2() const { return m_spaceTriangleShading2; }
}; };
class ViewResources class ViewResources {
{ void init(boo::IGraphicsDataFactory::Context& factory, const IThemeData& theme, FontCache* fcache) {
void init(boo::IGraphicsDataFactory::Context& factory, const IThemeData& theme, FontCache* fcache) m_viewRes.init(factory, theme);
{ m_textRes.init(factory, fcache);
m_viewRes.init(factory, theme); m_splitRes.init(factory, theme);
m_textRes.init(factory, fcache); m_toolbarRes.init(factory, theme);
m_splitRes.init(factory, theme); m_buttonRes.init(factory, theme);
m_toolbarRes.init(factory, theme); }
m_buttonRes.init(factory, theme);
}
public: public:
boo::IGraphicsDataFactory* m_factory; boo::IGraphicsDataFactory* m_factory;
FontCache* m_fcache = nullptr; FontCache* m_fcache = nullptr;
View::Resources m_viewRes; View::Resources m_viewRes;
TextView::Resources m_textRes; TextView::Resources m_textRes;
SplitView::Resources m_splitRes; SplitView::Resources m_splitRes;
Toolbar::Resources m_toolbarRes; Toolbar::Resources m_toolbarRes;
Button::Resources m_buttonRes; Button::Resources m_buttonRes;
specter::FontTag m_mainFont; specter::FontTag m_mainFont;
specter::FontTag m_monoFont10; specter::FontTag m_monoFont10;
specter::FontTag m_monoFont18; specter::FontTag m_monoFont18;
specter::FontTag m_heading14; specter::FontTag m_heading14;
specter::FontTag m_heading18; specter::FontTag m_heading18;
specter::FontTag m_titleFont; specter::FontTag m_titleFont;
specter::FontTag m_curveFont; specter::FontTag m_curveFont;
std::thread m_fcacheThread; std::thread m_fcacheThread;
std::atomic_bool m_fcacheInterrupt = {false}; std::atomic_bool m_fcacheInterrupt = {false};
std::atomic_bool m_fcacheReady = {false}; std::atomic_bool m_fcacheReady = {false};
ViewResources() = default; ViewResources() = default;
ViewResources(const ViewResources& other) = delete; ViewResources(const ViewResources& other) = delete;
ViewResources(ViewResources&& other) = default; ViewResources(ViewResources&& other) = default;
ViewResources& operator=(const ViewResources& other) = delete; ViewResources& operator=(const ViewResources& other) = delete;
ViewResources& operator=(ViewResources&& other) = default; ViewResources& operator=(ViewResources&& other) = default;
void updateBuffers() void updateBuffers() {
{ m_viewRes.updateBuffers();
m_viewRes.updateBuffers(); m_textRes.updateBuffers();
m_textRes.updateBuffers(); }
~ViewResources() {
if (m_fcacheThread.joinable()) {
m_fcacheInterrupt.store(true);
m_fcacheThread.join();
} }
}
~ViewResources() void init(boo::IGraphicsDataFactory* factory, FontCache* fcache, const IThemeData* theme, float pixelFactor);
{ void destroyResData();
if (m_fcacheThread.joinable()) void prepFontCacheSync();
{ void prepFontCacheAsync(boo::IWindow* window);
m_fcacheInterrupt.store(true); bool fontCacheReady() const { return m_fcacheReady.load(); }
m_fcacheThread.join(); void resetPixelFactor(float pixelFactor);
} void resetTheme(const IThemeData* theme);
}
void init(boo::IGraphicsDataFactory* factory, FontCache* fcache, const IThemeData* theme, float pixelFactor); float m_pixelFactor = 0;
void destroyResData(); float pixelFactor() const { return m_pixelFactor; }
void prepFontCacheSync();
void prepFontCacheAsync(boo::IWindow* window);
bool fontCacheReady() const { return m_fcacheReady.load(); }
void resetPixelFactor(float pixelFactor);
void resetTheme(const IThemeData* theme);
float m_pixelFactor = 0; const IThemeData* m_theme;
float pixelFactor() const { return m_pixelFactor; } const IThemeData& themeData() const { return *m_theme; }
const IThemeData* m_theme;
const IThemeData& themeData() const { return *m_theme; }
}; };
} // namespace specter } // namespace specter

View File

@ -1,13 +1,9 @@
#pragma once #pragma once
#if __specter__ #if __specter__
#define SPECTER_PROPERTY(n, d) \ #define SPECTER_PROPERTY(n, d) [[using specter: name(n), description(d)]]
[[using specter: name(n), description(d)]] #define SPECTER_ENUM(n, d, et) [[using specter: name(n), description(d), enum_type(et)]]
#define SPECTER_ENUM(n, d, et) \
[[using specter: name(n), description(d), enum_type(et)]]
#else #else
#define SPECTER_PROPERTY(n, d) #define SPECTER_PROPERTY(n, d)
#define SPECTER_ENUM(n, d, et) #define SPECTER_ENUM(n, d, et)
#endif #endif

View File

@ -16,4 +16,3 @@
#include "NodeSocket.hpp" #include "NodeSocket.hpp"
#include "FontCache.hpp" #include "FontCache.hpp"
#include "ViewResources.hpp" #include "ViewResources.hpp"

File diff suppressed because it is too large Load Diff

View File

@ -1,12 +1,10 @@
#include "specter/Control.hpp" #include "specter/Control.hpp"
namespace specter namespace specter {
{
Control::Control(ViewResources& res, View& parentView, Control::Control(ViewResources& res, View& parentView, IControlBinding* controlBinding)
IControlBinding* controlBinding)
: View(res, parentView), m_controlBinding(controlBinding) {} : View(res, parentView), m_controlBinding(controlBinding) {}
std::recursive_mutex ITextInputView::m_textInputLk; std::recursive_mutex ITextInputView::m_textInputLk;
} } // namespace specter

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,41 +1,34 @@
#include "specter/Icon.hpp" #include "specter/Icon.hpp"
#include "specter/RootView.hpp" #include "specter/RootView.hpp"
namespace specter namespace specter {
{
IconView::IconView(ViewResources& res, View& parentView, Icon& icon) IconView::IconView(ViewResources& res, View& parentView, Icon& icon) : View(res, parentView) {
: View(res, parentView) commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool {
{ buildResources(ctx, res);
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool m_vertexBinding.init(ctx, res, 4, m_viewVertBlockBuf, icon.m_tex);
{ return true;
buildResources(ctx, res); });
m_vertexBinding.init(ctx, res, 4, m_viewVertBlockBuf, icon.m_tex); TexShaderVert verts[] = {
return true; {{0, 1, 0}, icon.m_uvCoords[0]},
}); {{0, 0, 0}, icon.m_uvCoords[1]},
TexShaderVert verts[] = {{1, 1, 0}, icon.m_uvCoords[2]},
{ {{1, 0, 0}, icon.m_uvCoords[3]},
{{0, 1, 0}, icon.m_uvCoords[0]}, };
{{0, 0, 0}, icon.m_uvCoords[1]}, m_vertexBinding.load<decltype(verts)>(verts);
{{1, 1, 0}, icon.m_uvCoords[2]}, setBackground(zeus::CColor::skBlue);
{{1, 0, 0}, icon.m_uvCoords[3]},
};
m_vertexBinding.load<decltype(verts)>(verts);
setBackground(zeus::CColor::skBlue);
} }
void IconView::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) void IconView::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) {
{ m_viewVertBlock.setViewRect(root, sub);
m_viewVertBlock.setViewRect(root, sub); m_viewVertBlock.m_mv[0][0] *= sub.size[0];
m_viewVertBlock.m_mv[0][0] *= sub.size[0]; m_viewVertBlock.m_mv[1][1] *= sub.size[1];
m_viewVertBlock.m_mv[1][1] *= sub.size[1]; View::resized(m_viewVertBlock, sub);
View::resized(m_viewVertBlock, sub);
} }
void IconView::draw(boo::IGraphicsCommandQueue* gfxQ) void IconView::draw(boo::IGraphicsCommandQueue* gfxQ) {
{ gfxQ->setShaderDataBinding(m_vertexBinding);
gfxQ->setShaderDataBinding(m_vertexBinding); gfxQ->draw(0, 4);
gfxQ->draw(0, 4);
} }
} } // namespace specter

View File

@ -5,322 +5,264 @@
#define ROW_HEIGHT 18 #define ROW_HEIGHT 18
#define ITEM_MARGIN 1 #define ITEM_MARGIN 1
namespace specter namespace specter {
{
Menu::Menu(ViewResources& res, View& parentView, IMenuNode* rootNode) Menu::Menu(ViewResources& res, View& parentView, IMenuNode* rootNode) : View(res, parentView) {
: View(res, parentView) commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool {
{ buildResources(ctx, res);
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool m_vertsBinding.init(ctx, res, 8, m_viewVertBlockBuf);
{ return true;
buildResources(ctx, res); });
m_vertsBinding.init(ctx, res, 8, m_viewVertBlockBuf); m_headText.reset(new TextView(res, *this, res.m_mainFont));
return true; m_scroll.m_view.reset(new ScrollView(res, *this, ScrollView::Style::ThinIndicator));
}); m_content.reset(new ContentView(res, *this));
m_headText.reset(new TextView(res, *this, res.m_mainFont)); m_scroll.m_view->setContentView(m_content.get());
m_scroll.m_view.reset(new ScrollView(res, *this, ScrollView::Style::ThinIndicator)); reset(rootNode);
m_content.reset(new ContentView(res, *this));
m_scroll.m_view->setContentView(m_content.get());
reset(rootNode);
} }
void Menu::reset(IMenuNode* rootNode) void Menu::reset(IMenuNode* rootNode) {
{ m_rootNode = rootNode;
m_rootNode = rootNode; m_thisNode = rootNode;
m_thisNode = rootNode; ViewResources& res = rootView().viewRes();
ViewResources& res = rootView().viewRes();
for (int i=0 ; i<8 ; ++i) for (int i = 0; i < 8; ++i)
m_verts[i].m_color = res.themeData().tooltipBackground(); m_verts[i].m_color = res.themeData().tooltipBackground();
m_vertsBinding.load<decltype(m_verts)>(m_verts); m_vertsBinding.load<decltype(m_verts)>(m_verts);
m_subMenu.reset(); m_subMenu.reset();
const std::string* headText = rootNode->text(); const std::string* headText = rootNode->text();
m_headText->typesetGlyphs(headText?*headText:"", rootView().themeData().uiAltText()); m_headText->typesetGlyphs(headText ? *headText : "", rootView().themeData().uiAltText());
float pf = rootView().viewRes().pixelFactor(); float pf = rootView().viewRes().pixelFactor();
int itemAdv = (ROW_HEIGHT + ITEM_MARGIN*2) * pf; int itemAdv = (ROW_HEIGHT + ITEM_MARGIN * 2) * pf;
m_cWidth = m_headText->nominalWidth() + 10*pf; m_cWidth = m_headText->nominalWidth() + 10 * pf;
m_cHeight = headText ? itemAdv : 0; m_cHeight = headText ? itemAdv : 0;
m_cTop = m_cHeight; m_cTop = m_cHeight;
size_t subCount = rootNode->subNodeCount(); size_t subCount = rootNode->subNodeCount();
m_items.clear(); m_items.clear();
if (subCount) if (subCount) {
{ m_items.reserve(subCount);
m_items.reserve(subCount); for (size_t i = 0; i < subCount; ++i) {
for (size_t i=0 ; i<subCount ; ++i) IMenuNode* node = rootNode->subNode(i);
{ const std::string* nodeText = node->text();
IMenuNode* node = rootNode->subNode(i);
const std::string* nodeText = node->text();
m_items.emplace_back(); m_items.emplace_back();
ViewChild<std::unique_ptr<ItemView>>& item = m_items.back(); ViewChild<std::unique_ptr<ItemView>>& item = m_items.back();
if (nodeText) if (nodeText) {
{ item.m_view.reset(new ItemView(res, *this, *nodeText, i, node));
item.m_view.reset(new ItemView(res, *this, *nodeText, i, node)); m_cWidth = std::max(m_cWidth, int(item.m_view->m_textView->nominalWidth() + 10 * pf));
m_cWidth = std::max(m_cWidth, int(item.m_view->m_textView->nominalWidth() + 10*pf)); }
}
m_cHeight += itemAdv; m_cHeight += itemAdv;
}
} }
}
} }
Menu::Menu(ViewResources& res, View& parentView, IMenuNode* rootNode, IMenuNode* thisNode) Menu::Menu(ViewResources& res, View& parentView, IMenuNode* rootNode, IMenuNode* thisNode)
: View(res, parentView), m_rootNode(rootNode), m_thisNode(thisNode) : View(res, parentView), m_rootNode(rootNode), m_thisNode(thisNode) {
{ commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool {
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool buildResources(ctx, res);
{ m_vertsBinding.init(ctx, res, 8, m_viewVertBlockBuf);
buildResources(ctx, res); return true;
m_vertsBinding.init(ctx, res, 8, m_viewVertBlockBuf); });
return true; m_headText.reset(new TextView(res, *this, res.m_mainFont));
}); m_scroll.m_view.reset(new ScrollView(res, *this, ScrollView::Style::ThinIndicator));
m_headText.reset(new TextView(res, *this, res.m_mainFont)); m_content.reset(new ContentView(res, *this));
m_scroll.m_view.reset(new ScrollView(res, *this, ScrollView::Style::ThinIndicator)); m_scroll.m_view->setContentView(m_content.get());
m_content.reset(new ContentView(res, *this));
m_scroll.m_view->setContentView(m_content.get());
} }
Menu::ContentView::ContentView(ViewResources& res, Menu& menu) Menu::ContentView::ContentView(ViewResources& res, Menu& menu) : View(res, menu), m_menu(menu) {
: View(res, menu), m_menu(menu) commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool {
{ buildResources(ctx, res);
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool m_hlVertsBinding.init(ctx, res, 4, m_viewVertBlockBuf);
{ return true;
buildResources(ctx, res); });
m_hlVertsBinding.init(ctx, res, 4, m_viewVertBlockBuf);
return true;
});
m_hlVerts[0].m_color = res.themeData().button1Hover(); m_hlVerts[0].m_color = res.themeData().button1Hover();
m_hlVerts[1].m_color = res.themeData().button2Hover(); m_hlVerts[1].m_color = res.themeData().button2Hover();
m_hlVerts[2].m_color = res.themeData().button1Hover(); m_hlVerts[2].m_color = res.themeData().button1Hover();
m_hlVerts[3].m_color = res.themeData().button2Hover(); m_hlVerts[3].m_color = res.themeData().button2Hover();
} }
Menu::ItemView::ItemView(ViewResources& res, Menu& menu, std::string_view text, size_t idx, IMenuNode* node) Menu::ItemView::ItemView(ViewResources& res, Menu& menu, std::string_view text, size_t idx, IMenuNode* node)
: View(res, menu), m_menu(menu), m_idx(idx), m_node(node) : View(res, menu), m_menu(menu), m_idx(idx), m_node(node) {
{ commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool {
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool buildResources(ctx, res);
{ return true;
buildResources(ctx, res); });
return true; m_textView.reset(new specter::TextView(res, *this, res.m_mainFont));
}); m_textView->typesetGlyphs(text, res.themeData().uiText());
m_textView.reset(new specter::TextView(res, *this, res.m_mainFont));
m_textView->typesetGlyphs(text, res.themeData().uiText());
} }
void Menu::setVerts(int width, int height, float pf) void Menu::setVerts(int width, int height, float pf) {
{ m_verts[0].m_pos.assign(0, height - m_cTop - pf, 0);
m_verts[0].m_pos.assign(0, height-m_cTop-pf, 0); m_verts[1].m_pos.assign(0, 0, 0);
m_verts[1].m_pos.assign(0, 0, 0); m_verts[2].m_pos.assign(width, height - m_cTop - pf, 0);
m_verts[2].m_pos.assign(width, height-m_cTop-pf, 0); m_verts[3].m_pos.assign(width, 0, 0);
m_verts[3].m_pos.assign(width, 0, 0);
m_verts[4].m_pos.assign(0, height, 0); m_verts[4].m_pos.assign(0, height, 0);
m_verts[5].m_pos.assign(0, height-m_cTop+pf, 0); m_verts[5].m_pos.assign(0, height - m_cTop + pf, 0);
m_verts[6].m_pos.assign(width, height, 0); m_verts[6].m_pos.assign(width, height, 0);
m_verts[7].m_pos.assign(width, height-m_cTop+pf, 0); m_verts[7].m_pos.assign(width, height - m_cTop + pf, 0);
m_vertsBinding.load<decltype(m_verts)>(m_verts); m_vertsBinding.load<decltype(m_verts)>(m_verts);
} }
void Menu::ContentView::setHighlightedItem(size_t idx) void Menu::ContentView::setHighlightedItem(size_t idx) {
{ if (idx == -1) {
if (idx == -1) m_highlightedItem = -1;
{ return;
m_highlightedItem = -1; }
return; ViewChild<std::unique_ptr<ItemView>>& vc = m_menu.m_items[idx];
}
ViewChild<std::unique_ptr<ItemView>>& vc = m_menu.m_items[idx];
if (!vc.m_view) if (!vc.m_view) {
{ m_highlightedItem = -1;
m_highlightedItem = -1; return;
return; }
}
m_highlightedItem = idx; m_highlightedItem = idx;
const boo::SWindowRect& bgRect = subRect(); const boo::SWindowRect& bgRect = subRect();
const boo::SWindowRect& itemRect = vc.m_view->subRect(); const boo::SWindowRect& itemRect = vc.m_view->subRect();
int y = itemRect.location[1] - bgRect.location[1]; int y = itemRect.location[1] - bgRect.location[1];
m_hlVerts[0].m_pos.assign(0, y+itemRect.size[1], 0); m_hlVerts[0].m_pos.assign(0, y + itemRect.size[1], 0);
m_hlVerts[1].m_pos.assign(0, y, 0); m_hlVerts[1].m_pos.assign(0, y, 0);
m_hlVerts[2].m_pos.assign(itemRect.size[0], y+itemRect.size[1], 0); m_hlVerts[2].m_pos.assign(itemRect.size[0], y + itemRect.size[1], 0);
m_hlVerts[3].m_pos.assign(itemRect.size[0], y, 0); m_hlVerts[3].m_pos.assign(itemRect.size[0], y, 0);
m_hlVertsBinding.load<decltype(m_hlVerts)>(m_hlVerts); m_hlVertsBinding.load<decltype(m_hlVerts)>(m_hlVerts);
} }
void Menu::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) void Menu::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
{ m_scroll.mouseDown(coord, button, mod);
m_scroll.mouseDown(coord, button, mod);
} }
void Menu::ContentView::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) void Menu::ContentView::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
{ for (ViewChild<std::unique_ptr<ItemView>>& v : m_menu.m_items)
for (ViewChild<std::unique_ptr<ItemView>>& v : m_menu.m_items) v.mouseDown(coord, button, mod);
v.mouseDown(coord, button, mod);
} }
void Menu::ItemView::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) void Menu::ItemView::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {}
{
void Menu::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
m_scroll.mouseUp(coord, button, mod);
if (m_deferredActivation) {
IMenuNode* node = m_deferredActivation;
m_deferredActivation = nullptr;
node->activated(coord);
}
} }
void Menu::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) void Menu::ContentView::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
{ for (ViewChild<std::unique_ptr<ItemView>>& v : m_menu.m_items)
m_scroll.mouseUp(coord, button, mod); v.mouseUp(coord, button, mod);
if (m_deferredActivation)
{
IMenuNode* node = m_deferredActivation;
m_deferredActivation = nullptr;
node->activated(coord);
}
} }
void Menu::ContentView::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) void Menu::ItemView::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
{ if (m_menu.m_content->m_highlightedItem == m_idx)
for (ViewChild<std::unique_ptr<ItemView>>& v : m_menu.m_items) m_menu.m_deferredActivation = m_node;
v.mouseUp(coord, button, mod);
} }
void Menu::ItemView::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) void Menu::mouseMove(const boo::SWindowCoord& coord) { m_scroll.mouseMove(coord); }
{
if (m_menu.m_content->m_highlightedItem == m_idx) void Menu::ContentView::mouseMove(const boo::SWindowCoord& coord) {
m_menu.m_deferredActivation = m_node; for (ViewChild<std::unique_ptr<ItemView>>& v : m_menu.m_items)
v.mouseMove(coord);
} }
void Menu::mouseMove(const boo::SWindowCoord& coord) void Menu::ItemView::mouseEnter(const boo::SWindowCoord& coord) { m_menu.m_content->setHighlightedItem(m_idx); }
{
m_scroll.mouseMove(coord); void Menu::mouseLeave(const boo::SWindowCoord& coord) { m_scroll.mouseLeave(coord); }
void Menu::ContentView::mouseLeave(const boo::SWindowCoord& coord) {
for (ViewChild<std::unique_ptr<ItemView>>& v : m_menu.m_items)
v.mouseLeave(coord);
} }
void Menu::ContentView::mouseMove(const boo::SWindowCoord& coord) void Menu::ItemView::mouseLeave(const boo::SWindowCoord& coord) { m_menu.m_content->unsetHighlightedItem(m_idx); }
{
for (ViewChild<std::unique_ptr<ItemView>>& v : m_menu.m_items)
v.mouseMove(coord);
}
void Menu::ItemView::mouseEnter(const boo::SWindowCoord& coord) void Menu::scroll(const boo::SWindowCoord& coord, const boo::SScrollDelta& scroll) { m_scroll.scroll(coord, scroll); }
{
m_menu.m_content->setHighlightedItem(m_idx);
}
void Menu::mouseLeave(const boo::SWindowCoord& coord) void Menu::think() { m_scroll.m_view->think(); }
{
m_scroll.mouseLeave(coord);
}
void Menu::ContentView::mouseLeave(const boo::SWindowCoord& coord) void Menu::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) {
{ float pf = rootView().viewRes().pixelFactor();
for (ViewChild<std::unique_ptr<ItemView>>& v : m_menu.m_items) boo::SWindowRect rect = sub;
v.mouseLeave(coord); rect.size[0] = m_cWidth;
} if (rect.location[1] - m_cHeight < 0) {
rect.location[1] += ROW_HEIGHT * pf;
rect.size[1] = std::min(root.size[1] - rect.location[1], m_cHeight);
} else {
rect.location[1] -= m_cHeight;
rect.size[1] = m_cHeight;
}
void Menu::ItemView::mouseLeave(const boo::SWindowCoord& coord) View::resized(root, rect);
{ m_scroll.m_view->resized(root, rect);
m_menu.m_content->unsetHighlightedItem(m_idx); setVerts(rect.size[0], rect.size[1], pf);
}
void Menu::scroll(const boo::SWindowCoord& coord, const boo::SScrollDelta& scroll) rect.location[0] += 5 * pf;
{ rect.location[1] += rect.size[1] - (ROW_HEIGHT + ITEM_MARGIN - 5) * pf;
m_scroll.scroll(coord, scroll); rect.size[0] = m_headText->nominalWidth();
} rect.size[1] = m_headText->nominalHeight();
m_headText->resized(root, rect);
void Menu::think()
{
m_scroll.m_view->think();
}
void Menu::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub)
{
float pf = rootView().viewRes().pixelFactor();
boo::SWindowRect rect = sub;
rect.size[0] = m_cWidth;
if (rect.location[1] - m_cHeight < 0)
{
rect.location[1] += ROW_HEIGHT*pf;
rect.size[1] = std::min(root.size[1] - rect.location[1], m_cHeight);
}
else
{
rect.location[1] -= m_cHeight;
rect.size[1] = m_cHeight;
}
View::resized(root, rect);
m_scroll.m_view->resized(root, rect);
setVerts(rect.size[0], rect.size[1], pf);
rect.location[0] += 5*pf;
rect.location[1] += rect.size[1] - (ROW_HEIGHT + ITEM_MARGIN - 5)*pf;
rect.size[0] = m_headText->nominalWidth();
rect.size[1] = m_headText->nominalHeight();
m_headText->resized(root, rect);
} }
void Menu::ContentView::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub, void Menu::ContentView::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub,
const boo::SWindowRect& scissor) const boo::SWindowRect& scissor) {
{ View::resized(root, sub);
View::resized(root, sub); float pf = rootView().viewRes().pixelFactor();
float pf = rootView().viewRes().pixelFactor(); m_scissorRect = scissor;
m_scissorRect = scissor; boo::SWindowRect itemRect = sub;
boo::SWindowRect itemRect = sub; itemRect.size[0] = m_menu.m_cWidth;
itemRect.size[0] = m_menu.m_cWidth; itemRect.size[1] = ROW_HEIGHT * pf;
itemRect.size[1] = ROW_HEIGHT*pf; itemRect.location[1] += sub.size[1] - m_menu.m_cTop + ITEM_MARGIN * pf;
itemRect.location[1] += sub.size[1] - m_menu.m_cTop + ITEM_MARGIN*pf; int itemAdv = (ROW_HEIGHT + ITEM_MARGIN * 2) * pf;
int itemAdv = (ROW_HEIGHT + ITEM_MARGIN*2) * pf; for (ViewChild<std::unique_ptr<ItemView>>& c : m_menu.m_items) {
for (ViewChild<std::unique_ptr<ItemView>>& c : m_menu.m_items) itemRect.location[1] -= itemAdv;
{ if (c.m_view)
itemRect.location[1] -= itemAdv; c.m_view->resized(root, itemRect);
if (c.m_view) }
c.m_view->resized(root, itemRect);
}
} }
void Menu::ItemView::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) void Menu::ItemView::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) {
{ View::resized(root, sub);
View::resized(root, sub); float pf = rootView().viewRes().pixelFactor();
float pf = rootView().viewRes().pixelFactor(); boo::SWindowRect textRect = sub;
boo::SWindowRect textRect = sub; textRect.location[0] += 5 * pf;
textRect.location[0] += 5*pf; textRect.location[1] += 5 * pf;
textRect.location[1] += 5*pf; m_textView->resized(root, textRect);
m_textView->resized(root, textRect);
} }
void Menu::draw(boo::IGraphicsCommandQueue* gfxQ) void Menu::draw(boo::IGraphicsCommandQueue* gfxQ) {
{ View::draw(gfxQ);
View::draw(gfxQ); gfxQ->setShaderDataBinding(m_vertsBinding);
gfxQ->setShaderDataBinding(m_vertsBinding); gfxQ->draw(0, 4);
m_scroll.m_view->draw(gfxQ);
gfxQ->setShaderDataBinding(m_vertsBinding);
gfxQ->draw(4, 4);
m_headText->draw(gfxQ);
}
void Menu::ContentView::draw(boo::IGraphicsCommandQueue* gfxQ) {
View::draw(gfxQ);
gfxQ->setScissor(m_scissorRect);
if (m_highlightedItem != -1) {
gfxQ->setShaderDataBinding(m_hlVertsBinding);
gfxQ->draw(0, 4); gfxQ->draw(0, 4);
m_scroll.m_view->draw(gfxQ); }
gfxQ->setShaderDataBinding(m_vertsBinding); for (ViewChild<std::unique_ptr<ItemView>>& c : m_menu.m_items)
gfxQ->draw(4, 4); if (c.m_view)
m_headText->draw(gfxQ); c.m_view->draw(gfxQ);
gfxQ->setScissor(rootView().subRect());
} }
void Menu::ContentView::draw(boo::IGraphicsCommandQueue* gfxQ) void Menu::ItemView::draw(boo::IGraphicsCommandQueue* gfxQ) {
{ View::draw(gfxQ);
View::draw(gfxQ); m_textView->draw(gfxQ);
gfxQ->setScissor(m_scissorRect);
if (m_highlightedItem != -1)
{
gfxQ->setShaderDataBinding(m_hlVertsBinding);
gfxQ->draw(0, 4);
}
for (ViewChild<std::unique_ptr<ItemView>>& c : m_menu.m_items)
if (c.m_view)
c.m_view->draw(gfxQ);
gfxQ->setScissor(rootView().subRect());
} }
void Menu::ItemView::draw(boo::IGraphicsCommandQueue* gfxQ) } // namespace specter
{
View::draw(gfxQ);
m_textView->draw(gfxQ);
}
}

View File

@ -3,107 +3,93 @@
#include "specter/RootView.hpp" #include "specter/RootView.hpp"
#include "specter/Menu.hpp" #include "specter/Menu.hpp"
namespace specter namespace specter {
{
MessageWindow::MessageWindow(ViewResources& res, View& parentView, MessageWindow::MessageWindow(ViewResources& res, View& parentView, Type type, std::string_view message,
Type type, std::string_view message, std::function<void(bool)> func)
std::function<void (bool)> func)
: ModalWindow(res, parentView, RectangleConstraint(), : ModalWindow(res, parentView, RectangleConstraint(),
type==Type::ErrorOk ? res.themeData().splashErrorBackground() : res.themeData().splashBackground()), type == Type::ErrorOk ? res.themeData().splashErrorBackground() : res.themeData().splashBackground())
m_type(type), m_func(func), , m_type(type)
m_okBind(*this, rootView().viewManager().translateOr("ok", "OK")), , m_func(func)
m_cancelBind(*this, rootView().viewManager().translateOr("cancel", "Cancel")) , m_okBind(*this, rootView().viewManager().translateOr("ok", "OK"))
{ , m_cancelBind(*this, rootView().viewManager().translateOr("cancel", "Cancel")) {
m_text.reset(new MultiLineTextView(res, *this, res.m_mainFont, TextView::Alignment::Center)); m_text.reset(new MultiLineTextView(res, *this, res.m_mainFont, TextView::Alignment::Center));
m_text->typesetGlyphs(message, res.themeData().uiText(), 380 * res.pixelFactor()); m_text->typesetGlyphs(message, res.themeData().uiText(), 380 * res.pixelFactor());
constraint() = RectangleConstraint(400 * res.pixelFactor(), 80 * res.pixelFactor() + m_text->nominalHeight()); constraint() = RectangleConstraint(400 * res.pixelFactor(), 80 * res.pixelFactor() + m_text->nominalHeight());
m_ok.m_view.reset(new Button(res, *this, &m_okBind, m_okBind.m_name, nullptr, m_ok.m_view.reset(new Button(res, *this, &m_okBind, m_okBind.m_name, nullptr, Button::Style::Block,
Button::Style::Block, zeus::CColor::skWhite, zeus::CColor::skWhite, RectangleConstraint(150 * res.pixelFactor())));
RectangleConstraint(150 * res.pixelFactor()))); if (type == Type::ConfirmOkCancel)
if (type == Type::ConfirmOkCancel) m_cancel.m_view.reset(new Button(res, *this, &m_cancelBind, m_cancelBind.m_name, nullptr, Button::Style::Block,
m_cancel.m_view.reset(new Button(res, *this, &m_cancelBind, m_cancelBind.m_name, nullptr, zeus::CColor::skWhite, RectangleConstraint(150 * res.pixelFactor())));
Button::Style::Block, zeus::CColor::skWhite,
RectangleConstraint(150 * res.pixelFactor())));
updateContentOpacity(0.0); updateContentOpacity(0.0);
} }
void MessageWindow::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mods) void MessageWindow::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mods) {
{ if (closed() || skipBuildInAnimation())
if (closed() || skipBuildInAnimation()) return;
return; m_ok.mouseDown(coord, button, mods);
m_ok.mouseDown(coord, button, mods); m_cancel.mouseDown(coord, button, mods);
m_cancel.mouseDown(coord, button, mods);
} }
void MessageWindow::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mods) void MessageWindow::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mods) {
{ if (closed())
if (closed()) return;
return; m_ok.mouseUp(coord, button, mods);
m_ok.mouseUp(coord, button, mods); m_cancel.mouseUp(coord, button, mods);
m_cancel.mouseUp(coord, button, mods);
} }
void MessageWindow::mouseMove(const boo::SWindowCoord& coord) void MessageWindow::mouseMove(const boo::SWindowCoord& coord) {
{ if (closed())
if (closed()) return;
return; m_ok.mouseMove(coord);
m_ok.mouseMove(coord); m_cancel.mouseMove(coord);
m_cancel.mouseMove(coord);
} }
void MessageWindow::mouseEnter(const boo::SWindowCoord& coord) void MessageWindow::mouseEnter(const boo::SWindowCoord& coord) {
{ if (closed())
if (closed()) return;
return; m_ok.mouseEnter(coord);
m_ok.mouseEnter(coord); m_cancel.mouseEnter(coord);
m_cancel.mouseEnter(coord);
} }
void MessageWindow::mouseLeave(const boo::SWindowCoord& coord) void MessageWindow::mouseLeave(const boo::SWindowCoord& coord) {
{ if (closed())
if (closed()) return;
return; m_ok.mouseLeave(coord);
m_ok.mouseLeave(coord); m_cancel.mouseLeave(coord);
m_cancel.mouseLeave(coord);
} }
void MessageWindow::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) void MessageWindow::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) {
{ ModalWindow::resized(root, sub);
ModalWindow::resized(root, sub); boo::SWindowRect buttonRect = subRect();
boo::SWindowRect buttonRect = subRect(); float pf = rootView().viewRes().pixelFactor();
float pf = rootView().viewRes().pixelFactor(); buttonRect.location[1] += 20 * pf;
buttonRect.location[1] += 20 * pf; buttonRect.size[0] = m_ok.m_view->nominalWidth();
buttonRect.size[0] = m_ok.m_view->nominalWidth(); buttonRect.size[1] = m_ok.m_view->nominalHeight();
buttonRect.size[1] = m_ok.m_view->nominalHeight(); if (m_type == Type::ConfirmOkCancel) {
if (m_type == Type::ConfirmOkCancel) buttonRect.location[0] += 45 * pf;
{ m_ok.m_view->resized(root, buttonRect);
buttonRect.location[0] += 45 * pf; buttonRect.location[0] += 160 * pf;
m_ok.m_view->resized(root, buttonRect); m_cancel.m_view->resized(root, buttonRect);
buttonRect.location[0] += 160 * pf; } else {
m_cancel.m_view->resized(root, buttonRect); buttonRect.location[0] += 125 * pf;
} m_ok.m_view->resized(root, buttonRect);
else }
{
buttonRect.location[0] += 125 * pf;
m_ok.m_view->resized(root, buttonRect);
}
boo::SWindowRect textRect = subRect(); boo::SWindowRect textRect = subRect();
textRect.location[0] += 200 * pf; textRect.location[0] += 200 * pf;
textRect.location[1] += 65 * pf; textRect.location[1] += 65 * pf;
m_text->resized(root, textRect); m_text->resized(root, textRect);
} }
void MessageWindow::draw(boo::IGraphicsCommandQueue* gfxQ) void MessageWindow::draw(boo::IGraphicsCommandQueue* gfxQ) {
{ ModalWindow::draw(gfxQ);
ModalWindow::draw(gfxQ); m_text->draw(gfxQ);
m_text->draw(gfxQ); m_ok.m_view->draw(gfxQ);
m_ok.m_view->draw(gfxQ); if (m_type == Type::ConfirmOkCancel)
if (m_type == Type::ConfirmOkCancel) m_cancel.m_view->draw(gfxQ);
m_cancel.m_view->draw(gfxQ);
} }
} } // namespace specter

View File

@ -2,8 +2,7 @@
#include "specter/ViewResources.hpp" #include "specter/ViewResources.hpp"
#include "specter/RootView.hpp" #include "specter/RootView.hpp"
namespace specter namespace specter {
{
#define WIRE_START 0 #define WIRE_START 0
#define WIRE_FRAMES 40 #define WIRE_FRAMES 40
@ -16,483 +15,451 @@ namespace specter
#define CONTENT_MARGIN 10 #define CONTENT_MARGIN 10
#define WINDOW_MIN_DIM 16 #define WINDOW_MIN_DIM 16
void ModalWindow::setLineVerts(int width, int height, float pf, float t) void ModalWindow::setLineVerts(int width, int height, float pf, float t) {
{ std::pair<int, int> margin = m_cornersOutline[0]->queryGlyphDimensions(0);
std::pair<int,int> margin = m_cornersOutline[0]->queryGlyphDimensions(0); float t1 = zeus::clamp(0.f, t * 2.f, 1.f);
float t1 = zeus::clamp(0.f, t * 2.f, 1.f); float t2 = zeus::clamp(0.f, t * 2.f - 1.f, 1.f);
float t2 = zeus::clamp(0.f, t * 2.f - 1.f, 1.f);
float lineLeft = 0; float lineLeft = 0;
float lineRight = pf*LINE_WIDTH; float lineRight = pf * LINE_WIDTH;
float lineTop = height-margin.second; float lineTop = height - margin.second;
float lineBottom = margin.second; float lineBottom = margin.second;
m_verts.lineVerts[0].m_pos.assign(lineLeft, lineTop, 0); m_verts.lineVerts[0].m_pos.assign(lineLeft, lineTop, 0);
m_verts.lineVerts[1].m_pos = zeus::CVector3f::lerp({lineLeft, lineTop, 0}, {lineLeft, lineBottom, 0}, t1); m_verts.lineVerts[1].m_pos = zeus::CVector3f::lerp({lineLeft, lineTop, 0}, {lineLeft, lineBottom, 0}, t1);
m_verts.lineVerts[2].m_pos.assign(lineRight, lineTop, 0); m_verts.lineVerts[2].m_pos.assign(lineRight, lineTop, 0);
m_verts.lineVerts[3].m_pos = zeus::CVector3f::lerp({lineRight, lineTop, 0}, {lineRight, lineBottom, 0}, t1); m_verts.lineVerts[3].m_pos = zeus::CVector3f::lerp({lineRight, lineTop, 0}, {lineRight, lineBottom, 0}, t1);
m_verts.lineVerts[4].m_pos = m_verts.lineVerts[3].m_pos; m_verts.lineVerts[4].m_pos = m_verts.lineVerts[3].m_pos;
lineLeft = margin.first; lineLeft = margin.first;
lineRight = width-margin.first; lineRight = width - margin.first;
lineTop = height; lineTop = height;
lineBottom = height-pf*LINE_WIDTH; lineBottom = height - pf * LINE_WIDTH;
m_verts.lineVerts[5].m_pos.assign(lineLeft, lineTop, 0); m_verts.lineVerts[5].m_pos.assign(lineLeft, lineTop, 0);
m_verts.lineVerts[6].m_pos = m_verts.lineVerts[5].m_pos; m_verts.lineVerts[6].m_pos = m_verts.lineVerts[5].m_pos;
m_verts.lineVerts[7].m_pos.assign(lineLeft, lineBottom, 0); m_verts.lineVerts[7].m_pos.assign(lineLeft, lineBottom, 0);
m_verts.lineVerts[8].m_pos = zeus::CVector3f::lerp({lineLeft, lineTop, 0}, {lineRight, lineTop, 0}, t1); m_verts.lineVerts[8].m_pos = zeus::CVector3f::lerp({lineLeft, lineTop, 0}, {lineRight, lineTop, 0}, t1);
m_verts.lineVerts[9].m_pos = zeus::CVector3f::lerp({lineLeft, lineBottom, 0}, {lineRight, lineBottom, 0}, t1); m_verts.lineVerts[9].m_pos = zeus::CVector3f::lerp({lineLeft, lineBottom, 0}, {lineRight, lineBottom, 0}, t1);
m_verts.lineVerts[10].m_pos = m_verts.lineVerts[9].m_pos; m_verts.lineVerts[10].m_pos = m_verts.lineVerts[9].m_pos;
lineLeft = width-pf*LINE_WIDTH; lineLeft = width - pf * LINE_WIDTH;
lineRight = width; lineRight = width;
lineTop = height-margin.second; lineTop = height - margin.second;
lineBottom = margin.second; lineBottom = margin.second;
m_verts.lineVerts[11].m_pos.assign(lineLeft, lineTop, 0); m_verts.lineVerts[11].m_pos.assign(lineLeft, lineTop, 0);
m_verts.lineVerts[12].m_pos = m_verts.lineVerts[11].m_pos; m_verts.lineVerts[12].m_pos = m_verts.lineVerts[11].m_pos;
m_verts.lineVerts[13].m_pos = zeus::CVector3f::lerp({lineLeft, lineTop, 0}, {lineLeft, lineBottom, 0}, t2); m_verts.lineVerts[13].m_pos = zeus::CVector3f::lerp({lineLeft, lineTop, 0}, {lineLeft, lineBottom, 0}, t2);
m_verts.lineVerts[14].m_pos.assign(lineRight, lineTop, 0); m_verts.lineVerts[14].m_pos.assign(lineRight, lineTop, 0);
m_verts.lineVerts[15].m_pos = zeus::CVector3f::lerp({lineRight, lineTop, 0}, {lineRight, lineBottom, 0}, t2); m_verts.lineVerts[15].m_pos = zeus::CVector3f::lerp({lineRight, lineTop, 0}, {lineRight, lineBottom, 0}, t2);
m_verts.lineVerts[16].m_pos = m_verts.lineVerts[15].m_pos; m_verts.lineVerts[16].m_pos = m_verts.lineVerts[15].m_pos;
lineLeft = margin.first; lineLeft = margin.first;
lineRight = width-margin.first; lineRight = width - margin.first;
lineTop = pf*LINE_WIDTH; lineTop = pf * LINE_WIDTH;
lineBottom = 0; lineBottom = 0;
m_verts.lineVerts[17].m_pos.assign(lineLeft, lineTop, 0); m_verts.lineVerts[17].m_pos.assign(lineLeft, lineTop, 0);
m_verts.lineVerts[18].m_pos = m_verts.lineVerts[17].m_pos; m_verts.lineVerts[18].m_pos = m_verts.lineVerts[17].m_pos;
m_verts.lineVerts[19].m_pos.assign(lineLeft, lineBottom, 0); m_verts.lineVerts[19].m_pos.assign(lineLeft, lineBottom, 0);
m_verts.lineVerts[20].m_pos = zeus::CVector3f::lerp({lineLeft, lineTop, 0}, {lineRight, lineTop, 0}, t2); m_verts.lineVerts[20].m_pos = zeus::CVector3f::lerp({lineLeft, lineTop, 0}, {lineRight, lineTop, 0}, t2);
m_verts.lineVerts[21].m_pos = zeus::CVector3f::lerp({lineLeft, lineBottom, 0}, {lineRight, lineBottom, 0}, t2); m_verts.lineVerts[21].m_pos = zeus::CVector3f::lerp({lineLeft, lineBottom, 0}, {lineRight, lineBottom, 0}, t2);
} }
void ModalWindow::setLineVertsOut(int width, int height, float pf, float t) void ModalWindow::setLineVertsOut(int width, int height, float pf, float t) {
{ std::pair<int, int> margin = m_cornersOutline[0]->queryGlyphDimensions(0);
std::pair<int,int> margin = m_cornersOutline[0]->queryGlyphDimensions(0); float t1 = zeus::clamp(0.f, t * 2.f - 1.f, 1.f);
float t1 = zeus::clamp(0.f, t * 2.f - 1.f, 1.f); float t2 = zeus::clamp(0.f, t * 2.f, 1.f);
float t2 = zeus::clamp(0.f, t * 2.f, 1.f);
float lineLeft = 0; float lineLeft = 0;
float lineRight = pf*LINE_WIDTH; float lineRight = pf * LINE_WIDTH;
float lineTop = height-margin.second; float lineTop = height - margin.second;
float lineBottom = margin.second; float lineBottom = margin.second;
m_verts.lineVerts[0].m_pos = zeus::CVector3f::lerp({lineLeft, lineBottom, 0}, {lineLeft, lineTop, 0}, t1); m_verts.lineVerts[0].m_pos = zeus::CVector3f::lerp({lineLeft, lineBottom, 0}, {lineLeft, lineTop, 0}, t1);
m_verts.lineVerts[1].m_pos.assign(lineLeft, lineBottom, 0); m_verts.lineVerts[1].m_pos.assign(lineLeft, lineBottom, 0);
m_verts.lineVerts[2].m_pos = zeus::CVector3f::lerp({lineRight, lineBottom, 0}, {lineRight, lineTop, 0}, t1); m_verts.lineVerts[2].m_pos = zeus::CVector3f::lerp({lineRight, lineBottom, 0}, {lineRight, lineTop, 0}, t1);
m_verts.lineVerts[3].m_pos.assign(lineRight, lineBottom, 0); m_verts.lineVerts[3].m_pos.assign(lineRight, lineBottom, 0);
m_verts.lineVerts[4].m_pos = m_verts.lineVerts[3].m_pos; m_verts.lineVerts[4].m_pos = m_verts.lineVerts[3].m_pos;
lineLeft = margin.first; lineLeft = margin.first;
lineRight = width-margin.first; lineRight = width - margin.first;
lineTop = height; lineTop = height;
lineBottom = height-pf*LINE_WIDTH; lineBottom = height - pf * LINE_WIDTH;
m_verts.lineVerts[5].m_pos = zeus::CVector3f::lerp({lineRight, lineTop, 0}, {lineLeft, lineTop, 0}, t1); m_verts.lineVerts[5].m_pos = zeus::CVector3f::lerp({lineRight, lineTop, 0}, {lineLeft, lineTop, 0}, t1);
m_verts.lineVerts[6].m_pos = m_verts.lineVerts[5].m_pos; m_verts.lineVerts[6].m_pos = m_verts.lineVerts[5].m_pos;
m_verts.lineVerts[7].m_pos = zeus::CVector3f::lerp({lineRight, lineBottom, 0}, {lineLeft, lineBottom, 0}, t1); m_verts.lineVerts[7].m_pos = zeus::CVector3f::lerp({lineRight, lineBottom, 0}, {lineLeft, lineBottom, 0}, t1);
m_verts.lineVerts[8].m_pos.assign(lineRight, lineTop, 0); m_verts.lineVerts[8].m_pos.assign(lineRight, lineTop, 0);
m_verts.lineVerts[9].m_pos.assign(lineRight, lineBottom, 0); m_verts.lineVerts[9].m_pos.assign(lineRight, lineBottom, 0);
m_verts.lineVerts[10].m_pos = m_verts.lineVerts[9].m_pos; m_verts.lineVerts[10].m_pos = m_verts.lineVerts[9].m_pos;
lineLeft = width-pf*LINE_WIDTH; lineLeft = width - pf * LINE_WIDTH;
lineRight = width; lineRight = width;
lineTop = height-margin.second; lineTop = height - margin.second;
lineBottom = margin.second; lineBottom = margin.second;
m_verts.lineVerts[11].m_pos = zeus::CVector3f::lerp({lineLeft, lineBottom, 0}, {lineLeft, lineTop, 0}, t2); m_verts.lineVerts[11].m_pos = zeus::CVector3f::lerp({lineLeft, lineBottom, 0}, {lineLeft, lineTop, 0}, t2);
m_verts.lineVerts[12].m_pos = m_verts.lineVerts[11].m_pos; m_verts.lineVerts[12].m_pos = m_verts.lineVerts[11].m_pos;
m_verts.lineVerts[13].m_pos.assign(lineLeft, lineBottom, 0); m_verts.lineVerts[13].m_pos.assign(lineLeft, lineBottom, 0);
m_verts.lineVerts[14].m_pos = zeus::CVector3f::lerp({lineRight, lineBottom, 0}, {lineRight, lineTop, 0}, t2); m_verts.lineVerts[14].m_pos = zeus::CVector3f::lerp({lineRight, lineBottom, 0}, {lineRight, lineTop, 0}, t2);
m_verts.lineVerts[15].m_pos.assign(lineRight, lineBottom, 0); m_verts.lineVerts[15].m_pos.assign(lineRight, lineBottom, 0);
m_verts.lineVerts[16].m_pos = m_verts.lineVerts[15].m_pos; m_verts.lineVerts[16].m_pos = m_verts.lineVerts[15].m_pos;
lineLeft = margin.first; lineLeft = margin.first;
lineRight = width-margin.first; lineRight = width - margin.first;
lineTop = pf*LINE_WIDTH; lineTop = pf * LINE_WIDTH;
lineBottom = 0; lineBottom = 0;
m_verts.lineVerts[17].m_pos = zeus::CVector3f::lerp({lineRight, lineTop, 0}, {lineLeft, lineTop, 0}, t2); m_verts.lineVerts[17].m_pos = zeus::CVector3f::lerp({lineRight, lineTop, 0}, {lineLeft, lineTop, 0}, t2);
m_verts.lineVerts[18].m_pos = m_verts.lineVerts[17].m_pos; m_verts.lineVerts[18].m_pos = m_verts.lineVerts[17].m_pos;
m_verts.lineVerts[19].m_pos = zeus::CVector3f::lerp({lineRight, lineBottom, 0}, {lineLeft, lineBottom, 0}, t2); m_verts.lineVerts[19].m_pos = zeus::CVector3f::lerp({lineRight, lineBottom, 0}, {lineLeft, lineBottom, 0}, t2);
m_verts.lineVerts[20].m_pos.assign(lineRight, lineTop, 0); m_verts.lineVerts[20].m_pos.assign(lineRight, lineTop, 0);
m_verts.lineVerts[21].m_pos.assign(lineRight, lineBottom, 0); m_verts.lineVerts[21].m_pos.assign(lineRight, lineBottom, 0);
} }
void ModalWindow::setLineColors(float t) void ModalWindow::setLineColors(float t) {
{ float t1 = zeus::clamp(0.f, t * 2.f, 1.f);
float t1 = zeus::clamp(0.f, t * 2.f, 1.f); float t2 = zeus::clamp(0.f, t * 2.f - 1.f, 1.f);
float t2 = zeus::clamp(0.f, t * 2.f - 1.f, 1.f); float t3 = zeus::clamp(0.f, t * 2.f - 2.f, 1.f);
float t3 = zeus::clamp(0.f, t * 2.f - 2.f, 1.f);
zeus::CColor c1 = zeus::CColor::lerp(m_line1, m_line2, t1); zeus::CColor c1 = zeus::CColor::lerp(m_line1, m_line2, t1);
zeus::CColor c2 = zeus::CColor::lerp(m_line1, m_line2, t2); zeus::CColor c2 = zeus::CColor::lerp(m_line1, m_line2, t2);
zeus::CColor c3 = zeus::CColor::lerp(m_line1, m_line2, t3); zeus::CColor c3 = zeus::CColor::lerp(m_line1, m_line2, t3);
m_cornersOutline[0]->colorGlyphs(c1); m_cornersOutline[0]->colorGlyphs(c1);
if (t < 0.5) if (t < 0.5) {
{ m_cornersOutline[1]->colorGlyphs(zeus::CColor::skClear);
m_cornersOutline[1]->colorGlyphs(zeus::CColor::skClear); m_cornersOutline[2]->colorGlyphs(zeus::CColor::skClear);
m_cornersOutline[2]->colorGlyphs(zeus::CColor::skClear); m_cornersOutline[3]->colorGlyphs(zeus::CColor::skClear);
m_cornersOutline[3]->colorGlyphs(zeus::CColor::skClear); } else if (t < 1.0) {
} m_cornersOutline[1]->colorGlyphs(c2);
else if (t < 1.0) m_cornersOutline[2]->colorGlyphs(zeus::CColor::skClear);
{ m_cornersOutline[3]->colorGlyphs(c2);
m_cornersOutline[1]->colorGlyphs(c2); } else {
m_cornersOutline[2]->colorGlyphs(zeus::CColor::skClear); m_cornersOutline[1]->colorGlyphs(c2);
m_cornersOutline[3]->colorGlyphs(c2); m_cornersOutline[2]->colorGlyphs(c3);
} m_cornersOutline[3]->colorGlyphs(c2);
else }
{
m_cornersOutline[1]->colorGlyphs(c2);
m_cornersOutline[2]->colorGlyphs(c3);
m_cornersOutline[3]->colorGlyphs(c2);
}
m_verts.lineVerts[0].m_color = c1; m_verts.lineVerts[0].m_color = c1;
m_verts.lineVerts[1].m_color = c2; m_verts.lineVerts[1].m_color = c2;
m_verts.lineVerts[2].m_color = m_verts.lineVerts[0].m_color; m_verts.lineVerts[2].m_color = m_verts.lineVerts[0].m_color;
m_verts.lineVerts[3].m_color = m_verts.lineVerts[1].m_color; m_verts.lineVerts[3].m_color = m_verts.lineVerts[1].m_color;
m_verts.lineVerts[4].m_color = m_verts.lineVerts[3].m_color; m_verts.lineVerts[4].m_color = m_verts.lineVerts[3].m_color;
m_verts.lineVerts[5].m_color = c1; m_verts.lineVerts[5].m_color = c1;
m_verts.lineVerts[6].m_color = m_verts.lineVerts[5].m_color; m_verts.lineVerts[6].m_color = m_verts.lineVerts[5].m_color;
m_verts.lineVerts[7].m_color = m_verts.lineVerts[6].m_color; m_verts.lineVerts[7].m_color = m_verts.lineVerts[6].m_color;
m_verts.lineVerts[8].m_color = c2; m_verts.lineVerts[8].m_color = c2;
m_verts.lineVerts[9].m_color = m_verts.lineVerts[8].m_color; m_verts.lineVerts[9].m_color = m_verts.lineVerts[8].m_color;
m_verts.lineVerts[10].m_color = m_verts.lineVerts[9].m_color; m_verts.lineVerts[10].m_color = m_verts.lineVerts[9].m_color;
m_verts.lineVerts[11].m_color = c2; m_verts.lineVerts[11].m_color = c2;
m_verts.lineVerts[12].m_color = m_verts.lineVerts[11].m_color; m_verts.lineVerts[12].m_color = m_verts.lineVerts[11].m_color;
m_verts.lineVerts[13].m_color = c3; m_verts.lineVerts[13].m_color = c3;
m_verts.lineVerts[14].m_color = m_verts.lineVerts[12].m_color; m_verts.lineVerts[14].m_color = m_verts.lineVerts[12].m_color;
m_verts.lineVerts[15].m_color = m_verts.lineVerts[13].m_color; m_verts.lineVerts[15].m_color = m_verts.lineVerts[13].m_color;
m_verts.lineVerts[16].m_color = m_verts.lineVerts[15].m_color; m_verts.lineVerts[16].m_color = m_verts.lineVerts[15].m_color;
m_verts.lineVerts[17].m_color = c2; m_verts.lineVerts[17].m_color = c2;
m_verts.lineVerts[18].m_color = m_verts.lineVerts[17].m_color; m_verts.lineVerts[18].m_color = m_verts.lineVerts[17].m_color;
m_verts.lineVerts[19].m_color = m_verts.lineVerts[18].m_color; m_verts.lineVerts[19].m_color = m_verts.lineVerts[18].m_color;
m_verts.lineVerts[20].m_color = c3; m_verts.lineVerts[20].m_color = c3;
m_verts.lineVerts[21].m_color = m_verts.lineVerts[20].m_color; m_verts.lineVerts[21].m_color = m_verts.lineVerts[20].m_color;
} }
void ModalWindow::setLineColorsOut(float t) void ModalWindow::setLineColorsOut(float t) {
{ float t1 = zeus::clamp(0.f, t * 2.f, 1.f);
float t1 = zeus::clamp(0.f, t * 2.f, 1.f); float t2 = zeus::clamp(0.f, t * 2.f - 1.f, 1.f);
float t2 = zeus::clamp(0.f, t * 2.f - 1.f, 1.f); float t3 = zeus::clamp(0.f, t * 2.f - 2.f, 1.f);
float t3 = zeus::clamp(0.f, t * 2.f - 2.f, 1.f);
zeus::CColor c1 = zeus::CColor::lerp(m_line2Clear, m_line2, t1); zeus::CColor c1 = zeus::CColor::lerp(m_line2Clear, m_line2, t1);
zeus::CColor c2 = zeus::CColor::lerp(m_line2Clear, m_line2, t2); zeus::CColor c2 = zeus::CColor::lerp(m_line2Clear, m_line2, t2);
zeus::CColor c3 = zeus::CColor::lerp(m_line2Clear, m_line2, t3); zeus::CColor c3 = zeus::CColor::lerp(m_line2Clear, m_line2, t3);
m_cornersOutline[2]->colorGlyphs(c1); m_cornersOutline[2]->colorGlyphs(c1);
if (t < 0.5) if (t < 0.5) {
{ m_cornersOutline[1]->colorGlyphs(zeus::CColor::skClear);
m_cornersOutline[1]->colorGlyphs(zeus::CColor::skClear); m_cornersOutline[0]->colorGlyphs(zeus::CColor::skClear);
m_cornersOutline[0]->colorGlyphs(zeus::CColor::skClear); m_cornersOutline[3]->colorGlyphs(zeus::CColor::skClear);
m_cornersOutline[3]->colorGlyphs(zeus::CColor::skClear); } else if (t < 1.0) {
} m_cornersOutline[1]->colorGlyphs(c2);
else if (t < 1.0) m_cornersOutline[0]->colorGlyphs(zeus::CColor::skClear);
{ m_cornersOutline[3]->colorGlyphs(c2);
m_cornersOutline[1]->colorGlyphs(c2); } else {
m_cornersOutline[0]->colorGlyphs(zeus::CColor::skClear); m_cornersOutline[1]->colorGlyphs(c2);
m_cornersOutline[3]->colorGlyphs(c2); m_cornersOutline[0]->colorGlyphs(c3);
} m_cornersOutline[3]->colorGlyphs(c2);
else }
{
m_cornersOutline[1]->colorGlyphs(c2);
m_cornersOutline[0]->colorGlyphs(c3);
m_cornersOutline[3]->colorGlyphs(c2);
}
m_verts.lineVerts[0].m_color = c3; m_verts.lineVerts[0].m_color = c3;
m_verts.lineVerts[1].m_color = c2; m_verts.lineVerts[1].m_color = c2;
m_verts.lineVerts[2].m_color = m_verts.lineVerts[0].m_color; m_verts.lineVerts[2].m_color = m_verts.lineVerts[0].m_color;
m_verts.lineVerts[3].m_color = m_verts.lineVerts[1].m_color; m_verts.lineVerts[3].m_color = m_verts.lineVerts[1].m_color;
m_verts.lineVerts[4].m_color = m_verts.lineVerts[3].m_color; m_verts.lineVerts[4].m_color = m_verts.lineVerts[3].m_color;
m_verts.lineVerts[5].m_color = c3; m_verts.lineVerts[5].m_color = c3;
m_verts.lineVerts[6].m_color = m_verts.lineVerts[5].m_color; m_verts.lineVerts[6].m_color = m_verts.lineVerts[5].m_color;
m_verts.lineVerts[7].m_color = m_verts.lineVerts[6].m_color; m_verts.lineVerts[7].m_color = m_verts.lineVerts[6].m_color;
m_verts.lineVerts[8].m_color = c2; m_verts.lineVerts[8].m_color = c2;
m_verts.lineVerts[9].m_color = m_verts.lineVerts[8].m_color; m_verts.lineVerts[9].m_color = m_verts.lineVerts[8].m_color;
m_verts.lineVerts[10].m_color = m_verts.lineVerts[9].m_color; m_verts.lineVerts[10].m_color = m_verts.lineVerts[9].m_color;
m_verts.lineVerts[11].m_color = c2; m_verts.lineVerts[11].m_color = c2;
m_verts.lineVerts[12].m_color = m_verts.lineVerts[11].m_color; m_verts.lineVerts[12].m_color = m_verts.lineVerts[11].m_color;
m_verts.lineVerts[13].m_color = c1; m_verts.lineVerts[13].m_color = c1;
m_verts.lineVerts[14].m_color = m_verts.lineVerts[12].m_color; m_verts.lineVerts[14].m_color = m_verts.lineVerts[12].m_color;
m_verts.lineVerts[15].m_color = m_verts.lineVerts[13].m_color; m_verts.lineVerts[15].m_color = m_verts.lineVerts[13].m_color;
m_verts.lineVerts[16].m_color = m_verts.lineVerts[15].m_color; m_verts.lineVerts[16].m_color = m_verts.lineVerts[15].m_color;
m_verts.lineVerts[17].m_color = c2; m_verts.lineVerts[17].m_color = c2;
m_verts.lineVerts[18].m_color = m_verts.lineVerts[17].m_color; m_verts.lineVerts[18].m_color = m_verts.lineVerts[17].m_color;
m_verts.lineVerts[19].m_color = m_verts.lineVerts[18].m_color; m_verts.lineVerts[19].m_color = m_verts.lineVerts[18].m_color;
m_verts.lineVerts[20].m_color = c1; m_verts.lineVerts[20].m_color = c1;
m_verts.lineVerts[21].m_color = m_verts.lineVerts[20].m_color; m_verts.lineVerts[21].m_color = m_verts.lineVerts[20].m_color;
} }
void ModalWindow::setFillVerts(int width, int height, float pf) void ModalWindow::setFillVerts(int width, int height, float pf) {
{ std::pair<int, int> margin = m_cornersFilled[0]->queryGlyphDimensions(0);
std::pair<int,int> margin = m_cornersFilled[0]->queryGlyphDimensions(0);
float fillLeft = pf*LINE_WIDTH; float fillLeft = pf * LINE_WIDTH;
float fillRight = width-pf*LINE_WIDTH; float fillRight = width - pf * LINE_WIDTH;
float fillTop = height-margin.second; float fillTop = height - margin.second;
float fillBottom = margin.second; float fillBottom = margin.second;
m_verts.fillVerts[0].m_pos.assign(fillLeft, fillTop, 0); m_verts.fillVerts[0].m_pos.assign(fillLeft, fillTop, 0);
m_verts.fillVerts[1].m_pos.assign(fillLeft, fillBottom, 0); m_verts.fillVerts[1].m_pos.assign(fillLeft, fillBottom, 0);
m_verts.fillVerts[2].m_pos.assign(fillRight, fillTop, 0); m_verts.fillVerts[2].m_pos.assign(fillRight, fillTop, 0);
m_verts.fillVerts[3].m_pos.assign(fillRight, fillBottom, 0); m_verts.fillVerts[3].m_pos.assign(fillRight, fillBottom, 0);
m_verts.fillVerts[4].m_pos = m_verts.fillVerts[3].m_pos; m_verts.fillVerts[4].m_pos = m_verts.fillVerts[3].m_pos;
fillLeft = margin.first; fillLeft = margin.first;
fillRight = width-margin.first; fillRight = width - margin.first;
fillTop = height-pf*LINE_WIDTH; fillTop = height - pf * LINE_WIDTH;
fillBottom = height-margin.second; fillBottom = height - margin.second;
m_verts.fillVerts[5].m_pos.assign(fillLeft, fillTop, 0); m_verts.fillVerts[5].m_pos.assign(fillLeft, fillTop, 0);
m_verts.fillVerts[6].m_pos = m_verts.fillVerts[5].m_pos; m_verts.fillVerts[6].m_pos = m_verts.fillVerts[5].m_pos;
m_verts.fillVerts[7].m_pos.assign(fillLeft, fillBottom, 0); m_verts.fillVerts[7].m_pos.assign(fillLeft, fillBottom, 0);
m_verts.fillVerts[8].m_pos.assign(fillRight, fillTop, 0); m_verts.fillVerts[8].m_pos.assign(fillRight, fillTop, 0);
m_verts.fillVerts[9].m_pos.assign(fillRight, fillBottom, 0); m_verts.fillVerts[9].m_pos.assign(fillRight, fillBottom, 0);
m_verts.fillVerts[10].m_pos = m_verts.fillVerts[9].m_pos; m_verts.fillVerts[10].m_pos = m_verts.fillVerts[9].m_pos;
fillLeft = margin.first; fillLeft = margin.first;
fillRight = width-margin.first; fillRight = width - margin.first;
fillTop = margin.second; fillTop = margin.second;
fillBottom = pf*LINE_WIDTH; fillBottom = pf * LINE_WIDTH;
m_verts.fillVerts[11].m_pos.assign(fillLeft, fillTop, 0); m_verts.fillVerts[11].m_pos.assign(fillLeft, fillTop, 0);
m_verts.fillVerts[12].m_pos = m_verts.fillVerts[11].m_pos; m_verts.fillVerts[12].m_pos = m_verts.fillVerts[11].m_pos;
m_verts.fillVerts[13].m_pos.assign(fillLeft, fillBottom, 0); m_verts.fillVerts[13].m_pos.assign(fillLeft, fillBottom, 0);
m_verts.fillVerts[14].m_pos.assign(fillRight, fillTop, 0); m_verts.fillVerts[14].m_pos.assign(fillRight, fillTop, 0);
m_verts.fillVerts[15].m_pos.assign(fillRight, fillBottom, 0); m_verts.fillVerts[15].m_pos.assign(fillRight, fillBottom, 0);
} }
void ModalWindow::setFillColors(float t) void ModalWindow::setFillColors(float t) {
{ t = zeus::clamp(0.f, t, 1.f);
t = zeus::clamp(0.f, t, 1.f); zeus::CColor color = zeus::CColor::lerp(m_windowBgClear, m_windowBg, t);
zeus::CColor color = zeus::CColor::lerp(m_windowBgClear, m_windowBg, t);
for (int i=0 ; i<16 ; ++i) for (int i = 0; i < 16; ++i)
m_verts.fillVerts[i].m_color = color; m_verts.fillVerts[i].m_color = color;
for (int i=0 ; i<4 ; ++i) for (int i = 0; i < 4; ++i)
m_cornersFilled[i]->colorGlyphs(color); m_cornersFilled[i]->colorGlyphs(color);
} }
ModalWindow::ModalWindow(ViewResources& res, View& parentView, const RectangleConstraint& constraint) ModalWindow::ModalWindow(ViewResources& res, View& parentView, const RectangleConstraint& constraint)
: ModalWindow(res, parentView, constraint, res.themeData().splashBackground()) {} : ModalWindow(res, parentView, constraint, res.themeData().splashBackground()) {}
ModalWindow::ModalWindow(ViewResources& res, View& parentView, ModalWindow::ModalWindow(ViewResources& res, View& parentView, const RectangleConstraint& constraint,
const RectangleConstraint& constraint,
const zeus::CColor& bgColor) const zeus::CColor& bgColor)
: View(res, parentView), : View(res, parentView)
m_constraint(constraint), , m_constraint(constraint)
m_windowBg(bgColor), , m_windowBg(bgColor)
m_windowBgClear(m_windowBg), , m_windowBgClear(m_windowBg)
m_line1(res.themeData().splash1()), , m_line1(res.themeData().splash1())
m_line2(res.themeData().splash2()), , m_line2(res.themeData().splash2())
m_line2Clear(m_line2) , m_line2Clear(m_line2) {
{ m_windowBgClear[3] = 0.0;
m_windowBgClear[3] = 0.0; m_line2Clear[3] = 0.0;
m_line2Clear[3] = 0.0;
res.m_factory->commitTransaction([&](boo::IGraphicsDataFactory::Context& ctx) res.m_factory->commitTransaction([&](boo::IGraphicsDataFactory::Context& ctx) {
{ buildResources(ctx, res);
buildResources(ctx, res); m_viewBlockBuf = res.m_viewRes.m_bufPool.allocateBlock(res.m_factory);
m_viewBlockBuf = res.m_viewRes.m_bufPool.allocateBlock(res.m_factory); m_vertsBinding.init(ctx, res, 38, m_viewBlockBuf);
m_vertsBinding.init(ctx, res, 38, m_viewBlockBuf);
return true;
} BooTrace);
for (int i=0 ; i<4 ; ++i)
{
m_cornersOutline[i].reset(new specter::TextView(res, *this, res.m_curveFont, specter::TextView::Alignment::Left, 1));
m_cornersFilled[i].reset(new specter::TextView(res, *this, res.m_curveFont, specter::TextView::Alignment::Left, 1));
}
m_cornersOutline[0]->typesetGlyphs(L"\xF4F0");
m_cornersFilled[0]->typesetGlyphs(L"\xF4F1", res.themeData().splashBackground());
m_cornersOutline[1]->typesetGlyphs(L"\xF4F2");
m_cornersFilled[1]->typesetGlyphs(L"\xF4F3", res.themeData().splashBackground());
m_cornersOutline[2]->typesetGlyphs(L"\xF4F4");
m_cornersFilled[2]->typesetGlyphs(L"\xF4F5", res.themeData().splashBackground());
m_cornersOutline[3]->typesetGlyphs(L"\xF4F6");
m_cornersFilled[3]->typesetGlyphs(L"\xF4F7", res.themeData().splashBackground());
setLineColors(0.0);
setFillColors(0.0);
_loadVerts();
}
static float CubicEase(float t)
{
t *= 2.f;
if (t < 1) return 1.f/2.f*t*t*t;
t -= 2.f;
return 1.f/2.f*(t*t*t + 2.f);
}
void ModalWindow::think()
{
specter::ViewResources& res = rootView().viewRes();
float pf = res.pixelFactor();
switch (m_phase)
{
case Phase::BuildIn:
{
bool loadVerts = false;
int doneCount = 0;
if (m_frame > WIRE_START)
{
float wt = (m_frame-WIRE_START) / float(WIRE_FRAMES);
wt = zeus::clamp(0.f, wt, 2.f);
m_lineTime = CubicEase(wt);
setLineVerts(m_width, m_height, pf, m_lineTime);
setLineColors(wt);
if (wt == 2.f)
++doneCount;
loadVerts = true;
}
if (m_frame > SOLID_START)
{
float ft = (m_frame-SOLID_START) / float(SOLID_FRAMES);
ft = zeus::clamp(0.f, ft, 2.f);
setFillColors(ft);
if (ft == 2.f)
++doneCount;
loadVerts = true;
}
if (res.fontCacheReady() && m_frame > CONTENT_START)
{
if (!m_contentStartFrame)
m_contentStartFrame = m_frame;
float tt = (m_frame-m_contentStartFrame) / float(CONTENT_FRAMES);
tt = zeus::clamp(0.f, tt, 1.f);
updateContentOpacity(tt);
if (tt == 1.f)
++doneCount;
}
if (doneCount == 3)
m_phase = Phase::Showing;
if (loadVerts)
_loadVerts();
++m_frame;
break;
}
case Phase::ResWait:
{
if (res.fontCacheReady())
{
updateContentOpacity(1.0);
m_phase = Phase::Showing;
}
break;
}
case Phase::BuildOut:
{
{
float wt = (WIRE_FRAMES - m_frame) / float(WIRE_FRAMES);
wt = zeus::clamp(0.f, wt, 1.f);
m_lineTime = CubicEase(wt);
setLineVertsOut(m_width, m_height, pf, m_lineTime);
setLineColorsOut(wt);
if (wt == 0.f)
m_phase = Phase::Done;
}
{
float ft = (SOLID_FRAMES - m_frame) / float(SOLID_FRAMES);
ft = zeus::clamp(0.f, ft, 1.f);
setFillColors(ft);
}
if (res.fontCacheReady())
{
float tt = (CONTENT_FRAMES - m_frame) / float(CONTENT_FRAMES);
tt = zeus::clamp(0.f, tt, 1.f);
updateContentOpacity(tt);
}
_loadVerts();
++m_frame;
break;
}
default: break;
}
}
bool ModalWindow::skipBuildInAnimation()
{
if (m_phase != Phase::BuildIn)
return false;
specter::ViewResources& res = rootView().viewRes();
float pf = res.pixelFactor();
m_lineTime = 1.0;
setLineVerts(m_width, m_height, pf, 1.0);
setLineColors(2.0);
setFillColors(2.0);
_loadVerts();
m_phase = Phase::ResWait;
return true; return true;
} BooTrace);
for (int i = 0; i < 4; ++i) {
m_cornersOutline[i].reset(
new specter::TextView(res, *this, res.m_curveFont, specter::TextView::Alignment::Left, 1));
m_cornersFilled[i].reset(new specter::TextView(res, *this, res.m_curveFont, specter::TextView::Alignment::Left, 1));
}
m_cornersOutline[0]->typesetGlyphs(L"\xF4F0");
m_cornersFilled[0]->typesetGlyphs(L"\xF4F1", res.themeData().splashBackground());
m_cornersOutline[1]->typesetGlyphs(L"\xF4F2");
m_cornersFilled[1]->typesetGlyphs(L"\xF4F3", res.themeData().splashBackground());
m_cornersOutline[2]->typesetGlyphs(L"\xF4F4");
m_cornersFilled[2]->typesetGlyphs(L"\xF4F5", res.themeData().splashBackground());
m_cornersOutline[3]->typesetGlyphs(L"\xF4F6");
m_cornersFilled[3]->typesetGlyphs(L"\xF4F7", res.themeData().splashBackground());
setLineColors(0.0);
setFillColors(0.0);
_loadVerts();
} }
void ModalWindow::close(bool skipAnimation) static float CubicEase(float t) {
{ t *= 2.f;
m_phase = skipAnimation ? Phase::Done : Phase::BuildOut; if (t < 1)
m_frame = 0; return 1.f / 2.f * t * t * t;
t -= 2.f;
return 1.f / 2.f * (t * t * t + 2.f);
} }
void ModalWindow::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) void ModalWindow::think() {
{ specter::ViewResources& res = rootView().viewRes();
float pf = rootView().viewRes().pixelFactor(); float pf = res.pixelFactor();
boo::SWindowRect centerRect = sub; switch (m_phase) {
std::pair<int,int> constrained = m_constraint.solve(root.size[0] - CONTENT_MARGIN * pf * 2, case Phase::BuildIn: {
root.size[1] - CONTENT_MARGIN * pf * 2); bool loadVerts = false;
m_width = std::max(constrained.first, int(WINDOW_MIN_DIM * pf)); int doneCount = 0;
m_height = std::max(constrained.second, int(WINDOW_MIN_DIM * pf)); if (m_frame > WIRE_START) {
centerRect.size[0] = m_width; float wt = (m_frame - WIRE_START) / float(WIRE_FRAMES);
centerRect.size[1] = m_height; wt = zeus::clamp(0.f, wt, 2.f);
centerRect.location[0] = root.size[0] / 2 - m_width / 2.0; m_lineTime = CubicEase(wt);
centerRect.location[1] = root.size[1] / 2 - m_height / 2.0; setLineVerts(m_width, m_height, pf, m_lineTime);
View::resized(root, centerRect); setLineColors(wt);
m_viewBlock.setViewRect(root, centerRect); if (wt == 2.f)
m_viewBlockBuf.access().finalAssign(m_viewBlock); ++doneCount;
loadVerts = true;
setLineVerts(m_width, m_height, pf, m_lineTime); }
setFillVerts(m_width, m_height, pf); if (m_frame > SOLID_START) {
float ft = (m_frame - SOLID_START) / float(SOLID_FRAMES);
ft = zeus::clamp(0.f, ft, 2.f);
setFillColors(ft);
if (ft == 2.f)
++doneCount;
loadVerts = true;
}
if (res.fontCacheReady() && m_frame > CONTENT_START) {
if (!m_contentStartFrame)
m_contentStartFrame = m_frame;
float tt = (m_frame - m_contentStartFrame) / float(CONTENT_FRAMES);
tt = zeus::clamp(0.f, tt, 1.f);
updateContentOpacity(tt);
if (tt == 1.f)
++doneCount;
}
if (doneCount == 3)
m_phase = Phase::Showing;
if (loadVerts)
_loadVerts();
++m_frame;
break;
}
case Phase::ResWait: {
if (res.fontCacheReady()) {
updateContentOpacity(1.0);
m_phase = Phase::Showing;
}
break;
}
case Phase::BuildOut: {
{
float wt = (WIRE_FRAMES - m_frame) / float(WIRE_FRAMES);
wt = zeus::clamp(0.f, wt, 1.f);
m_lineTime = CubicEase(wt);
setLineVertsOut(m_width, m_height, pf, m_lineTime);
setLineColorsOut(wt);
if (wt == 0.f)
m_phase = Phase::Done;
}
{
float ft = (SOLID_FRAMES - m_frame) / float(SOLID_FRAMES);
ft = zeus::clamp(0.f, ft, 1.f);
setFillColors(ft);
}
if (res.fontCacheReady()) {
float tt = (CONTENT_FRAMES - m_frame) / float(CONTENT_FRAMES);
tt = zeus::clamp(0.f, tt, 1.f);
updateContentOpacity(tt);
}
_loadVerts(); _loadVerts();
++m_frame;
boo::SWindowRect cornerRect = centerRect; break;
cornerRect.size[0] = cornerRect.size[1] = 8 * pf; }
cornerRect.location[1] = centerRect.location[1] + m_height - 8 * pf; default:
m_cornersOutline[0]->resized(root, cornerRect); break;
m_cornersFilled[0]->resized(root, cornerRect); }
cornerRect.location[0] = centerRect.location[0] + m_width - 8 * pf;
m_cornersOutline[1]->resized(root, cornerRect);
m_cornersFilled[1]->resized(root, cornerRect);
cornerRect.location[1] = centerRect.location[1];
m_cornersOutline[2]->resized(root, cornerRect);
m_cornersFilled[2]->resized(root, cornerRect);
cornerRect.location[0] = centerRect.location[0];
m_cornersOutline[3]->resized(root, cornerRect);
m_cornersFilled[3]->resized(root, cornerRect);
} }
void ModalWindow::draw(boo::IGraphicsCommandQueue* gfxQ) bool ModalWindow::skipBuildInAnimation() {
{ if (m_phase != Phase::BuildIn)
if (m_phase == Phase::Done) return false;
return;
gfxQ->setShaderDataBinding(m_vertsBinding); specter::ViewResources& res = rootView().viewRes();
gfxQ->draw(0, 22); float pf = res.pixelFactor();
gfxQ->draw(22, 16);
m_cornersFilled[0]->draw(gfxQ); m_lineTime = 1.0;
m_cornersFilled[1]->draw(gfxQ); setLineVerts(m_width, m_height, pf, 1.0);
m_cornersFilled[2]->draw(gfxQ); setLineColors(2.0);
m_cornersFilled[3]->draw(gfxQ); setFillColors(2.0);
_loadVerts();
m_cornersOutline[0]->draw(gfxQ); m_phase = Phase::ResWait;
m_cornersOutline[1]->draw(gfxQ); return true;
m_cornersOutline[2]->draw(gfxQ);
m_cornersOutline[3]->draw(gfxQ);
} }
void ModalWindow::close(bool skipAnimation) {
m_phase = skipAnimation ? Phase::Done : Phase::BuildOut;
m_frame = 0;
} }
void ModalWindow::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) {
float pf = rootView().viewRes().pixelFactor();
boo::SWindowRect centerRect = sub;
std::pair<int, int> constrained =
m_constraint.solve(root.size[0] - CONTENT_MARGIN * pf * 2, root.size[1] - CONTENT_MARGIN * pf * 2);
m_width = std::max(constrained.first, int(WINDOW_MIN_DIM * pf));
m_height = std::max(constrained.second, int(WINDOW_MIN_DIM * pf));
centerRect.size[0] = m_width;
centerRect.size[1] = m_height;
centerRect.location[0] = root.size[0] / 2 - m_width / 2.0;
centerRect.location[1] = root.size[1] / 2 - m_height / 2.0;
View::resized(root, centerRect);
m_viewBlock.setViewRect(root, centerRect);
m_viewBlockBuf.access().finalAssign(m_viewBlock);
setLineVerts(m_width, m_height, pf, m_lineTime);
setFillVerts(m_width, m_height, pf);
_loadVerts();
boo::SWindowRect cornerRect = centerRect;
cornerRect.size[0] = cornerRect.size[1] = 8 * pf;
cornerRect.location[1] = centerRect.location[1] + m_height - 8 * pf;
m_cornersOutline[0]->resized(root, cornerRect);
m_cornersFilled[0]->resized(root, cornerRect);
cornerRect.location[0] = centerRect.location[0] + m_width - 8 * pf;
m_cornersOutline[1]->resized(root, cornerRect);
m_cornersFilled[1]->resized(root, cornerRect);
cornerRect.location[1] = centerRect.location[1];
m_cornersOutline[2]->resized(root, cornerRect);
m_cornersFilled[2]->resized(root, cornerRect);
cornerRect.location[0] = centerRect.location[0];
m_cornersOutline[3]->resized(root, cornerRect);
m_cornersFilled[3]->resized(root, cornerRect);
}
void ModalWindow::draw(boo::IGraphicsCommandQueue* gfxQ) {
if (m_phase == Phase::Done)
return;
gfxQ->setShaderDataBinding(m_vertsBinding);
gfxQ->draw(0, 22);
gfxQ->draw(22, 16);
m_cornersFilled[0]->draw(gfxQ);
m_cornersFilled[1]->draw(gfxQ);
m_cornersFilled[2]->draw(gfxQ);
m_cornersFilled[3]->draw(gfxQ);
m_cornersOutline[0]->draw(gfxQ);
m_cornersOutline[1]->draw(gfxQ);
m_cornersOutline[2]->draw(gfxQ);
m_cornersOutline[3]->draw(gfxQ);
}
} // namespace specter

View File

@ -1,290 +1,249 @@
#include "specter/MultiLineTextView.hpp" #include "specter/MultiLineTextView.hpp"
#include "specter/ViewResources.hpp" #include "specter/ViewResources.hpp"
namespace specter namespace specter {
{
static logvisor::Module Log("specter::MultiLineTextView"); static logvisor::Module Log("specter::MultiLineTextView");
std::string MultiLineTextView::LineWrap(std::string_view str, int wrap) std::string MultiLineTextView::LineWrap(std::string_view str, int wrap) {
{ size_t rem = str.size();
size_t rem = str.size(); const utf8proc_uint8_t* it = reinterpret_cast<const utf8proc_uint8_t*>(str.data());
const utf8proc_uint8_t* it = reinterpret_cast<const utf8proc_uint8_t*>(str.data()); uint32_t lCh = -1;
uint32_t lCh = -1; int adv = 0;
int adv = 0;
std::string ret; std::string ret;
ret.reserve(str.size()); ret.reserve(str.size());
size_t lastSpaceRem; size_t lastSpaceRem;
const utf8proc_uint8_t* lastSpaceIt = nullptr; const utf8proc_uint8_t* lastSpaceIt = nullptr;
size_t rollbackPos; size_t rollbackPos;
while (rem) while (rem) {
{ utf8proc_int32_t ch;
utf8proc_int32_t ch; utf8proc_ssize_t sz = utf8proc_iterate(it, -1, &ch);
utf8proc_ssize_t sz = utf8proc_iterate(it, -1, &ch); if (sz < 0)
if (sz < 0) Log.report(logvisor::Fatal, "invalid UTF-8 char");
Log.report(logvisor::Fatal, "invalid UTF-8 char"); if (ch == '\n') {
if (ch == '\n') ret += '\n';
{ lCh = -1;
ret += '\n'; rem -= sz;
lCh = -1; it += sz;
rem -= sz; lastSpaceIt = nullptr;
it += sz; adv = 0;
lastSpaceIt = nullptr; continue;
adv = 0;
continue;
}
const FontAtlas::Glyph* glyph = m_fontAtlas.lookupGlyph(ch);
if (!glyph)
{
rem -= sz;
it += sz;
continue;
}
if (lCh != -1)
adv += TextView::DoKern(m_fontAtlas.lookupKern(lCh, glyph->m_glyphIdx), m_fontAtlas);
adv += glyph->m_advance;
if (adv > wrap && lastSpaceIt)
{
ret.assign(ret.cbegin(), ret.cbegin() + rollbackPos);
ret += '\n';
lCh = -1;
rem = lastSpaceRem;
it = lastSpaceIt;
lastSpaceIt = nullptr;
adv = 0;
continue;
}
if (sz == 1 && (it[0] == ' ' || it[0] == '-' || it[0] == '/' || it[0] == '\\'))
{
lastSpaceIt = it + 1;
lastSpaceRem = rem - 1;
rollbackPos = ret.size() + 1;
}
for (utf8proc_ssize_t i=0 ; i<sz ; ++i)
ret += it[i];
lCh = glyph->m_glyphIdx;
rem -= sz;
it += sz;
} }
return ret; const FontAtlas::Glyph* glyph = m_fontAtlas.lookupGlyph(ch);
} if (!glyph) {
rem -= sz;
std::wstring MultiLineTextView::LineWrap(std::wstring_view str, int wrap) it += sz;
{ continue;
uint32_t lCh = -1;
int adv = 0;
std::wstring ret;
ret.reserve(str.size());
std::wstring_view::const_iterator lastSpaceIt = str.cend();
size_t rollbackPos;
for (std::wstring_view::const_iterator it = str.cbegin() ; it != str.cend() ; ++it)
{
wchar_t ch = *it;
if (ch == L'\n')
{
ret += L'\n';
lCh = -1;
lastSpaceIt = str.cend();
adv = 0;
continue;
}
const FontAtlas::Glyph* glyph = m_fontAtlas.lookupGlyph(ch);
if (!glyph)
continue;
if (lCh != -1)
adv += TextView::DoKern(m_fontAtlas.lookupKern(lCh, glyph->m_glyphIdx), m_fontAtlas);
adv += glyph->m_advance;
if (adv > wrap && lastSpaceIt != str.cend())
{
ret.assign(ret.cbegin(), ret.cbegin() + rollbackPos);
ret += L'\n';
lCh = -1;
it = lastSpaceIt;
lastSpaceIt = str.cend();
adv = 0;
continue;
}
if (ch == L' ' || ch == L'-')
{
lastSpaceIt = it + 1;
rollbackPos = ret.size() + 1;
}
ret += ch;
lCh = glyph->m_glyphIdx;
} }
return ret; if (lCh != -1)
} adv += TextView::DoKern(m_fontAtlas.lookupKern(lCh, glyph->m_glyphIdx), m_fontAtlas);
adv += glyph->m_advance;
MultiLineTextView::MultiLineTextView(ViewResources& res, if (adv > wrap && lastSpaceIt) {
View& parentView, ret.assign(ret.cbegin(), ret.cbegin() + rollbackPos);
const FontAtlas& font, ret += '\n';
TextView::Alignment align, lCh = -1;
size_t lineCapacity, rem = lastSpaceRem;
float lineHeight) it = lastSpaceIt;
: View(res, parentView), lastSpaceIt = nullptr;
m_viewSystem(res), adv = 0;
m_fontAtlas(font), continue;
m_align(align),
m_lineCapacity(lineCapacity),
m_lineHeight(lineHeight)
{
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool
{
buildResources(ctx, res);
return true;
});
}
MultiLineTextView::MultiLineTextView(ViewResources& res,
View& parentView,
FontTag font,
TextView::Alignment align,
size_t lineCapacity,
float lineHeight)
: MultiLineTextView(res,
parentView,
res.m_textRes.m_fcache->lookupAtlas(font),
align,
lineCapacity,
lineHeight) {}
void MultiLineTextView::typesetGlyphs(std::string_view str,
const zeus::CColor& defaultColor,
unsigned wrap)
{
if (wrap)
{
typesetGlyphs(LineWrap(str, wrap), defaultColor);
return;
} }
m_width = 0; if (sz == 1 && (it[0] == ' ' || it[0] == '-' || it[0] == '/' || it[0] == '\\')) {
size_t rem = str.size() + 1; lastSpaceIt = it + 1;
const utf8proc_uint8_t* it = reinterpret_cast<const utf8proc_uint8_t*>(str.data()); lastSpaceRem = rem - 1;
rollbackPos = ret.size() + 1;
size_t lineCount = 0;
while (rem)
{
utf8proc_int32_t ch;
utf8proc_ssize_t sz = utf8proc_iterate(it, -1, &ch);
if (sz < 0)
Log.report(logvisor::Fatal, "invalid UTF-8 char");
if (ch == '\n' || ch == '\0')
++lineCount;
rem -= sz;
it += sz;
} }
for (utf8proc_ssize_t i = 0; i < sz; ++i)
ret += it[i];
lCh = glyph->m_glyphIdx;
rem -= sz;
it += sz;
}
m_lines.reserve(lineCount); return ret;
rem = str.size() + 1;
it = reinterpret_cast<const utf8proc_uint8_t*>(str.data());
const utf8proc_uint8_t* beginIt = it;
size_t lineIt = 0;
while (rem)
{
utf8proc_int32_t ch;
utf8proc_ssize_t sz = utf8proc_iterate(it, -1, &ch);
if (ch == '\n' || ch == '\0')
{
TextView& tv = (lineIt < m_lines.size()) ? *m_lines[lineIt] :
*m_lines.emplace_back(new TextView(m_viewSystem, *this, m_fontAtlas, m_align, m_lineCapacity));
tv.typesetGlyphs(std::string((char*)beginIt, it - beginIt), defaultColor);
m_width = std::max(m_width, tv.nominalWidth());
beginIt = it + 1;
++lineIt;
}
rem -= sz;
it += sz;
}
updateSize();
} }
void MultiLineTextView::typesetGlyphs(std::wstring_view str, std::wstring MultiLineTextView::LineWrap(std::wstring_view str, int wrap) {
const zeus::CColor& defaultColor, uint32_t lCh = -1;
unsigned wrap) int adv = 0;
{
if (wrap) std::wstring ret;
{ ret.reserve(str.size());
typesetGlyphs(LineWrap(str, wrap), defaultColor); std::wstring_view::const_iterator lastSpaceIt = str.cend();
return; size_t rollbackPos;
for (std::wstring_view::const_iterator it = str.cbegin(); it != str.cend(); ++it) {
wchar_t ch = *it;
if (ch == L'\n') {
ret += L'\n';
lCh = -1;
lastSpaceIt = str.cend();
adv = 0;
continue;
} }
m_width = 0; const FontAtlas::Glyph* glyph = m_fontAtlas.lookupGlyph(ch);
size_t rem = str.size() + 1; if (!glyph)
auto it = str.cbegin(); continue;
size_t lineCount = 0; if (lCh != -1)
while (rem) adv += TextView::DoKern(m_fontAtlas.lookupKern(lCh, glyph->m_glyphIdx), m_fontAtlas);
{ adv += glyph->m_advance;
if (*it == L'\n' || *it == L'\0')
++lineCount; if (adv > wrap && lastSpaceIt != str.cend()) {
--rem; ret.assign(ret.cbegin(), ret.cbegin() + rollbackPos);
++it; ret += L'\n';
lCh = -1;
it = lastSpaceIt;
lastSpaceIt = str.cend();
adv = 0;
continue;
} }
m_lines.reserve(lineCount); if (ch == L' ' || ch == L'-') {
rem = str.size() + 1; lastSpaceIt = it + 1;
it = str.cbegin(); rollbackPos = ret.size() + 1;
auto beginIt = it;
size_t lineIt = 0;
while (rem)
{
if (*it == L'\n' || *it == L'\0')
{
TextView& tv = (lineIt < m_lines.size()) ? *m_lines[lineIt] :
*m_lines.emplace_back(new TextView(m_viewSystem, *this, m_fontAtlas, m_align, m_lineCapacity));
tv.typesetGlyphs(std::wstring(beginIt, it), defaultColor);
m_width = std::max(m_width, tv.nominalWidth());
beginIt = it + 1;
++lineIt;
}
--rem;
++it;
} }
ret += ch;
lCh = glyph->m_glyphIdx;
}
updateSize(); return ret;
} }
void MultiLineTextView::colorGlyphs(const zeus::CColor& newColor) MultiLineTextView::MultiLineTextView(ViewResources& res, View& parentView, const FontAtlas& font,
{ TextView::Alignment align, size_t lineCapacity, float lineHeight)
for (std::unique_ptr<TextView>& tv : m_lines) : View(res, parentView)
tv->colorGlyphs(newColor); , m_viewSystem(res)
, m_fontAtlas(font)
, m_align(align)
, m_lineCapacity(lineCapacity)
, m_lineHeight(lineHeight) {
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool {
buildResources(ctx, res);
return true;
});
} }
void MultiLineTextView::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) MultiLineTextView::MultiLineTextView(ViewResources& res, View& parentView, FontTag font, TextView::Alignment align,
{ size_t lineCapacity, float lineHeight)
View::resized(root, sub); : MultiLineTextView(res, parentView, res.m_textRes.m_fcache->lookupAtlas(font), align, lineCapacity, lineHeight) {}
unsigned lHeight = unsigned(m_lineHeight * m_fontAtlas.FT_LineHeight()) >> 6;
unsigned decumHeight = lHeight * m_lines.size(); void MultiLineTextView::typesetGlyphs(std::string_view str, const zeus::CColor& defaultColor, unsigned wrap) {
boo::SWindowRect tsub = sub; if (wrap) {
tsub.location[1] += decumHeight; typesetGlyphs(LineWrap(str, wrap), defaultColor);
tsub.size[1] = 10; return;
for (std::unique_ptr<TextView>& tv : m_lines) }
{
tsub.location[1] -= lHeight; m_width = 0;
tv->resized(root, tsub); size_t rem = str.size() + 1;
const utf8proc_uint8_t* it = reinterpret_cast<const utf8proc_uint8_t*>(str.data());
size_t lineCount = 0;
while (rem) {
utf8proc_int32_t ch;
utf8proc_ssize_t sz = utf8proc_iterate(it, -1, &ch);
if (sz < 0)
Log.report(logvisor::Fatal, "invalid UTF-8 char");
if (ch == '\n' || ch == '\0')
++lineCount;
rem -= sz;
it += sz;
}
m_lines.reserve(lineCount);
rem = str.size() + 1;
it = reinterpret_cast<const utf8proc_uint8_t*>(str.data());
const utf8proc_uint8_t* beginIt = it;
size_t lineIt = 0;
while (rem) {
utf8proc_int32_t ch;
utf8proc_ssize_t sz = utf8proc_iterate(it, -1, &ch);
if (ch == '\n' || ch == '\0') {
TextView& tv =
(lineIt < m_lines.size())
? *m_lines[lineIt]
: *m_lines.emplace_back(new TextView(m_viewSystem, *this, m_fontAtlas, m_align, m_lineCapacity));
tv.typesetGlyphs(std::string((char*)beginIt, it - beginIt), defaultColor);
m_width = std::max(m_width, tv.nominalWidth());
beginIt = it + 1;
++lineIt;
} }
rem -= sz;
it += sz;
}
updateSize();
} }
void MultiLineTextView::draw(boo::IGraphicsCommandQueue* gfxQ) void MultiLineTextView::typesetGlyphs(std::wstring_view str, const zeus::CColor& defaultColor, unsigned wrap) {
{ if (wrap) {
View::draw(gfxQ); typesetGlyphs(LineWrap(str, wrap), defaultColor);
for (std::unique_ptr<TextView>& tv : m_lines) return;
tv->draw(gfxQ); }
m_width = 0;
size_t rem = str.size() + 1;
auto it = str.cbegin();
size_t lineCount = 0;
while (rem) {
if (*it == L'\n' || *it == L'\0')
++lineCount;
--rem;
++it;
}
m_lines.reserve(lineCount);
rem = str.size() + 1;
it = str.cbegin();
auto beginIt = it;
size_t lineIt = 0;
while (rem) {
if (*it == L'\n' || *it == L'\0') {
TextView& tv =
(lineIt < m_lines.size())
? *m_lines[lineIt]
: *m_lines.emplace_back(new TextView(m_viewSystem, *this, m_fontAtlas, m_align, m_lineCapacity));
tv.typesetGlyphs(std::wstring(beginIt, it), defaultColor);
m_width = std::max(m_width, tv.nominalWidth());
beginIt = it + 1;
++lineIt;
}
--rem;
++it;
}
updateSize();
} }
void MultiLineTextView::colorGlyphs(const zeus::CColor& newColor) {
for (std::unique_ptr<TextView>& tv : m_lines)
tv->colorGlyphs(newColor);
} }
void MultiLineTextView::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) {
View::resized(root, sub);
unsigned lHeight = unsigned(m_lineHeight * m_fontAtlas.FT_LineHeight()) >> 6;
unsigned decumHeight = lHeight * m_lines.size();
boo::SWindowRect tsub = sub;
tsub.location[1] += decumHeight;
tsub.size[1] = 10;
for (std::unique_ptr<TextView>& tv : m_lines) {
tsub.location[1] -= lHeight;
tv->resized(root, tsub);
}
}
void MultiLineTextView::draw(boo::IGraphicsCommandQueue* gfxQ) {
View::draw(gfxQ);
for (std::unique_ptr<TextView>& tv : m_lines)
tv->draw(gfxQ);
}
} // namespace specter

View File

@ -2,94 +2,82 @@
#include "specter/RootView.hpp" #include "specter/RootView.hpp"
#include "specter/ViewResources.hpp" #include "specter/ViewResources.hpp"
namespace specter namespace specter {
{
PathButtons::PathButtons(ViewResources& res, View& parentView, IPathButtonsBinding& binding, bool fillContainer) PathButtons::PathButtons(ViewResources& res, View& parentView, IPathButtonsBinding& binding, bool fillContainer)
: ScrollView(res, parentView, ScrollView::Style::SideButtons), m_binding(binding), m_fillContainer(fillContainer) : ScrollView(res, parentView, ScrollView::Style::SideButtons), m_binding(binding), m_fillContainer(fillContainer) {
{ m_contentView.m_view.reset(new ContentView(res, *this));
m_contentView.m_view.reset(new ContentView(res, *this)); setContentView(m_contentView.m_view.get());
setContentView(m_contentView.m_view.get());
} }
void PathButtons::setButtons(const std::vector<hecl::SystemString>& comps) void PathButtons::setButtons(const std::vector<hecl::SystemString>& comps) {
{ m_pathButtons.clear();
m_pathButtons.clear(); m_pathButtons.reserve(comps.size());
m_pathButtons.reserve(comps.size()); size_t idx = 0;
size_t idx = 0; ViewResources& res = rootView().viewRes();
ViewResources& res = rootView().viewRes(); for (const hecl::SystemString& c : comps)
for (const hecl::SystemString& c : comps) m_pathButtons.emplace_back(*this, res, idx++, c);
m_pathButtons.emplace_back(*this, res, idx++, c);
} }
void PathButtons::setMultiplyColor(const zeus::CColor& color) void PathButtons::setMultiplyColor(const zeus::CColor& color) {
{ ScrollView::setMultiplyColor(color);
ScrollView::setMultiplyColor(color); for (PathButton& b : m_pathButtons)
for (PathButton& b : m_pathButtons) b.m_button.m_view->setMultiplyColor(color);
b.m_button.m_view->setMultiplyColor(color);
} }
void PathButtons::ContentView::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) void PathButtons::ContentView::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button,
{ boo::EModifierKey mod) {
for (PathButton& b : m_pb.m_pathButtons) for (PathButton& b : m_pb.m_pathButtons)
b.m_button.mouseDown(coord, button, mod); b.m_button.mouseDown(coord, button, mod);
} }
void PathButtons::ContentView::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) void PathButtons::ContentView::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button,
{ boo::EModifierKey mod) {
for (PathButton& b : m_pb.m_pathButtons) for (PathButton& b : m_pb.m_pathButtons)
b.m_button.mouseUp(coord, button, mod); b.m_button.mouseUp(coord, button, mod);
if (m_pb.m_pathButtonPending >= 0) if (m_pb.m_pathButtonPending >= 0) {
{ m_pb.m_binding.pathButtonActivated(m_pb.m_pathButtonPending);
m_pb.m_binding.pathButtonActivated(m_pb.m_pathButtonPending); m_pb.m_pathButtonPending = -1;
m_pb.m_pathButtonPending = -1; }
}
} }
void PathButtons::ContentView::mouseMove(const boo::SWindowCoord& coord) void PathButtons::ContentView::mouseMove(const boo::SWindowCoord& coord) {
{ for (PathButton& b : m_pb.m_pathButtons)
for (PathButton& b : m_pb.m_pathButtons) b.m_button.mouseMove(coord);
b.m_button.mouseMove(coord);
} }
void PathButtons::ContentView::mouseLeave(const boo::SWindowCoord& coord) void PathButtons::ContentView::mouseLeave(const boo::SWindowCoord& coord) {
{ for (PathButton& b : m_pb.m_pathButtons)
for (PathButton& b : m_pb.m_pathButtons) b.m_button.mouseLeave(coord);
b.m_button.mouseLeave(coord);
} }
void PathButtons::ContentView::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub, void PathButtons::ContentView::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub,
const boo::SWindowRect& scissor) const boo::SWindowRect& scissor) {
{ View::resized(root, sub);
View::resized(root, sub); m_scissorRect = scissor;
m_scissorRect = scissor; m_scissorRect.size[1] += 2;
m_scissorRect.size[1] += 2; boo::SWindowRect pathRect = sub;
boo::SWindowRect pathRect = sub; for (PathButton& b : m_pb.m_pathButtons) {
for (PathButton& b : m_pb.m_pathButtons) pathRect.size[0] = b.m_button.m_view->nominalWidth();
{ pathRect.size[1] = b.m_button.m_view->nominalHeight();
pathRect.size[0] = b.m_button.m_view->nominalWidth(); b.m_button.m_view->resized(root, pathRect);
pathRect.size[1] = b.m_button.m_view->nominalHeight(); pathRect.location[0] += pathRect.size[0] + 2;
b.m_button.m_view->resized(root, pathRect); }
pathRect.location[0] += pathRect.size[0] + 2;
}
} }
void PathButtons::containerResized(const boo::SWindowRect& root, const boo::SWindowRect& sub) void PathButtons::containerResized(const boo::SWindowRect& root, const boo::SWindowRect& sub) {
{ if (m_fillContainer) {
if (m_fillContainer) boo::SWindowRect fillRect = sub;
{ fillRect.size[1] = 20 * rootView().viewRes().pixelFactor();
boo::SWindowRect fillRect = sub; View::resized(root, fillRect);
fillRect.size[1] = 20 * rootView().viewRes().pixelFactor(); }
View::resized(root, fillRect);
}
} }
void PathButtons::ContentView::draw(boo::IGraphicsCommandQueue* gfxQ) void PathButtons::ContentView::draw(boo::IGraphicsCommandQueue* gfxQ) {
{ gfxQ->setScissor(m_scissorRect);
gfxQ->setScissor(m_scissorRect); for (PathButton& b : m_pb.m_pathButtons)
for (PathButton& b : m_pb.m_pathButtons) b.m_button.m_view->draw(gfxQ);
b.m_button.m_view->draw(gfxQ); gfxQ->setScissor(rootView().subRect());
gfxQ->setScissor(rootView().subRect());
} }
} } // namespace specter

File diff suppressed because it is too large Load Diff

View File

@ -3,315 +3,261 @@
#include "specter/RootView.hpp" #include "specter/RootView.hpp"
#include "specter/Button.hpp" #include "specter/Button.hpp"
namespace specter namespace specter {
{
#define MAX_SCROLL_SPEED 100 #define MAX_SCROLL_SPEED 100
ScrollView::ScrollView(ViewResources& res, View& parentView, Style style) ScrollView::ScrollView(ViewResources& res, View& parentView, Style style)
: View(res, parentView), m_style(style), m_sideButtonBind(*this, rootView().viewManager()) : View(res, parentView), m_style(style), m_sideButtonBind(*this, rootView().viewManager()) {
{ commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool {
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool buildResources(ctx, res);
{ m_vertsBinding.init(ctx, res, 4, m_viewVertBlockBuf);
buildResources(ctx, res); return true;
m_vertsBinding.init(ctx, res, 4, m_viewVertBlockBuf); });
return true;
});
if (style == Style::SideButtons) if (style == Style::SideButtons) {
{ m_sideButtons[0].m_view.reset(new Button(res, *this, &m_sideButtonBind, "<"));
m_sideButtons[0].m_view.reset(new Button(res, *this, &m_sideButtonBind, "<")); m_sideButtons[1].m_view.reset(new Button(res, *this, &m_sideButtonBind, ">"));
m_sideButtons[1].m_view.reset(new Button(res, *this, &m_sideButtonBind, ">")); }
}
} }
bool ScrollView::_scroll(const boo::SScrollDelta& scroll) bool ScrollView::_scroll(const boo::SScrollDelta& scroll) {
{ if (m_contentView.m_view) {
if (m_contentView.m_view) float ratioX = subRect().size[0] / float(m_contentView.m_view->nominalWidth());
{ float ratioY = subRect().size[1] / float(m_contentView.m_view->nominalHeight());
float ratioX = subRect().size[0] / float(m_contentView.m_view->nominalWidth());
float ratioY = subRect().size[1] / float(m_contentView.m_view->nominalHeight());
float pf = rootView().viewRes().pixelFactor();
double mult = 20.0 * pf;
if (scroll.isFine)
mult = 1.0 * pf;
bool ret = false;
if (ratioX >= 1.f)
{
m_scroll[0] = 0;
m_targetScroll[0] = 0;
m_drawSideButtons = false;
ret = true;
}
else
{
m_drawSideButtons = true;
m_targetScroll[0] += scroll.delta[0] * mult;
m_targetScroll[0] = std::min(m_targetScroll[0], 0);
int scrollWidth = m_contentView.m_view->nominalWidth() - scrollAreaWidth();
m_targetScroll[0] = std::max(m_targetScroll[0], -scrollWidth);
}
if (ratioY >= 1.f)
{
m_scroll[1] = 0;
m_targetScroll[1] = 0;
ret = true;
}
else
{
m_targetScroll[1] -= scroll.delta[1] * mult;
m_targetScroll[1] = std::max(m_targetScroll[1], 0);
int scrollHeight = m_contentView.m_view->nominalHeight() - subRect().size[1];
m_targetScroll[1] = std::min(m_targetScroll[1], scrollHeight);
}
if (scroll.isFine)
{
m_scroll[0] = m_targetScroll[0];
m_scroll[1] = m_targetScroll[1];
ret = true;
}
return ret;
}
else
{
m_scroll[0] = 0;
m_scroll[1] = 0;
m_targetScroll[0] = 0;
m_targetScroll[1] = 0;
m_drawSideButtons = false;
return true;
}
return false;
}
int ScrollView::scrollAreaWidth() const
{
int ret = subRect().size[0];
if (m_style == Style::SideButtons && m_drawSideButtons)
{
ret -= m_sideButtons[0].m_view->nominalWidth();
ret -= m_sideButtons[1].m_view->nominalWidth();
}
return std::max(0, ret);
}
void ScrollView::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod)
{
if (m_style == Style::SideButtons && m_drawSideButtons)
{
if (m_sideButtons[0].mouseDown(coord, button, mod) ||
m_sideButtons[1].mouseDown(coord, button, mod))
return;
}
m_contentView.mouseDown(coord, button, mod);
}
void ScrollView::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod)
{
if (m_style == Style::SideButtons)
{
m_sideButtons[0].mouseUp(coord, button, mod);
m_sideButtons[1].mouseUp(coord, button, mod);
}
m_contentView.mouseUp(coord, button, mod);
}
void ScrollView::mouseMove(const boo::SWindowCoord& coord)
{
if (m_style == Style::SideButtons && m_drawSideButtons)
{
m_sideButtons[0].mouseMove(coord);
m_sideButtons[1].mouseMove(coord);
}
m_contentView.mouseMove(coord);
}
void ScrollView::mouseEnter(const boo::SWindowCoord& coord)
{
if (m_style == Style::SideButtons && m_drawSideButtons)
{
m_sideButtons[0].mouseEnter(coord);
m_sideButtons[1].mouseEnter(coord);
}
m_contentView.mouseEnter(coord);
}
void ScrollView::mouseLeave(const boo::SWindowCoord& coord)
{
if (m_style == Style::SideButtons)
{
m_sideButtons[0].mouseLeave(coord);
m_sideButtons[1].mouseLeave(coord);
}
m_contentView.mouseLeave(coord);
}
void ScrollView::scroll(const boo::SWindowCoord& coord, const boo::SScrollDelta& scroll)
{
if (!scroll.isAccelerated)
{
boo::SScrollDelta newScroll = scroll;
m_consecutiveScroll[m_consecutiveIdx][0] += scroll.delta[0];
m_consecutiveScroll[m_consecutiveIdx][1] += scroll.delta[1];
newScroll.delta[0] = 0;
newScroll.delta[1] = 0;
for (size_t i=0 ; i<16 ; ++i)
{
newScroll.delta[0] += m_consecutiveScroll[i][0];
newScroll.delta[1] += m_consecutiveScroll[i][1];
}
if (_scroll(newScroll))
updateSize();
return;
}
if (_scroll(scroll))
updateSize();
}
void ScrollView::setMultiplyColor(const zeus::CColor& color)
{
View::setMultiplyColor(color);
if (m_style == Style::SideButtons)
{
m_sideButtons[0].m_view->setMultiplyColor(color);
m_sideButtons[1].m_view->setMultiplyColor(color);
}
if (m_contentView.m_view)
m_contentView.m_view->setMultiplyColor(color);
}
void ScrollView::think()
{
m_consecutiveIdx = (m_consecutiveIdx+1) % 16;
m_consecutiveScroll[m_consecutiveIdx][0] = 0.0;
m_consecutiveScroll[m_consecutiveIdx][1] = 0.0;
if (m_sideButtonState != SideButtonState::None)
{
if (m_sideButtonState == SideButtonState::ScrollLeft)
m_targetScroll[0] -= 3;
else if (m_sideButtonState == SideButtonState::ScrollRight)
m_targetScroll[0] += 3;
m_targetScroll[0] = std::min(m_targetScroll[0], 0);
int scrollWidth = m_contentView.m_view->nominalWidth() - scrollAreaWidth();
m_targetScroll[0] = std::max(m_targetScroll[0], -scrollWidth);
}
bool update = false;
float pf = rootView().viewRes().pixelFactor(); float pf = rootView().viewRes().pixelFactor();
double mult = 20.0 * pf;
if (scroll.isFine)
mult = 1.0 * pf;
int xSpeed = std::max(1, std::min(abs(m_targetScroll[0] - m_scroll[0]) / int(5*pf), int(pf*MAX_SCROLL_SPEED))); bool ret = false;
if (m_scroll[0] < m_targetScroll[0])
{ if (ratioX >= 1.f) {
m_scroll[0] += xSpeed; m_scroll[0] = 0;
update = true; m_targetScroll[0] = 0;
} m_drawSideButtons = false;
else if (m_scroll[0] > m_targetScroll[0]) ret = true;
{ } else {
m_scroll[0] -= xSpeed; m_drawSideButtons = true;
update = true; m_targetScroll[0] += scroll.delta[0] * mult;
m_targetScroll[0] = std::min(m_targetScroll[0], 0);
int scrollWidth = m_contentView.m_view->nominalWidth() - scrollAreaWidth();
m_targetScroll[0] = std::max(m_targetScroll[0], -scrollWidth);
} }
int ySpeed = std::max(1, std::min(abs(m_targetScroll[1] - m_scroll[1]) / int(5*pf), int(pf*MAX_SCROLL_SPEED))); if (ratioY >= 1.f) {
if (m_scroll[1] < m_targetScroll[1]) m_scroll[1] = 0;
{ m_targetScroll[1] = 0;
m_scroll[1] += ySpeed; ret = true;
update = true; } else {
} m_targetScroll[1] -= scroll.delta[1] * mult;
else if (m_scroll[1] > m_targetScroll[1]) m_targetScroll[1] = std::max(m_targetScroll[1], 0);
{ int scrollHeight = m_contentView.m_view->nominalHeight() - subRect().size[1];
m_scroll[1] -= ySpeed; m_targetScroll[1] = std::min(m_targetScroll[1], scrollHeight);
update = true;
} }
if (update) if (scroll.isFine) {
updateSize(); m_scroll[0] = m_targetScroll[0];
m_scroll[1] = m_targetScroll[1];
ret = true;
}
return ret;
} else {
m_scroll[0] = 0;
m_scroll[1] = 0;
m_targetScroll[0] = 0;
m_targetScroll[1] = 0;
m_drawSideButtons = false;
return true;
}
return false;
} }
void ScrollView::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) int ScrollView::scrollAreaWidth() const {
{ int ret = subRect().size[0];
View::resized(root, sub); if (m_style == Style::SideButtons && m_drawSideButtons) {
_scroll({}); ret -= m_sideButtons[0].m_view->nominalWidth();
if (m_contentView.m_view) ret -= m_sideButtons[1].m_view->nominalWidth();
{ }
boo::SWindowRect cRect = sub; return std::max(0, ret);
cRect.location[0] += m_scroll[0]; }
cRect.location[1] += sub.size[1] - m_contentView.m_view->nominalHeight() + m_scroll[1];
cRect.size[0] = m_contentView.m_view->nominalWidth();
cRect.size[1] = m_contentView.m_view->nominalHeight();
m_contentView.m_scissorRect = sub;
if (m_style == Style::SideButtons && m_drawSideButtons)
{
int width0 = m_sideButtons[0].m_view->nominalWidth() + 2;
int width1 = m_sideButtons[1].m_view->nominalWidth();
cRect.location[0] += width0;
cRect.size[0] -= (width0 + width1);
m_contentView.m_scissorRect.location[0] += width0; void ScrollView::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
m_contentView.m_scissorRect.size[0] -= (width0 + width1); if (m_style == Style::SideButtons && m_drawSideButtons) {
} if (m_sideButtons[0].mouseDown(coord, button, mod) || m_sideButtons[1].mouseDown(coord, button, mod))
m_contentView.m_view->resized(root, cRect, m_contentView.m_scissorRect); return;
}
m_contentView.mouseDown(coord, button, mod);
}
void ScrollView::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
if (m_style == Style::SideButtons) {
m_sideButtons[0].mouseUp(coord, button, mod);
m_sideButtons[1].mouseUp(coord, button, mod);
}
m_contentView.mouseUp(coord, button, mod);
}
if (m_style == Style::ThinIndicator) void ScrollView::mouseMove(const boo::SWindowCoord& coord) {
{ if (m_style == Style::SideButtons && m_drawSideButtons) {
float ratio = sub.size[1] / float(cRect.size[1]); m_sideButtons[0].mouseMove(coord);
m_drawInd = ratio < 1.f; m_sideButtons[1].mouseMove(coord);
if (m_drawInd) }
{ m_contentView.mouseMove(coord);
float pf = rootView().viewRes().pixelFactor(); }
int barHeight = sub.size[1] * ratio;
int scrollHeight = sub.size[1] - barHeight;
float prog = m_scroll[1] / float(cRect.size[1] - sub.size[1]);
int x = sub.size[0];
int y = sub.size[1] - scrollHeight * prog;
m_verts[0].m_pos.assign(x, y, 0);
m_verts[1].m_pos.assign(x, y-barHeight, 0);
m_verts[2].m_pos.assign(x+2*pf, y, 0);
m_verts[3].m_pos.assign(x+2*pf, y-barHeight, 0);
const zeus::CColor& color = rootView().themeData().scrollIndicator();
for (int i=0 ; i<4 ; ++i)
m_verts[i].m_color = color;
m_vertsBinding.load<decltype(m_verts)>(m_verts);
}
}
else if (m_style == Style::SideButtons && m_drawSideButtons)
{
boo::SWindowRect bRect = sub;
bRect.size[0] = m_sideButtons[0].m_view->nominalWidth();
bRect.size[1] = m_sideButtons[0].m_view->nominalHeight();
m_sideButtons[0].m_view->resized(root, bRect);
bRect.size[0] = m_sideButtons[1].m_view->nominalWidth(); void ScrollView::mouseEnter(const boo::SWindowCoord& coord) {
bRect.size[1] = m_sideButtons[1].m_view->nominalHeight(); if (m_style == Style::SideButtons && m_drawSideButtons) {
bRect.location[0] += sub.size[0] - bRect.size[0]; m_sideButtons[0].mouseEnter(coord);
m_sideButtons[1].m_view->resized(root, bRect); m_sideButtons[1].mouseEnter(coord);
} }
m_contentView.mouseEnter(coord);
}
void ScrollView::mouseLeave(const boo::SWindowCoord& coord) {
if (m_style == Style::SideButtons) {
m_sideButtons[0].mouseLeave(coord);
m_sideButtons[1].mouseLeave(coord);
}
m_contentView.mouseLeave(coord);
}
void ScrollView::scroll(const boo::SWindowCoord& coord, const boo::SScrollDelta& scroll) {
if (!scroll.isAccelerated) {
boo::SScrollDelta newScroll = scroll;
m_consecutiveScroll[m_consecutiveIdx][0] += scroll.delta[0];
m_consecutiveScroll[m_consecutiveIdx][1] += scroll.delta[1];
newScroll.delta[0] = 0;
newScroll.delta[1] = 0;
for (size_t i = 0; i < 16; ++i) {
newScroll.delta[0] += m_consecutiveScroll[i][0];
newScroll.delta[1] += m_consecutiveScroll[i][1];
} }
if (_scroll(newScroll))
updateSize();
return;
}
if (_scroll(scroll))
updateSize();
} }
void ScrollView::draw(boo::IGraphicsCommandQueue* gfxQ) void ScrollView::setMultiplyColor(const zeus::CColor& color) {
{ View::setMultiplyColor(color);
if (m_contentView.m_view) if (m_style == Style::SideButtons) {
{ m_sideButtons[0].m_view->setMultiplyColor(color);
m_contentView.m_view->draw(gfxQ); m_sideButtons[1].m_view->setMultiplyColor(color);
}
if (m_contentView.m_view)
m_contentView.m_view->setMultiplyColor(color);
}
if (m_style == Style::ThinIndicator && m_drawInd) void ScrollView::think() {
{ m_consecutiveIdx = (m_consecutiveIdx + 1) % 16;
gfxQ->setShaderDataBinding(m_vertsBinding); m_consecutiveScroll[m_consecutiveIdx][0] = 0.0;
gfxQ->draw(0, 4); m_consecutiveScroll[m_consecutiveIdx][1] = 0.0;
}
else if (m_style == Style::SideButtons && m_drawSideButtons) if (m_sideButtonState != SideButtonState::None) {
{ if (m_sideButtonState == SideButtonState::ScrollLeft)
m_sideButtons[0].m_view->draw(gfxQ); m_targetScroll[0] -= 3;
m_sideButtons[1].m_view->draw(gfxQ); else if (m_sideButtonState == SideButtonState::ScrollRight)
} m_targetScroll[0] += 3;
m_targetScroll[0] = std::min(m_targetScroll[0], 0);
int scrollWidth = m_contentView.m_view->nominalWidth() - scrollAreaWidth();
m_targetScroll[0] = std::max(m_targetScroll[0], -scrollWidth);
}
bool update = false;
float pf = rootView().viewRes().pixelFactor();
int xSpeed = std::max(1, std::min(abs(m_targetScroll[0] - m_scroll[0]) / int(5 * pf), int(pf * MAX_SCROLL_SPEED)));
if (m_scroll[0] < m_targetScroll[0]) {
m_scroll[0] += xSpeed;
update = true;
} else if (m_scroll[0] > m_targetScroll[0]) {
m_scroll[0] -= xSpeed;
update = true;
}
int ySpeed = std::max(1, std::min(abs(m_targetScroll[1] - m_scroll[1]) / int(5 * pf), int(pf * MAX_SCROLL_SPEED)));
if (m_scroll[1] < m_targetScroll[1]) {
m_scroll[1] += ySpeed;
update = true;
} else if (m_scroll[1] > m_targetScroll[1]) {
m_scroll[1] -= ySpeed;
update = true;
}
if (update)
updateSize();
}
void ScrollView::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) {
View::resized(root, sub);
_scroll({});
if (m_contentView.m_view) {
boo::SWindowRect cRect = sub;
cRect.location[0] += m_scroll[0];
cRect.location[1] += sub.size[1] - m_contentView.m_view->nominalHeight() + m_scroll[1];
cRect.size[0] = m_contentView.m_view->nominalWidth();
cRect.size[1] = m_contentView.m_view->nominalHeight();
m_contentView.m_scissorRect = sub;
if (m_style == Style::SideButtons && m_drawSideButtons) {
int width0 = m_sideButtons[0].m_view->nominalWidth() + 2;
int width1 = m_sideButtons[1].m_view->nominalWidth();
cRect.location[0] += width0;
cRect.size[0] -= (width0 + width1);
m_contentView.m_scissorRect.location[0] += width0;
m_contentView.m_scissorRect.size[0] -= (width0 + width1);
} }
m_contentView.m_view->resized(root, cRect, m_contentView.m_scissorRect);
if (m_style == Style::ThinIndicator) {
float ratio = sub.size[1] / float(cRect.size[1]);
m_drawInd = ratio < 1.f;
if (m_drawInd) {
float pf = rootView().viewRes().pixelFactor();
int barHeight = sub.size[1] * ratio;
int scrollHeight = sub.size[1] - barHeight;
float prog = m_scroll[1] / float(cRect.size[1] - sub.size[1]);
int x = sub.size[0];
int y = sub.size[1] - scrollHeight * prog;
m_verts[0].m_pos.assign(x, y, 0);
m_verts[1].m_pos.assign(x, y - barHeight, 0);
m_verts[2].m_pos.assign(x + 2 * pf, y, 0);
m_verts[3].m_pos.assign(x + 2 * pf, y - barHeight, 0);
const zeus::CColor& color = rootView().themeData().scrollIndicator();
for (int i = 0; i < 4; ++i)
m_verts[i].m_color = color;
m_vertsBinding.load<decltype(m_verts)>(m_verts);
}
} else if (m_style == Style::SideButtons && m_drawSideButtons) {
boo::SWindowRect bRect = sub;
bRect.size[0] = m_sideButtons[0].m_view->nominalWidth();
bRect.size[1] = m_sideButtons[0].m_view->nominalHeight();
m_sideButtons[0].m_view->resized(root, bRect);
bRect.size[0] = m_sideButtons[1].m_view->nominalWidth();
bRect.size[1] = m_sideButtons[1].m_view->nominalHeight();
bRect.location[0] += sub.size[0] - bRect.size[0];
m_sideButtons[1].m_view->resized(root, bRect);
}
}
} }
void ScrollView::draw(boo::IGraphicsCommandQueue* gfxQ) {
if (m_contentView.m_view) {
m_contentView.m_view->draw(gfxQ);
if (m_style == Style::ThinIndicator && m_drawInd) {
gfxQ->setShaderDataBinding(m_vertsBinding);
gfxQ->draw(0, 4);
} else if (m_style == Style::SideButtons && m_drawSideButtons) {
m_sideButtons[0].m_view->draw(gfxQ);
m_sideButtons[1].m_view->draw(gfxQ);
}
}
} }
} // namespace specter

View File

@ -3,8 +3,7 @@
#include "specter/ViewResources.hpp" #include "specter/ViewResources.hpp"
#include "specter/RootView.hpp" #include "specter/RootView.hpp"
namespace specter namespace specter {
{
static logvisor::Module Log("specter::Space"); static logvisor::Module Log("specter::Space");
#define TRIANGLE_DIM 12 #define TRIANGLE_DIM 12
@ -18,343 +17,282 @@ static logvisor::Module Log("specter::Space");
static const zeus::CColor TriColor = {0.75, 0.75, 0.75, 1.0}; static const zeus::CColor TriColor = {0.75, 0.75, 0.75, 1.0};
Space::Space(ViewResources& res, View& parentView, ISpaceController& controller, Space::Space(ViewResources& res, View& parentView, ISpaceController& controller, Toolbar::Position tbPos,
Toolbar::Position tbPos, unsigned tbUnits) unsigned tbUnits)
: View(res, parentView), m_controller(controller), m_tbPos(tbPos) : View(res, parentView), m_controller(controller), m_tbPos(tbPos) {
{ commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool {
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool buildResources(ctx, res);
{ return true;
buildResources(ctx, res); });
return true; setBackground(res.themeData().spaceBackground());
}); if (controller.spaceSplitAllowed())
setBackground(res.themeData().spaceBackground()); m_cornerView.m_view.reset(new CornerView(res, *this, TriColor));
if (controller.spaceSplitAllowed()) if (tbPos != Toolbar::Position::None)
m_cornerView.m_view.reset(new CornerView(res, *this, TriColor)); m_toolbar.m_view.reset(new Toolbar(res, *this, tbPos, tbUnits));
if (tbPos != Toolbar::Position::None)
m_toolbar.m_view.reset(new Toolbar(res, *this, tbPos, tbUnits));
} }
Space::CornerView::CornerView(ViewResources& res, Space& space, const zeus::CColor& triColor) Space::CornerView::CornerView(ViewResources& res, Space& space, const zeus::CColor& triColor)
: View(res, space), m_space(space) : View(res, space), m_space(space) {
{ commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool {
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool buildResources(ctx, res);
{ m_vertexBinding.init(ctx, res, 34, m_viewVertBlockBuf);
buildResources(ctx, res); return true;
m_vertexBinding.init(ctx, res, 34, m_viewVertBlockBuf); });
return true; float pf = res.pixelFactor();
});
float pf = res.pixelFactor();
zeus::CColor edgeColor1 = triColor * res.themeData().spaceTriangleShading1(); zeus::CColor edgeColor1 = triColor * res.themeData().spaceTriangleShading1();
zeus::CColor edgeColor2 = triColor * res.themeData().spaceTriangleShading2(); zeus::CColor edgeColor2 = triColor * res.themeData().spaceTriangleShading2();
View::SolidShaderVert verts[34]; View::SolidShaderVert verts[34];
verts[0].m_pos.assign(0, TRIANGLE_DIM * pf, 0); verts[0].m_pos.assign(0, TRIANGLE_DIM * pf, 0);
verts[0].m_color = edgeColor1; verts[0].m_color = edgeColor1;
verts[1].m_pos.assign(TRIANGLE_DIM * pf, 0, 0); verts[1].m_pos.assign(TRIANGLE_DIM * pf, 0, 0);
verts[1].m_color = edgeColor1; verts[1].m_color = edgeColor1;
verts[2].m_pos.assign(0, (TRIANGLE_DIM + 1) * pf, 0); verts[2].m_pos.assign(0, (TRIANGLE_DIM + 1) * pf, 0);
verts[2].m_color = edgeColor1; verts[2].m_color = edgeColor1;
verts[3].m_pos.assign((TRIANGLE_DIM + 1) * pf, 0, 0); verts[3].m_pos.assign((TRIANGLE_DIM + 1) * pf, 0, 0);
verts[3].m_color = edgeColor1; verts[3].m_color = edgeColor1;
verts[4] = verts[3]; verts[4] = verts[3];
verts[5].m_pos.assign(0, TRIANGLE_DIM1 * pf, 0); verts[5].m_pos.assign(0, TRIANGLE_DIM1 * pf, 0);
verts[5].m_color = edgeColor2; verts[5].m_color = edgeColor2;
verts[6] = verts[5]; verts[6] = verts[5];
verts[7].m_pos.assign(TRIANGLE_DIM1 * pf, 0, 0); verts[7].m_pos.assign(TRIANGLE_DIM1 * pf, 0, 0);
verts[7].m_color = edgeColor2; verts[7].m_color = edgeColor2;
verts[8].m_pos.assign(0, (TRIANGLE_DIM1 + 1) * pf, 0); verts[8].m_pos.assign(0, (TRIANGLE_DIM1 + 1) * pf, 0);
verts[8].m_color = edgeColor2; verts[8].m_color = edgeColor2;
verts[9].m_pos.assign((TRIANGLE_DIM1 + 1) * pf, 0, 0); verts[9].m_pos.assign((TRIANGLE_DIM1 + 1) * pf, 0, 0);
verts[9].m_color = edgeColor2; verts[9].m_color = edgeColor2;
verts[10] = verts[9]; verts[10] = verts[9];
verts[11].m_pos.assign(0, TRIANGLE_DIM2 * pf, 0); verts[11].m_pos.assign(0, TRIANGLE_DIM2 * pf, 0);
verts[11].m_color = edgeColor2; verts[11].m_color = edgeColor2;
verts[12] = verts[11]; verts[12] = verts[11];
verts[13].m_pos.assign(TRIANGLE_DIM2 * pf, 0, 0); verts[13].m_pos.assign(TRIANGLE_DIM2 * pf, 0, 0);
verts[13].m_color = edgeColor2; verts[13].m_color = edgeColor2;
verts[14].m_pos.assign(0, (TRIANGLE_DIM2 + 1) * pf, 0); verts[14].m_pos.assign(0, (TRIANGLE_DIM2 + 1) * pf, 0);
verts[14].m_color = edgeColor2; verts[14].m_color = edgeColor2;
verts[15].m_pos.assign((TRIANGLE_DIM2 + 1) * pf, 0, 0); verts[15].m_pos.assign((TRIANGLE_DIM2 + 1) * pf, 0, 0);
verts[15].m_color = edgeColor2; verts[15].m_color = edgeColor2;
verts[16] = verts[15]; verts[16] = verts[15];
verts[17].m_pos.assign(0, TRIANGLE_DIM3 * pf, 0); verts[17].m_pos.assign(0, TRIANGLE_DIM3 * pf, 0);
verts[17].m_color = edgeColor2; verts[17].m_color = edgeColor2;
verts[18] = verts[17]; verts[18] = verts[17];
verts[19].m_pos.assign(TRIANGLE_DIM3 * pf, 0, 0); verts[19].m_pos.assign(TRIANGLE_DIM3 * pf, 0, 0);
verts[19].m_color = edgeColor2; verts[19].m_color = edgeColor2;
verts[20].m_pos.assign(0, (TRIANGLE_DIM3 + 1) * pf, 0); verts[20].m_pos.assign(0, (TRIANGLE_DIM3 + 1) * pf, 0);
verts[20].m_color = edgeColor2; verts[20].m_color = edgeColor2;
verts[21].m_pos.assign((TRIANGLE_DIM3 + 1) * pf, 0, 0); verts[21].m_pos.assign((TRIANGLE_DIM3 + 1) * pf, 0, 0);
verts[21].m_color = edgeColor2; verts[21].m_color = edgeColor2;
verts[22] = verts[21]; verts[22] = verts[21];
verts[23].m_pos.assign(0, TRIANGLE_DIM4 * pf, 0); verts[23].m_pos.assign(0, TRIANGLE_DIM4 * pf, 0);
verts[23].m_color = edgeColor2; verts[23].m_color = edgeColor2;
verts[24] = verts[23]; verts[24] = verts[23];
verts[25].m_pos.assign(TRIANGLE_DIM4 * pf, 0, 0); verts[25].m_pos.assign(TRIANGLE_DIM4 * pf, 0, 0);
verts[25].m_color = edgeColor2; verts[25].m_color = edgeColor2;
verts[26].m_pos.assign(0, (TRIANGLE_DIM4 + 1) * pf, 0); verts[26].m_pos.assign(0, (TRIANGLE_DIM4 + 1) * pf, 0);
verts[26].m_color = edgeColor2; verts[26].m_color = edgeColor2;
verts[27].m_pos.assign((TRIANGLE_DIM4 + 1) * pf, 0, 0); verts[27].m_pos.assign((TRIANGLE_DIM4 + 1) * pf, 0, 0);
verts[27].m_color = edgeColor2; verts[27].m_color = edgeColor2;
verts[28] = verts[27]; verts[28] = verts[27];
verts[29].m_pos.assign(0, TRIANGLE_DIM5 * pf, 0); verts[29].m_pos.assign(0, TRIANGLE_DIM5 * pf, 0);
verts[29].m_color = edgeColor2; verts[29].m_color = edgeColor2;
verts[30] = verts[29]; verts[30] = verts[29];
verts[31].m_pos.assign(TRIANGLE_DIM5 * pf, 0, 0); verts[31].m_pos.assign(TRIANGLE_DIM5 * pf, 0, 0);
verts[31].m_color = edgeColor2; verts[31].m_color = edgeColor2;
verts[32].m_pos.assign(0, (TRIANGLE_DIM5 + 1) * pf, 0); verts[32].m_pos.assign(0, (TRIANGLE_DIM5 + 1) * pf, 0);
verts[32].m_color = edgeColor2; verts[32].m_color = edgeColor2;
verts[33].m_pos.assign((TRIANGLE_DIM5 + 1) * pf, 0, 0); verts[33].m_pos.assign((TRIANGLE_DIM5 + 1) * pf, 0, 0);
verts[33].m_color = edgeColor2; verts[33].m_color = edgeColor2;
m_vertexBinding.load<decltype(verts)>(verts); m_vertexBinding.load<decltype(verts)>(verts);
} }
View* Space::setContentView(View* view) View* Space::setContentView(View* view) {
{ View* ret = m_contentView.m_view;
View* ret = m_contentView.m_view; m_contentView.m_view = view;
m_contentView.m_view = view; updateSize();
updateSize(); return ret;
return ret;
} }
void Space::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) void Space::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
{ if (m_cornerView.mouseDown(coord, button, mod))
if (m_cornerView.mouseDown(coord, button, mod)) return;
return; m_contentView.mouseDown(coord, button, mod);
m_contentView.mouseDown(coord, button, mod); m_toolbar.mouseDown(coord, button, mod);
m_toolbar.mouseDown(coord, button, mod);
} }
void Space::CornerView::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) void Space::CornerView::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
{ if (button == boo::EMouseButton::Primary) {
if (button == boo::EMouseButton::Primary) m_space.m_cornerDrag = true;
{ m_space.m_cornerDragPoint[0] = coord.pixel[0];
m_space.m_cornerDrag = true; m_space.m_cornerDragPoint[1] = coord.pixel[1];
m_space.m_cornerDragPoint[0] = coord.pixel[0]; rootView().setActiveDragView(&m_space);
m_space.m_cornerDragPoint[1] = coord.pixel[1]; }
rootView().setActiveDragView(&m_space);
}
} }
void Space::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) void Space::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
{ m_cornerView.mouseUp(coord, button, mod);
m_cornerView.mouseUp(coord, button, mod); m_contentView.mouseUp(coord, button, mod);
m_contentView.mouseUp(coord, button, mod); m_toolbar.mouseUp(coord, button, mod);
m_toolbar.mouseUp(coord, button, mod);
} }
void Space::CornerView::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) void Space::CornerView::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
{ if (button == boo::EMouseButton::Primary) {
if (button == boo::EMouseButton::Primary) m_space.m_cornerDrag = false;
{ rootView().unsetActiveDragView(&m_space);
m_space.m_cornerDrag = false; }
rootView().unsetActiveDragView(&m_space);
}
} }
void Space::mouseMove(const boo::SWindowCoord& coord) void Space::mouseMove(const boo::SWindowCoord& coord) {
{ if (m_cornerDrag) {
if (m_cornerDrag)
{
float pf = rootView().viewRes().pixelFactor();
if (coord.pixel[0] < m_cornerDragPoint[0] - CORNER_DRAG_THRESHOLD * pf)
{
if (m_cornerView.m_view->m_flip)
{
rootView().mouseUp(coord, boo::EMouseButton::Primary, boo::EModifierKey::None);
rootView().viewManager().deferSpaceSplit(&m_controller, SplitView::Axis::Vertical, 1, coord);
}
else
{
SplitView* sv = findSplitViewOnSide(SplitView::Axis::Vertical, 0);
if (sv)
{
rootView().mouseUp(coord, boo::EMouseButton::Primary, boo::EModifierKey::None);
rootView().beginInteractiveJoin(sv, coord);
}
}
}
else if (coord.pixel[1] < m_cornerDragPoint[1] - CORNER_DRAG_THRESHOLD * pf)
{
if (m_cornerView.m_view->m_flip)
{
rootView().mouseUp(coord, boo::EMouseButton::Primary, boo::EModifierKey::None);
rootView().viewManager().deferSpaceSplit(&m_controller, SplitView::Axis::Horizontal, 1, coord);
}
else
{
SplitView* sv = findSplitViewOnSide(SplitView::Axis::Horizontal, 0);
if (sv)
{
rootView().mouseUp(coord, boo::EMouseButton::Primary, boo::EModifierKey::None);
rootView().beginInteractiveJoin(sv, coord);
}
}
}
else if (coord.pixel[0] > m_cornerDragPoint[0] + CORNER_DRAG_THRESHOLD * pf)
{
if (!m_cornerView.m_view->m_flip)
{
rootView().mouseUp(coord, boo::EMouseButton::Primary, boo::EModifierKey::None);
rootView().viewManager().deferSpaceSplit(&m_controller, SplitView::Axis::Vertical, 0, coord);
}
else
{
SplitView* sv = findSplitViewOnSide(SplitView::Axis::Vertical, 1);
if (sv)
{
rootView().mouseUp(coord, boo::EMouseButton::Primary, boo::EModifierKey::None);
rootView().beginInteractiveJoin(sv, coord);
}
}
}
else if (coord.pixel[1] > m_cornerDragPoint[1] + CORNER_DRAG_THRESHOLD * pf)
{
if (!m_cornerView.m_view->m_flip)
{
rootView().mouseUp(coord, boo::EMouseButton::Primary, boo::EModifierKey::None);
rootView().viewManager().deferSpaceSplit(&m_controller, SplitView::Axis::Horizontal, 0, coord);
}
else
{
SplitView* sv = findSplitViewOnSide(SplitView::Axis::Horizontal, 1);
if (sv)
{
rootView().mouseUp(coord, boo::EMouseButton::Primary, boo::EModifierKey::None);
rootView().beginInteractiveJoin(sv, coord);
}
}
}
}
else
{
m_cornerView.mouseMove(coord);
m_contentView.mouseMove(coord);
m_toolbar.mouseMove(coord);
}
}
void Space::mouseEnter(const boo::SWindowCoord& coord)
{
m_cornerView.mouseEnter(coord);
m_contentView.mouseEnter(coord);
m_toolbar.mouseEnter(coord);
}
void Space::CornerView::mouseEnter(const boo::SWindowCoord& coord)
{
rootView().setSpaceCornerHover(true);
}
void Space::mouseLeave(const boo::SWindowCoord& coord)
{
m_cornerView.mouseLeave(coord);
m_contentView.mouseLeave(coord);
m_toolbar.mouseLeave(coord);
}
void Space::CornerView::mouseLeave(const boo::SWindowCoord& coord)
{
rootView().setSpaceCornerHover(false);
}
SplitView* Space::findSplitViewOnSide(SplitView::Axis axis, int side)
{
SplitView* ret = parentView().castToSplitView();
View* test = this;
while (ret)
{
if (ret->axis() != axis)
return nullptr;
if (ret->m_views[side ^ 1].m_view == test)
return ret;
else if (ret->m_views[side].m_view == test)
test = ret;
ret = ret->parentView().castToSplitView();
}
return nullptr;
}
void Space::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub)
{
View::resized(root, sub);
float pf = rootView().viewRes().pixelFactor(); float pf = rootView().viewRes().pixelFactor();
if (m_cornerView.m_view) if (coord.pixel[0] < m_cornerDragPoint[0] - CORNER_DRAG_THRESHOLD * pf) {
{ if (m_cornerView.m_view->m_flip) {
boo::SWindowRect cornerRect = sub; rootView().mouseUp(coord, boo::EMouseButton::Primary, boo::EModifierKey::None);
int triDim = TRIANGLE_DIM * pf; rootView().viewManager().deferSpaceSplit(&m_controller, SplitView::Axis::Vertical, 1, coord);
cornerRect.size[0] = cornerRect.size[1] = triDim; } else {
if (cornerRect.location[0] < triDim && cornerRect.location[1] < triDim) SplitView* sv = findSplitViewOnSide(SplitView::Axis::Vertical, 0);
{ if (sv) {
cornerRect.location[0] += sub.size[0] - triDim; rootView().mouseUp(coord, boo::EMouseButton::Primary, boo::EModifierKey::None);
cornerRect.location[1] += sub.size[1] - triDim; rootView().beginInteractiveJoin(sv, coord);
m_cornerView.m_view->resized(root, cornerRect, true);
} }
else }
m_cornerView.m_view->resized(root, cornerRect, false); } else if (coord.pixel[1] < m_cornerDragPoint[1] - CORNER_DRAG_THRESHOLD * pf) {
} if (m_cornerView.m_view->m_flip) {
rootView().mouseUp(coord, boo::EMouseButton::Primary, boo::EModifierKey::None);
boo::SWindowRect tbRect = sub; rootView().viewManager().deferSpaceSplit(&m_controller, SplitView::Axis::Horizontal, 1, coord);
if (m_toolbar.m_view) } else {
{ SplitView* sv = findSplitViewOnSide(SplitView::Axis::Horizontal, 0);
tbRect.size[1] = m_toolbar.m_view->nominalHeight(); if (sv) {
if (m_tbPos == Toolbar::Position::Top) rootView().mouseUp(coord, boo::EMouseButton::Primary, boo::EModifierKey::None);
tbRect.location[1] += sub.size[1] - tbRect.size[1]; rootView().beginInteractiveJoin(sv, coord);
m_toolbar.m_view->resized(root, tbRect); }
} }
else } else if (coord.pixel[0] > m_cornerDragPoint[0] + CORNER_DRAG_THRESHOLD * pf) {
tbRect.size[1] = 0; if (!m_cornerView.m_view->m_flip) {
rootView().mouseUp(coord, boo::EMouseButton::Primary, boo::EModifierKey::None);
if (m_contentView.m_view) rootView().viewManager().deferSpaceSplit(&m_controller, SplitView::Axis::Vertical, 0, coord);
{ } else {
boo::SWindowRect contentRect = sub; SplitView* sv = findSplitViewOnSide(SplitView::Axis::Vertical, 1);
if (m_tbPos == Toolbar::Position::Bottom) if (sv) {
contentRect.location[1] += tbRect.size[1]; rootView().mouseUp(coord, boo::EMouseButton::Primary, boo::EModifierKey::None);
contentRect.size[1] = sub.size[1] - tbRect.size[1]; rootView().beginInteractiveJoin(sv, coord);
contentRect.size[1] = std::max(contentRect.size[1], 0); }
m_contentView.m_view->resized(root, contentRect); }
} else if (coord.pixel[1] > m_cornerDragPoint[1] + CORNER_DRAG_THRESHOLD * pf) {
if (!m_cornerView.m_view->m_flip) {
rootView().mouseUp(coord, boo::EMouseButton::Primary, boo::EModifierKey::None);
rootView().viewManager().deferSpaceSplit(&m_controller, SplitView::Axis::Horizontal, 0, coord);
} else {
SplitView* sv = findSplitViewOnSide(SplitView::Axis::Horizontal, 1);
if (sv) {
rootView().mouseUp(coord, boo::EMouseButton::Primary, boo::EModifierKey::None);
rootView().beginInteractiveJoin(sv, coord);
}
}
} }
} else {
m_cornerView.mouseMove(coord);
m_contentView.mouseMove(coord);
m_toolbar.mouseMove(coord);
}
} }
void Space::CornerView::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub, bool flip) void Space::mouseEnter(const boo::SWindowCoord& coord) {
{ m_cornerView.mouseEnter(coord);
m_flip = flip; m_contentView.mouseEnter(coord);
if (flip) m_toolbar.mouseEnter(coord);
{
m_viewVertBlock.m_mv[0][0] = -2.0f / root.size[0];
m_viewVertBlock.m_mv[1][1] = -2.0f / root.size[1];
m_viewVertBlock.m_mv[3][0] = (sub.location[0] + sub.size[0]) * -m_viewVertBlock.m_mv[0][0] - 1.0f;
m_viewVertBlock.m_mv[3][1] = (sub.location[1] + sub.size[1]) * -m_viewVertBlock.m_mv[1][1] - 1.0f;
View::resized(m_viewVertBlock, sub);
}
else
View::resized(root, sub);
} }
void Space::draw(boo::IGraphicsCommandQueue* gfxQ) void Space::CornerView::mouseEnter(const boo::SWindowCoord& coord) { rootView().setSpaceCornerHover(true); }
{
View::draw(gfxQ); void Space::mouseLeave(const boo::SWindowCoord& coord) {
if (m_contentView.m_view) m_cornerView.mouseLeave(coord);
m_contentView.m_view->draw(gfxQ); m_contentView.mouseLeave(coord);
if (m_toolbar.m_view) m_toolbar.mouseLeave(coord);
m_toolbar.m_view->draw(gfxQ);
if (m_cornerView.m_view)
m_cornerView.m_view->draw(gfxQ);
} }
void Space::CornerView::draw(boo::IGraphicsCommandQueue* gfxQ) void Space::CornerView::mouseLeave(const boo::SWindowCoord& coord) { rootView().setSpaceCornerHover(false); }
{
gfxQ->setShaderDataBinding(m_vertexBinding); SplitView* Space::findSplitViewOnSide(SplitView::Axis axis, int side) {
gfxQ->draw(0, 34); SplitView* ret = parentView().castToSplitView();
View* test = this;
while (ret) {
if (ret->axis() != axis)
return nullptr;
if (ret->m_views[side ^ 1].m_view == test)
return ret;
else if (ret->m_views[side].m_view == test)
test = ret;
ret = ret->parentView().castToSplitView();
}
return nullptr;
} }
void Space::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) {
View::resized(root, sub);
float pf = rootView().viewRes().pixelFactor();
if (m_cornerView.m_view) {
boo::SWindowRect cornerRect = sub;
int triDim = TRIANGLE_DIM * pf;
cornerRect.size[0] = cornerRect.size[1] = triDim;
if (cornerRect.location[0] < triDim && cornerRect.location[1] < triDim) {
cornerRect.location[0] += sub.size[0] - triDim;
cornerRect.location[1] += sub.size[1] - triDim;
m_cornerView.m_view->resized(root, cornerRect, true);
} else
m_cornerView.m_view->resized(root, cornerRect, false);
}
boo::SWindowRect tbRect = sub;
if (m_toolbar.m_view) {
tbRect.size[1] = m_toolbar.m_view->nominalHeight();
if (m_tbPos == Toolbar::Position::Top)
tbRect.location[1] += sub.size[1] - tbRect.size[1];
m_toolbar.m_view->resized(root, tbRect);
} else
tbRect.size[1] = 0;
if (m_contentView.m_view) {
boo::SWindowRect contentRect = sub;
if (m_tbPos == Toolbar::Position::Bottom)
contentRect.location[1] += tbRect.size[1];
contentRect.size[1] = sub.size[1] - tbRect.size[1];
contentRect.size[1] = std::max(contentRect.size[1], 0);
m_contentView.m_view->resized(root, contentRect);
}
} }
void Space::CornerView::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub, bool flip) {
m_flip = flip;
if (flip) {
m_viewVertBlock.m_mv[0][0] = -2.0f / root.size[0];
m_viewVertBlock.m_mv[1][1] = -2.0f / root.size[1];
m_viewVertBlock.m_mv[3][0] = (sub.location[0] + sub.size[0]) * -m_viewVertBlock.m_mv[0][0] - 1.0f;
m_viewVertBlock.m_mv[3][1] = (sub.location[1] + sub.size[1]) * -m_viewVertBlock.m_mv[1][1] - 1.0f;
View::resized(m_viewVertBlock, sub);
} else
View::resized(root, sub);
}
void Space::draw(boo::IGraphicsCommandQueue* gfxQ) {
View::draw(gfxQ);
if (m_contentView.m_view)
m_contentView.m_view->draw(gfxQ);
if (m_toolbar.m_view)
m_toolbar.m_view->draw(gfxQ);
if (m_cornerView.m_view)
m_cornerView.m_view->draw(gfxQ);
}
void Space::CornerView::draw(boo::IGraphicsCommandQueue* gfxQ) {
gfxQ->setShaderDataBinding(m_vertexBinding);
gfxQ->draw(0, 34);
}
} // namespace specter

View File

@ -4,492 +4,401 @@
#include "specter/ViewResources.hpp" #include "specter/ViewResources.hpp"
#include "specter/Space.hpp" #include "specter/Space.hpp"
namespace specter namespace specter {
{
static logvisor::Module Log("specter::SplitView"); static logvisor::Module Log("specter::SplitView");
static const zeus::RGBA32 Tex[3] = static const zeus::RGBA32 Tex[3] = {{{0, 0, 0, 64}}, {{0, 0, 0, 255}}, {{255, 255, 255, 64}}};
{
{{0,0,0,64}},
{{0,0,0,255}},
{{255,255,255,64}}
};
void SplitView::Resources::init(boo::IGraphicsDataFactory::Context& ctx, const IThemeData& theme) void SplitView::Resources::init(boo::IGraphicsDataFactory::Context& ctx, const IThemeData& theme) {
{ m_shadingTex = ctx.newStaticTexture(3, 1, 1, boo::TextureFormat::RGBA8, boo::TextureClampMode::Repeat, Tex, 12);
m_shadingTex = ctx.newStaticTexture(3, 1, 1, boo::TextureFormat::RGBA8, boo::TextureClampMode::Repeat, Tex, 12);
} }
SplitView::SplitView(ViewResources& res, View& parentView, ISplitSpaceController* controller, SplitView::SplitView(ViewResources& res, View& parentView, ISplitSpaceController* controller, Axis axis, float split,
Axis axis, float split, int clearanceA, int clearanceB) int clearanceA, int clearanceB)
: View(res, parentView), m_controller(controller), m_axis(axis), m_slide(split), : View(res, parentView)
m_clearanceA(clearanceA), m_clearanceB(clearanceB) , m_controller(controller)
{ , m_axis(axis)
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool , m_slide(split)
{ , m_clearanceA(clearanceA)
buildResources(ctx, res); , m_clearanceB(clearanceB) {
m_splitBlockBuf = res.m_viewRes.m_bufPool.allocateBlock(res.m_factory); commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool {
m_splitVertsBinding.init(ctx, res, 4, m_splitBlockBuf, res.m_splitRes.m_shadingTex.get()); buildResources(ctx, res);
return true; m_splitBlockBuf = res.m_viewRes.m_bufPool.allocateBlock(res.m_factory);
}); m_splitVertsBinding.init(ctx, res, 4, m_splitBlockBuf, res.m_splitRes.m_shadingTex.get());
return true;
});
} }
View* SplitView::setContentView(int slot, View* view) View* SplitView::setContentView(int slot, View* view) {
{ if (slot < 0 || slot > 1)
if (slot < 0 || slot > 1) Log.report(logvisor::Fatal, "out-of-range slot to RootView::SplitView::setContentView");
Log.report(logvisor::Fatal, "out-of-range slot to RootView::SplitView::setContentView"); View* ret = m_views[slot].m_view;
View* ret = m_views[slot].m_view; m_views[slot].m_view = view;
m_views[slot].m_view = view; m_views[slot].m_mouseDown = 0;
m_views[slot].m_mouseDown = 0; m_views[slot].m_mouseIn = false;
m_views[slot].m_mouseIn = false; updateSize();
updateSize(); return ret;
return ret;
} }
void SplitView::_setSplit(float slide) void SplitView::_setSplit(float slide) {
{ m_slide = std::min(std::max(slide, 0.0f), 1.0f);
m_slide = std::min(std::max(slide, 0.0f), 1.0f); const boo::SWindowRect& rect = subRect();
const boo::SWindowRect& rect = subRect(); if (rect.size[0] && rect.size[1] && (m_clearanceA >= 0 || m_clearanceB >= 0)) {
if (rect.size[0] && rect.size[1] && if (m_axis == Axis::Horizontal) {
(m_clearanceA >= 0 || m_clearanceB >= 0)) int slidePx = rect.size[1] * m_slide;
{ if (m_clearanceA >= 0 && slidePx < m_clearanceA)
if (m_axis == Axis::Horizontal) m_slide = m_clearanceA / float(rect.size[1]);
{ if (m_clearanceB >= 0 && (rect.size[1] - slidePx) < m_clearanceB)
int slidePx = rect.size[1] * m_slide; m_slide = 1.0 - m_clearanceB / float(rect.size[1]);
if (m_clearanceA >= 0 && slidePx < m_clearanceA) } else if (m_axis == Axis::Vertical) {
m_slide = m_clearanceA / float(rect.size[1]); int slidePx = rect.size[0] * m_slide;
if (m_clearanceB >= 0 && (rect.size[1] - slidePx) < m_clearanceB) if (m_clearanceA >= 0 && slidePx < m_clearanceA)
m_slide = 1.0 - m_clearanceB / float(rect.size[1]); m_slide = m_clearanceA / float(rect.size[0]);
} if (m_clearanceB >= 0 && (rect.size[0] - slidePx) < m_clearanceB)
else if (m_axis == Axis::Vertical) m_slide = 1.0 - m_clearanceB / float(rect.size[0]);
{
int slidePx = rect.size[0] * m_slide;
if (m_clearanceA >= 0 && slidePx < m_clearanceA)
m_slide = m_clearanceA / float(rect.size[0]);
if (m_clearanceB >= 0 && (rect.size[0] - slidePx) < m_clearanceB)
m_slide = 1.0 - m_clearanceB / float(rect.size[0]);
}
m_slide = std::min(std::max(m_slide, 0.0f), 1.0f);
} }
if (m_controller) m_slide = std::min(std::max(m_slide, 0.0f), 1.0f);
m_controller->updateSplit(m_slide); }
if (m_controller)
m_controller->updateSplit(m_slide);
} }
void SplitView::setSplit(float slide) void SplitView::setSplit(float slide) {
{ _setSplit(slide);
_setSplit(slide); updateSize();
updateSize();
} }
void SplitView::setAxis(Axis axis) void SplitView::setAxis(Axis axis) {
{ m_axis = axis;
m_axis = axis; setSplit(m_slide);
setSplit(m_slide);
} }
bool SplitView::testSplitHover(const boo::SWindowCoord& coord) bool SplitView::testSplitHover(const boo::SWindowCoord& coord) {
{ if (m_axis == Axis::Horizontal) {
if (m_axis == Axis::Horizontal) int slidePx = subRect().size[1] * m_slide;
{ if (abs(int(coord.pixel[1] - subRect().location[1]) - slidePx) < 4)
int slidePx = subRect().size[1] * m_slide; return true;
if (abs(int(coord.pixel[1] - subRect().location[1]) - slidePx) < 4) } else if (m_axis == Axis::Vertical) {
return true; int slidePx = subRect().size[0] * m_slide;
} if (abs(int(coord.pixel[0] - subRect().location[0]) - slidePx) < 4)
else if (m_axis == Axis::Vertical) return true;
{ }
int slidePx = subRect().size[0] * m_slide; return false;
if (abs(int(coord.pixel[0] - subRect().location[0]) - slidePx) < 4) }
return true;
} bool SplitView::testJoinArrowHover(const boo::SWindowCoord& coord, int& origSlotOut, SplitView*& splitOut, int& slotOut,
boo::SWindowRect& rectOut, ArrowDir& dirOut, int forceSlot) {
if (!subRect().coordInRect(coord))
return false; return false;
}
bool SplitView::testJoinArrowHover(const boo::SWindowCoord& coord, int& origSlotOut, int origDummy;
SplitView*& splitOut, int& slotOut, ArrowDir dirDummy;
boo::SWindowRect& rectOut, ArrowDir& dirOut, int forceSlot)
{
if (!subRect().coordInRect(coord))
return false;
int origDummy; if (m_axis == Axis::Horizontal) {
ArrowDir dirDummy; int slidePx = subRect().size[1] * m_slide;
if ((forceSlot == -1 && coord.pixel[1] - subRect().location[1] - slidePx >= 0) || forceSlot == 1) {
if (m_axis == Axis::Horizontal) origSlotOut = 0;
{ dirOut = ArrowDir::Up;
int slidePx = subRect().size[1] * m_slide; if (m_views[1].m_view) {
if ((forceSlot == -1 && coord.pixel[1] - subRect().location[1] - slidePx >= 0) || forceSlot == 1) SplitView* chSplit = m_views[1].m_view->castToSplitView();
{ if (chSplit && chSplit->m_axis == Axis::Horizontal)
origSlotOut = 0; return chSplit->testJoinArrowHover(coord, origDummy, splitOut, slotOut, rectOut, dirDummy, 0);
dirOut = ArrowDir::Up; }
if (m_views[1].m_view) splitOut = this;
{ slotOut = 1;
SplitView* chSplit = m_views[1].m_view->castToSplitView(); rectOut = subRect();
if (chSplit && chSplit->m_axis == Axis::Horizontal) rectOut.location[1] += slidePx;
return chSplit->testJoinArrowHover(coord, origDummy, splitOut, slotOut, rectOut, dirDummy, 0); rectOut.size[1] -= slidePx;
} return true;
splitOut = this; } else {
slotOut = 1; origSlotOut = 1;
rectOut = subRect(); dirOut = ArrowDir::Down;
rectOut.location[1] += slidePx; if (m_views[0].m_view) {
rectOut.size[1] -= slidePx; SplitView* chSplit = m_views[0].m_view->castToSplitView();
return true; if (chSplit && chSplit->m_axis == Axis::Horizontal)
} return chSplit->testJoinArrowHover(coord, origDummy, splitOut, slotOut, rectOut, dirDummy, 1);
else }
{ splitOut = this;
origSlotOut = 1; slotOut = 0;
dirOut = ArrowDir::Down; rectOut = subRect();
if (m_views[0].m_view) rectOut.size[1] = slidePx;
{ return true;
SplitView* chSplit = m_views[0].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Horizontal)
return chSplit->testJoinArrowHover(coord, origDummy, splitOut, slotOut, rectOut, dirDummy, 1);
}
splitOut = this;
slotOut = 0;
rectOut = subRect();
rectOut.size[1] = slidePx;
return true;
}
} }
else } else {
{ int slidePx = subRect().size[0] * m_slide;
int slidePx = subRect().size[0] * m_slide; if ((forceSlot == -1 && coord.pixel[0] - subRect().location[0] - slidePx >= 0) || forceSlot == 1) {
if ((forceSlot == -1 && coord.pixel[0] - subRect().location[0] - slidePx >= 0) || forceSlot == 1) origSlotOut = 0;
{ dirOut = ArrowDir::Right;
origSlotOut = 0; if (m_views[1].m_view) {
dirOut = ArrowDir::Right; SplitView* chSplit = m_views[1].m_view->castToSplitView();
if (m_views[1].m_view) if (chSplit && chSplit->m_axis == Axis::Vertical)
{ return chSplit->testJoinArrowHover(coord, origDummy, splitOut, slotOut, rectOut, dirDummy, 0);
SplitView* chSplit = m_views[1].m_view->castToSplitView(); }
if (chSplit && chSplit->m_axis == Axis::Vertical) splitOut = this;
return chSplit->testJoinArrowHover(coord, origDummy, splitOut, slotOut, rectOut, dirDummy, 0); slotOut = 1;
} rectOut = subRect();
splitOut = this; rectOut.location[0] += slidePx;
slotOut = 1; rectOut.size[0] -= slidePx;
rectOut = subRect(); return true;
rectOut.location[0] += slidePx; } else {
rectOut.size[0] -= slidePx; origSlotOut = 1;
return true; dirOut = ArrowDir::Left;
} if (m_views[0].m_view) {
else SplitView* chSplit = m_views[0].m_view->castToSplitView();
{ if (chSplit && chSplit->m_axis == Axis::Vertical)
origSlotOut = 1; return chSplit->testJoinArrowHover(coord, origDummy, splitOut, slotOut, rectOut, dirDummy, 1);
dirOut = ArrowDir::Left; }
if (m_views[0].m_view) splitOut = this;
{ slotOut = 0;
SplitView* chSplit = m_views[0].m_view->castToSplitView(); rectOut = subRect();
if (chSplit && chSplit->m_axis == Axis::Vertical) rectOut.size[0] = slidePx;
return chSplit->testJoinArrowHover(coord, origDummy, splitOut, slotOut, rectOut, dirDummy, 1); return true;
}
splitOut = this;
slotOut = 0;
rectOut = subRect();
rectOut.size[0] = slidePx;
return true;
}
} }
}
} }
void SplitView::getJoinArrowHover(int slot, boo::SWindowRect& rectOut, ArrowDir& dirOut) void SplitView::getJoinArrowHover(int slot, boo::SWindowRect& rectOut, ArrowDir& dirOut) {
{ if (m_axis == Axis::Horizontal) {
if (m_axis == Axis::Horizontal) int slidePx = subRect().size[1] * m_slide;
{ if (slot == 1) {
int slidePx = subRect().size[1] * m_slide; if (m_views[1].m_view) {
if (slot == 1) SplitView* chSplit = m_views[1].m_view->castToSplitView();
{ if (chSplit && chSplit->m_axis == Axis::Horizontal)
if (m_views[1].m_view) return chSplit->getJoinArrowHover(0, rectOut, dirOut);
{ }
SplitView* chSplit = m_views[1].m_view->castToSplitView(); rectOut = subRect();
if (chSplit && chSplit->m_axis == Axis::Horizontal) rectOut.location[1] += slidePx;
return chSplit->getJoinArrowHover(0, rectOut, dirOut); rectOut.size[1] -= slidePx;
} dirOut = ArrowDir::Up;
rectOut = subRect(); } else {
rectOut.location[1] += slidePx; if (m_views[0].m_view) {
rectOut.size[1] -= slidePx; SplitView* chSplit = m_views[0].m_view->castToSplitView();
dirOut = ArrowDir::Up; if (chSplit && chSplit->m_axis == Axis::Horizontal)
} return chSplit->getJoinArrowHover(1, rectOut, dirOut);
else }
{ rectOut = subRect();
if (m_views[0].m_view) rectOut.size[1] = slidePx;
{ dirOut = ArrowDir::Down;
SplitView* chSplit = m_views[0].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Horizontal)
return chSplit->getJoinArrowHover(1, rectOut, dirOut);
}
rectOut = subRect();
rectOut.size[1] = slidePx;
dirOut = ArrowDir::Down;
}
} }
else } else {
{ int slidePx = subRect().size[0] * m_slide;
int slidePx = subRect().size[0] * m_slide; if (slot == 1) {
if (slot == 1) if (m_views[1].m_view) {
{ SplitView* chSplit = m_views[1].m_view->castToSplitView();
if (m_views[1].m_view) if (chSplit && chSplit->m_axis == Axis::Vertical)
{ return chSplit->getJoinArrowHover(0, rectOut, dirOut);
SplitView* chSplit = m_views[1].m_view->castToSplitView(); }
if (chSplit && chSplit->m_axis == Axis::Vertical) rectOut = subRect();
return chSplit->getJoinArrowHover(0, rectOut, dirOut); rectOut.location[0] += slidePx;
} rectOut.size[0] -= slidePx;
rectOut = subRect(); dirOut = ArrowDir::Right;
rectOut.location[0] += slidePx; } else {
rectOut.size[0] -= slidePx; if (m_views[0].m_view) {
dirOut = ArrowDir::Right; SplitView* chSplit = m_views[0].m_view->castToSplitView();
} if (chSplit && chSplit->m_axis == Axis::Vertical)
else return chSplit->getJoinArrowHover(1, rectOut, dirOut);
{ }
if (m_views[0].m_view) rectOut = subRect();
{ rectOut.size[0] = slidePx;
SplitView* chSplit = m_views[0].m_view->castToSplitView(); dirOut = ArrowDir::Left;
if (chSplit && chSplit->m_axis == Axis::Vertical)
return chSplit->getJoinArrowHover(1, rectOut, dirOut);
}
rectOut = subRect();
rectOut.size[0] = slidePx;
dirOut = ArrowDir::Left;
}
} }
}
} }
bool SplitView::testSplitLineHover(const boo::SWindowCoord& coord, int& slotOut, bool SplitView::testSplitLineHover(const boo::SWindowCoord& coord, int& slotOut, boo::SWindowRect& rectOut,
boo::SWindowRect& rectOut, float& splitOut, Axis& axisOut) float& splitOut, Axis& axisOut) {
{ if (!subRect().coordInRect(coord))
if (!subRect().coordInRect(coord)) return false;
return false;
if (m_axis == Axis::Horizontal) if (m_axis == Axis::Horizontal) {
{ int slidePx = subRect().size[1] * m_slide;
int slidePx = subRect().size[1] * m_slide; if (coord.pixel[1] - subRect().location[1] - slidePx >= 0) {
if (coord.pixel[1] - subRect().location[1] - slidePx >= 0) if (m_views[1].m_view) {
{ SplitView* chSplit = m_views[1].m_view->castToSplitView();
if (m_views[1].m_view) if (chSplit && chSplit->m_axis == Axis::Horizontal)
{ return chSplit->testSplitLineHover(coord, slotOut, rectOut, splitOut, axisOut);
SplitView* chSplit = m_views[1].m_view->castToSplitView(); }
if (chSplit && chSplit->m_axis == Axis::Horizontal) slotOut = 1;
return chSplit->testSplitLineHover(coord, slotOut, rectOut, splitOut, axisOut); rectOut = subRect();
} rectOut.location[1] += slidePx;
slotOut = 1; rectOut.size[1] -= slidePx;
rectOut = subRect(); splitOut = (coord.pixel[0] - rectOut.location[0]) / float(rectOut.size[0]);
rectOut.location[1] += slidePx; axisOut = Axis::Vertical;
rectOut.size[1] -= slidePx; return true;
splitOut = (coord.pixel[0] - rectOut.location[0]) / float(rectOut.size[0]); } else {
axisOut = Axis::Vertical; if (m_views[0].m_view) {
return true; SplitView* chSplit = m_views[0].m_view->castToSplitView();
} if (chSplit && chSplit->m_axis == Axis::Horizontal)
else return chSplit->testSplitLineHover(coord, slotOut, rectOut, splitOut, axisOut);
{ }
if (m_views[0].m_view) slotOut = 0;
{ rectOut = subRect();
SplitView* chSplit = m_views[0].m_view->castToSplitView(); rectOut.size[1] = slidePx;
if (chSplit && chSplit->m_axis == Axis::Horizontal) splitOut = (coord.pixel[0] - rectOut.location[0]) / float(rectOut.size[0]);
return chSplit->testSplitLineHover(coord, slotOut, rectOut, splitOut, axisOut); axisOut = Axis::Vertical;
} return true;
slotOut = 0;
rectOut = subRect();
rectOut.size[1] = slidePx;
splitOut = (coord.pixel[0] - rectOut.location[0]) / float(rectOut.size[0]);
axisOut = Axis::Vertical;
return true;
}
} }
else } else {
{ int slidePx = subRect().size[0] * m_slide;
int slidePx = subRect().size[0] * m_slide; if (coord.pixel[0] - subRect().location[0] - slidePx >= 0) {
if (coord.pixel[0] - subRect().location[0] - slidePx >= 0) if (m_views[1].m_view) {
{ SplitView* chSplit = m_views[1].m_view->castToSplitView();
if (m_views[1].m_view) if (chSplit && chSplit->m_axis == Axis::Vertical)
{ return chSplit->testSplitLineHover(coord, slotOut, rectOut, splitOut, axisOut);
SplitView* chSplit = m_views[1].m_view->castToSplitView(); }
if (chSplit && chSplit->m_axis == Axis::Vertical) slotOut = 1;
return chSplit->testSplitLineHover(coord, slotOut, rectOut, splitOut, axisOut); rectOut = subRect();
} rectOut.location[0] += slidePx;
slotOut = 1; rectOut.size[0] -= slidePx;
rectOut = subRect(); splitOut = (coord.pixel[1] - rectOut.location[1]) / float(rectOut.size[1]);
rectOut.location[0] += slidePx; axisOut = Axis::Horizontal;
rectOut.size[0] -= slidePx; return true;
splitOut = (coord.pixel[1] - rectOut.location[1]) / float(rectOut.size[1]); } else {
axisOut = Axis::Horizontal; if (m_views[0].m_view) {
return true; SplitView* chSplit = m_views[0].m_view->castToSplitView();
} if (chSplit && chSplit->m_axis == Axis::Vertical)
else return chSplit->testSplitLineHover(coord, slotOut, rectOut, splitOut, axisOut);
{ }
if (m_views[0].m_view) slotOut = 0;
{ rectOut = subRect();
SplitView* chSplit = m_views[0].m_view->castToSplitView(); rectOut.size[0] = slidePx;
if (chSplit && chSplit->m_axis == Axis::Vertical) splitOut = (coord.pixel[1] - rectOut.location[1]) / float(rectOut.size[1]);
return chSplit->testSplitLineHover(coord, slotOut, rectOut, splitOut, axisOut); axisOut = Axis::Horizontal;
} return true;
slotOut = 0;
rectOut = subRect();
rectOut.size[0] = slidePx;
splitOut = (coord.pixel[1] - rectOut.location[1]) / float(rectOut.size[1]);
axisOut = Axis::Horizontal;
return true;
}
} }
}
} }
void SplitView::getSplitLineHover(int slot, boo::SWindowRect& rectOut, Axis& axisOut) void SplitView::getSplitLineHover(int slot, boo::SWindowRect& rectOut, Axis& axisOut) {
{ if (m_axis == Axis::Horizontal) {
if (m_axis == Axis::Horizontal) int slidePx = subRect().size[1] * m_slide;
{ if (slot == 1) {
int slidePx = subRect().size[1] * m_slide; if (m_views[1].m_view) {
if (slot == 1) SplitView* chSplit = m_views[1].m_view->castToSplitView();
{ if (chSplit && chSplit->m_axis == Axis::Horizontal)
if (m_views[1].m_view) return chSplit->getSplitLineHover(0, rectOut, axisOut);
{ }
SplitView* chSplit = m_views[1].m_view->castToSplitView(); rectOut = subRect();
if (chSplit && chSplit->m_axis == Axis::Horizontal) rectOut.location[1] += slidePx;
return chSplit->getSplitLineHover(0, rectOut, axisOut); rectOut.size[1] -= slidePx;
} axisOut = Axis::Vertical;
rectOut = subRect(); } else {
rectOut.location[1] += slidePx; if (m_views[0].m_view) {
rectOut.size[1] -= slidePx; SplitView* chSplit = m_views[0].m_view->castToSplitView();
axisOut = Axis::Vertical; if (chSplit && chSplit->m_axis == Axis::Horizontal)
} return chSplit->getSplitLineHover(1, rectOut, axisOut);
else }
{ rectOut = subRect();
if (m_views[0].m_view) rectOut.size[1] = slidePx;
{ axisOut = Axis::Vertical;
SplitView* chSplit = m_views[0].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Horizontal)
return chSplit->getSplitLineHover(1, rectOut, axisOut);
}
rectOut = subRect();
rectOut.size[1] = slidePx;
axisOut = Axis::Vertical;
}
} }
else } else {
{ int slidePx = subRect().size[0] * m_slide;
int slidePx = subRect().size[0] * m_slide; if (slot == 1) {
if (slot == 1) if (m_views[1].m_view) {
{ SplitView* chSplit = m_views[1].m_view->castToSplitView();
if (m_views[1].m_view) if (chSplit && chSplit->m_axis == Axis::Vertical)
{ return chSplit->getSplitLineHover(0, rectOut, axisOut);
SplitView* chSplit = m_views[1].m_view->castToSplitView(); }
if (chSplit && chSplit->m_axis == Axis::Vertical) rectOut = subRect();
return chSplit->getSplitLineHover(0, rectOut, axisOut); rectOut.location[0] += slidePx;
} rectOut.size[0] -= slidePx;
rectOut = subRect(); axisOut = Axis::Horizontal;
rectOut.location[0] += slidePx; } else {
rectOut.size[0] -= slidePx; if (m_views[0].m_view) {
axisOut = Axis::Horizontal; SplitView* chSplit = m_views[0].m_view->castToSplitView();
} if (chSplit && chSplit->m_axis == Axis::Vertical)
else return chSplit->getSplitLineHover(1, rectOut, axisOut);
{ }
if (m_views[0].m_view) rectOut = subRect();
{ rectOut.size[0] = slidePx;
SplitView* chSplit = m_views[0].m_view->castToSplitView(); axisOut = Axis::Horizontal;
if (chSplit && chSplit->m_axis == Axis::Vertical)
return chSplit->getSplitLineHover(1, rectOut, axisOut);
}
rectOut = subRect();
rectOut.size[0] = slidePx;
axisOut = Axis::Horizontal;
}
} }
}
} }
void SplitView::startDragSplit(const boo::SWindowCoord& coord) void SplitView::startDragSplit(const boo::SWindowCoord& coord) {
{ m_dragging = true;
m_dragging = true; if (m_axis == Axis::Horizontal)
if (m_axis == Axis::Horizontal) setSplit((coord.pixel[1] - subRect().location[1]) / float(subRect().size[1]));
setSplit((coord.pixel[1] - subRect().location[1]) / float(subRect().size[1])); else if (m_axis == Axis::Vertical)
else if (m_axis == Axis::Vertical) setSplit((coord.pixel[0] - subRect().location[0]) / float(subRect().size[0]));
setSplit((coord.pixel[0] - subRect().location[0]) / float(subRect().size[0]));
} }
void SplitView::endDragSplit() void SplitView::endDragSplit() { m_dragging = false; }
{
m_dragging = false; void SplitView::moveDragSplit(const boo::SWindowCoord& coord) {
if (m_axis == Axis::Horizontal)
setSplit((coord.pixel[1] - subRect().location[1]) / float(subRect().size[1]));
else if (m_axis == Axis::Vertical)
setSplit((coord.pixel[0] - subRect().location[0]) / float(subRect().size[0]));
} }
void SplitView::moveDragSplit(const boo::SWindowCoord& coord) void SplitView::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
{ m_views[0].mouseDown(coord, button, mod);
if (m_axis == Axis::Horizontal) m_views[1].mouseDown(coord, button, mod);
setSplit((coord.pixel[1] - subRect().location[1]) / float(subRect().size[1]));
else if (m_axis == Axis::Vertical)
setSplit((coord.pixel[0] - subRect().location[0]) / float(subRect().size[0]));
} }
void SplitView::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) void SplitView::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
{ m_views[0].mouseUp(coord, button, mod);
m_views[0].mouseDown(coord, button, mod); m_views[1].mouseUp(coord, button, mod);
m_views[1].mouseDown(coord, button, mod);
} }
void SplitView::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) void SplitView::mouseMove(const boo::SWindowCoord& coord) {
{ m_views[0].mouseMove(coord);
m_views[0].mouseUp(coord, button, mod); m_views[1].mouseMove(coord);
m_views[1].mouseUp(coord, button, mod);
} }
void SplitView::mouseMove(const boo::SWindowCoord& coord) void SplitView::mouseEnter(const boo::SWindowCoord& coord) {
{ m_views[0].mouseEnter(coord);
m_views[0].mouseMove(coord); m_views[1].mouseEnter(coord);
m_views[1].mouseMove(coord);
} }
void SplitView::mouseEnter(const boo::SWindowCoord& coord) void SplitView::mouseLeave(const boo::SWindowCoord& coord) {
{ m_views[0].mouseLeave(coord);
m_views[0].mouseEnter(coord); m_views[1].mouseLeave(coord);
m_views[1].mouseEnter(coord);
} }
void SplitView::mouseLeave(const boo::SWindowCoord& coord) void SplitView::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) {
{ View::resized(root, sub);
m_views[0].mouseLeave(coord); _setSplit(m_slide);
m_views[1].mouseLeave(coord); if (m_axis == Axis::Horizontal) {
} boo::SWindowRect ssub = sub;
ssub.size[1] *= m_slide;
void SplitView::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub)
{
View::resized(root, sub);
_setSplit(m_slide);
if (m_axis == Axis::Horizontal)
{
boo::SWindowRect ssub = sub;
ssub.size[1] *= m_slide;
if (m_views[0].m_view)
m_views[0].m_view->resized(root, ssub);
ssub.location[1] += ssub.size[1];
ssub.size[1] = sub.size[1] - ssub.size[1];
if (m_views[1].m_view)
m_views[1].m_view->resized(root, ssub);
ssub.location[1] -= 1;
m_splitBlock.setViewRect(root, ssub);
setHorizontalVerts(ssub.size[0]);
}
else if (m_axis == Axis::Vertical)
{
boo::SWindowRect ssub = sub;
ssub.size[0] *= m_slide;
if (m_views[0].m_view)
m_views[0].m_view->resized(root, ssub);
ssub.location[0] += ssub.size[0];
ssub.size[0] = sub.size[0] - ssub.size[0];
if (m_views[1].m_view)
m_views[1].m_view->resized(root, ssub);
ssub.location[0] -= 1;
m_splitBlock.setViewRect(root, ssub);
setVerticalVerts(ssub.size[1]);
}
m_splitBlockBuf.access().finalAssign(m_splitBlock);
m_splitVertsBinding.load<decltype(m_splitVerts)>(m_splitVerts);
}
void SplitView::draw(boo::IGraphicsCommandQueue* gfxQ)
{
View::draw(gfxQ);
if (m_views[0].m_view) if (m_views[0].m_view)
m_views[0].m_view->draw(gfxQ); m_views[0].m_view->resized(root, ssub);
ssub.location[1] += ssub.size[1];
ssub.size[1] = sub.size[1] - ssub.size[1];
if (m_views[1].m_view) if (m_views[1].m_view)
m_views[1].m_view->draw(gfxQ); m_views[1].m_view->resized(root, ssub);
gfxQ->setShaderDataBinding(m_splitVertsBinding); ssub.location[1] -= 1;
gfxQ->draw(0, 4); m_splitBlock.setViewRect(root, ssub);
setHorizontalVerts(ssub.size[0]);
} else if (m_axis == Axis::Vertical) {
boo::SWindowRect ssub = sub;
ssub.size[0] *= m_slide;
if (m_views[0].m_view)
m_views[0].m_view->resized(root, ssub);
ssub.location[0] += ssub.size[0];
ssub.size[0] = sub.size[0] - ssub.size[0];
if (m_views[1].m_view)
m_views[1].m_view->resized(root, ssub);
ssub.location[0] -= 1;
m_splitBlock.setViewRect(root, ssub);
setVerticalVerts(ssub.size[1]);
}
m_splitBlockBuf.access().finalAssign(m_splitBlock);
m_splitVertsBinding.load<decltype(m_splitVerts)>(m_splitVerts);
} }
void SplitView::draw(boo::IGraphicsCommandQueue* gfxQ) {
View::draw(gfxQ);
if (m_views[0].m_view)
m_views[0].m_view->draw(gfxQ);
if (m_views[1].m_view)
m_views[1].m_view->draw(gfxQ);
gfxQ->setShaderDataBinding(m_splitVertsBinding);
gfxQ->draw(0, 4);
} }
} // namespace specter

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -7,336 +7,285 @@
#include <freetype/internal/internal.h> #include <freetype/internal/internal.h>
#include <freetype/internal/ftobjs.h> #include <freetype/internal/ftobjs.h>
namespace specter namespace specter {
{
static logvisor::Module Log("specter::TextView"); static logvisor::Module Log("specter::TextView");
void TextView::Resources::init(boo::IGraphicsDataFactory::Context& ctx, FontCache* fcache) void TextView::Resources::init(boo::IGraphicsDataFactory::Context& ctx, FontCache* fcache) {
{ m_fcache = fcache;
m_fcache = fcache; m_regular = hecl::conv->convert(ctx, Shader_SpecterTextViewShader{});
m_regular = hecl::conv->convert(ctx, Shader_SpecterTextViewShader{}); m_subpixel = hecl::conv->convert(ctx, Shader_SpecterTextViewShaderSubpixel{});
m_subpixel = hecl::conv->convert(ctx, Shader_SpecterTextViewShaderSubpixel{});
} }
void TextView::_commitResources(size_t capacity) void TextView::_commitResources(size_t capacity) {
{ auto& res = rootView().viewRes();
auto& res = rootView().viewRes(); auto fontTex = m_fontAtlas.texture(res.m_factory);
auto fontTex = m_fontAtlas.texture(res.m_factory); View::commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) {
View::commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) buildResources(ctx, res);
{
buildResources(ctx, res);
if (capacity) if (capacity) {
{ m_glyphBuf = res.m_textRes.m_glyphPool.allocateBlock(res.m_factory, capacity);
m_glyphBuf = res.m_textRes.m_glyphPool.allocateBlock(res.m_factory, capacity);
boo::ObjToken<boo::IShaderPipeline> shader; boo::ObjToken<boo::IShaderPipeline> shader;
if (m_fontAtlas.subpixel()) if (m_fontAtlas.subpixel())
shader = res.m_textRes.m_subpixel; shader = res.m_textRes.m_subpixel;
else else
shader = res.m_textRes.m_regular; shader = res.m_textRes.m_regular;
auto vBufInfo = m_glyphBuf.getBufferInfo(); auto vBufInfo = m_glyphBuf.getBufferInfo();
auto uBufInfo = m_viewVertBlockBuf.getBufferInfo(); auto uBufInfo = m_viewVertBlockBuf.getBufferInfo();
boo::ObjToken<boo::IGraphicsBuffer> uBufs[] = {uBufInfo.first.get()}; boo::ObjToken<boo::IGraphicsBuffer> uBufs[] = {uBufInfo.first.get()};
size_t uBufOffs[] = {size_t(uBufInfo.second)}; size_t uBufOffs[] = {size_t(uBufInfo.second)};
size_t uBufSizes[] = {sizeof(ViewBlock)}; size_t uBufSizes[] = {sizeof(ViewBlock)};
boo::ObjToken<boo::ITexture> texs[] = {fontTex.get()}; boo::ObjToken<boo::ITexture> texs[] = {fontTex.get()};
m_shaderBinding = ctx.newShaderDataBinding(shader, {}, vBufInfo.first.get(), nullptr, 1, m_shaderBinding = ctx.newShaderDataBinding(shader, {}, vBufInfo.first.get(), nullptr, 1, uBufs, nullptr, uBufOffs,
uBufs, nullptr, uBufOffs, uBufSizes, uBufSizes, 1, texs, nullptr, nullptr, 0, vBufInfo.second);
1, texs, nullptr, nullptr, 0, vBufInfo.second); }
} return true;
return true; });
});
} }
TextView::TextView(ViewResources& res, TextView::TextView(ViewResources& res, View& parentView, const FontAtlas& font, Alignment align, size_t capacity)
View& parentView, const FontAtlas& font, : View(res, parentView), m_capacity(capacity), m_fontAtlas(font), m_align(align) {
Alignment align, size_t capacity) if (size_t(hecl::VertexBufferPool<RenderGlyph>::bucketCapacity()) < capacity)
: View(res, parentView), Log.report(logvisor::Fatal, "bucket overflow [%" PRISize "/%" PRISize "]", capacity,
m_capacity(capacity), hecl::VertexBufferPool<RenderGlyph>::bucketCapacity());
m_fontAtlas(font),
m_align(align)
{
if (size_t(hecl::VertexBufferPool<RenderGlyph>::bucketCapacity()) < capacity)
Log.report(logvisor::Fatal, "bucket overflow [%" PRISize "/%" PRISize "]",
capacity, hecl::VertexBufferPool<RenderGlyph>::bucketCapacity());
_commitResources(0); _commitResources(0);
} }
TextView::TextView(ViewResources& res, View& parentView, FontTag font, Alignment align, size_t capacity) TextView::TextView(ViewResources& res, View& parentView, FontTag font, Alignment align, size_t capacity)
: TextView(res, parentView, res.m_textRes.m_fcache->lookupAtlas(font), align, capacity) {} : TextView(res, parentView, res.m_textRes.m_fcache->lookupAtlas(font), align, capacity) {}
TextView::RenderGlyph::RenderGlyph(int& adv, const FontAtlas::Glyph& glyph, const zeus::CColor& defaultColor) TextView::RenderGlyph::RenderGlyph(int& adv, const FontAtlas::Glyph& glyph, const zeus::CColor& defaultColor) {
{ m_pos[0].assign(adv + glyph.m_leftPadding, glyph.m_verticalOffset + glyph.m_height, 0.f);
m_pos[0].assign(adv + glyph.m_leftPadding, glyph.m_verticalOffset + glyph.m_height, 0.f); m_pos[1].assign(adv + glyph.m_leftPadding, glyph.m_verticalOffset, 0.f);
m_pos[1].assign(adv + glyph.m_leftPadding, glyph.m_verticalOffset, 0.f); m_pos[2].assign(adv + glyph.m_leftPadding + glyph.m_width, glyph.m_verticalOffset + glyph.m_height, 0.f);
m_pos[2].assign(adv + glyph.m_leftPadding + glyph.m_width, glyph.m_verticalOffset + glyph.m_height, 0.f); m_pos[3].assign(adv + glyph.m_leftPadding + glyph.m_width, glyph.m_verticalOffset, 0.f);
m_pos[3].assign(adv + glyph.m_leftPadding + glyph.m_width, glyph.m_verticalOffset, 0.f); m_uv[0].assign(glyph.m_uv[0], glyph.m_uv[1], glyph.m_layerFloat);
m_uv[0].assign(glyph.m_uv[0], glyph.m_uv[1], glyph.m_layerFloat); m_uv[1].assign(glyph.m_uv[0], glyph.m_uv[3], glyph.m_layerFloat);
m_uv[1].assign(glyph.m_uv[0], glyph.m_uv[3], glyph.m_layerFloat); m_uv[2].assign(glyph.m_uv[2], glyph.m_uv[1], glyph.m_layerFloat);
m_uv[2].assign(glyph.m_uv[2], glyph.m_uv[1], glyph.m_layerFloat); m_uv[3].assign(glyph.m_uv[2], glyph.m_uv[3], glyph.m_layerFloat);
m_uv[3].assign(glyph.m_uv[2], glyph.m_uv[3], glyph.m_layerFloat); m_color = defaultColor;
m_color = defaultColor; adv += glyph.m_advance;
adv += glyph.m_advance;
} }
int TextView::DoKern(FT_Pos val, const FontAtlas& atlas) int TextView::DoKern(FT_Pos val, const FontAtlas& atlas) {
{ if (!val)
if (!val) return 0; return 0;
val = FT_MulFix(val, atlas.FT_Xscale()); val = FT_MulFix(val, atlas.FT_Xscale());
FT_Pos orig_x = val; FT_Pos orig_x = val;
/* we scale down kerning values for small ppem values */ /* we scale down kerning values for small ppem values */
/* to avoid that rounding makes them too big. */ /* to avoid that rounding makes them too big. */
/* `25' has been determined heuristically. */ /* `25' has been determined heuristically. */
if (atlas.FT_XPPem() < 25) if (atlas.FT_XPPem() < 25)
val = FT_MulDiv(orig_x, atlas.FT_XPPem(), 25); val = FT_MulDiv(orig_x, atlas.FT_XPPem(), 25);
return FT_PIX_ROUND(val) >> 6; return FT_PIX_ROUND(val) >> 6;
} }
void TextView::typesetGlyphs(std::string_view str, const zeus::CColor& defaultColor) void TextView::typesetGlyphs(std::string_view str, const zeus::CColor& defaultColor) {
{ UTF8Iterator it(str.begin());
UTF8Iterator it(str.begin()); size_t charLen = str.size() ? std::min(it.countTo(str.end()), m_capacity) : 0;
size_t charLen = str.size() ? std::min(it.countTo(str.end()), m_capacity) : 0; if (charLen > m_curSize) {
if (charLen > m_curSize) m_curSize = charLen;
{ _commitResources(charLen);
m_curSize = charLen; }
_commitResources(charLen);
uint32_t lCh = -1;
m_glyphs.clear();
m_glyphs.reserve(charLen);
m_glyphInfo.clear();
m_glyphInfo.reserve(charLen);
int adv = 0;
if (charLen) {
for (; it.iter() < str.end(); ++it) {
utf8proc_int32_t ch = *it;
if (ch == -1) {
Log.report(logvisor::Warning, "invalid UTF-8 char");
break;
}
if (ch == '\n' || ch == '\0')
break;
const FontAtlas::Glyph* glyph = m_fontAtlas.lookupGlyph(ch);
if (!glyph)
continue;
if (lCh != -1)
adv += DoKern(m_fontAtlas.lookupKern(lCh, glyph->m_glyphIdx), m_fontAtlas);
m_glyphs.emplace_back(adv, *glyph, defaultColor);
m_glyphInfo.emplace_back(ch, glyph->m_width, glyph->m_height, adv);
lCh = glyph->m_glyphIdx;
if (m_glyphs.size() == m_capacity)
break;
} }
}
uint32_t lCh = -1; if (m_align == Alignment::Right) {
m_glyphs.clear(); int adj = -adv;
m_glyphs.reserve(charLen); for (RenderGlyph& g : m_glyphs) {
m_glyphInfo.clear(); g.m_pos[0][0] += adj;
m_glyphInfo.reserve(charLen); g.m_pos[1][0] += adj;
int adv = 0; g.m_pos[2][0] += adj;
g.m_pos[3][0] += adj;
if (charLen)
{
for (; it.iter() < str.end() ; ++it)
{
utf8proc_int32_t ch = *it;
if (ch == -1)
{
Log.report(logvisor::Warning, "invalid UTF-8 char");
break;
}
if (ch == '\n' || ch == '\0')
break;
const FontAtlas::Glyph* glyph = m_fontAtlas.lookupGlyph(ch);
if (!glyph)
continue;
if (lCh != -1)
adv += DoKern(m_fontAtlas.lookupKern(lCh, glyph->m_glyphIdx), m_fontAtlas);
m_glyphs.emplace_back(adv, *glyph, defaultColor);
m_glyphInfo.emplace_back(ch, glyph->m_width, glyph->m_height, adv);
lCh = glyph->m_glyphIdx;
if (m_glyphs.size() == m_capacity)
break;
}
} }
} else if (m_align == Alignment::Center) {
if (m_align == Alignment::Right) int adj = -adv / 2;
{ for (RenderGlyph& g : m_glyphs) {
int adj = -adv; g.m_pos[0][0] += adj;
for (RenderGlyph& g : m_glyphs) g.m_pos[1][0] += adj;
{ g.m_pos[2][0] += adj;
g.m_pos[0][0] += adj; g.m_pos[3][0] += adj;
g.m_pos[1][0] += adj;
g.m_pos[2][0] += adj;
g.m_pos[3][0] += adj;
}
}
else if (m_align == Alignment::Center)
{
int adj = -adv / 2;
for (RenderGlyph& g : m_glyphs)
{
g.m_pos[0][0] += adj;
g.m_pos[1][0] += adj;
g.m_pos[2][0] += adj;
g.m_pos[3][0] += adj;
}
} }
}
m_width = adv; m_width = adv;
invalidateGlyphs(); invalidateGlyphs();
updateSize(); updateSize();
} }
void TextView::typesetGlyphs(std::wstring_view str, const zeus::CColor& defaultColor) void TextView::typesetGlyphs(std::wstring_view str, const zeus::CColor& defaultColor) {
{ size_t charLen = std::min(str.size(), m_capacity);
size_t charLen = std::min(str.size(), m_capacity); if (charLen > m_curSize) {
if (charLen > m_curSize) m_curSize = charLen;
{ _commitResources(charLen);
m_curSize = charLen; }
_commitResources(charLen);
uint32_t lCh = -1;
m_glyphs.clear();
m_glyphs.reserve(charLen);
m_glyphInfo.clear();
m_glyphInfo.reserve(charLen);
int adv = 0;
for (wchar_t ch : str) {
if (ch == L'\n')
break;
const FontAtlas::Glyph* glyph = m_fontAtlas.lookupGlyph(ch);
if (!glyph)
continue;
if (lCh != -1)
adv += DoKern(m_fontAtlas.lookupKern(lCh, glyph->m_glyphIdx), m_fontAtlas);
m_glyphs.emplace_back(adv, *glyph, defaultColor);
m_glyphInfo.emplace_back(ch, glyph->m_width, glyph->m_height, adv);
lCh = glyph->m_glyphIdx;
if (m_glyphs.size() == m_capacity)
break;
}
if (m_align == Alignment::Right) {
int adj = -adv;
for (RenderGlyph& g : m_glyphs) {
g.m_pos[0][0] += adj;
g.m_pos[1][0] += adj;
g.m_pos[2][0] += adj;
g.m_pos[3][0] += adj;
} }
} else if (m_align == Alignment::Center) {
uint32_t lCh = -1; int adj = -adv / 2;
m_glyphs.clear(); for (RenderGlyph& g : m_glyphs) {
m_glyphs.reserve(charLen); g.m_pos[0][0] += adj;
m_glyphInfo.clear(); g.m_pos[1][0] += adj;
m_glyphInfo.reserve(charLen); g.m_pos[2][0] += adj;
int adv = 0; g.m_pos[3][0] += adj;
for (wchar_t ch : str)
{
if (ch == L'\n')
break;
const FontAtlas::Glyph* glyph = m_fontAtlas.lookupGlyph(ch);
if (!glyph)
continue;
if (lCh != -1)
adv += DoKern(m_fontAtlas.lookupKern(lCh, glyph->m_glyphIdx), m_fontAtlas);
m_glyphs.emplace_back(adv, *glyph, defaultColor);
m_glyphInfo.emplace_back(ch, glyph->m_width, glyph->m_height, adv);
lCh = glyph->m_glyphIdx;
if (m_glyphs.size() == m_capacity)
break;
} }
}
if (m_align == Alignment::Right) m_width = adv;
{ invalidateGlyphs();
int adj = -adv; updateSize();
for (RenderGlyph& g : m_glyphs)
{
g.m_pos[0][0] += adj;
g.m_pos[1][0] += adj;
g.m_pos[2][0] += adj;
g.m_pos[3][0] += adj;
}
}
else if (m_align == Alignment::Center)
{
int adj = -adv / 2;
for (RenderGlyph& g : m_glyphs)
{
g.m_pos[0][0] += adj;
g.m_pos[1][0] += adj;
g.m_pos[2][0] += adj;
g.m_pos[3][0] += adj;
}
}
m_width = adv;
invalidateGlyphs();
updateSize();
} }
void TextView::colorGlyphs(const zeus::CColor& newColor) void TextView::colorGlyphs(const zeus::CColor& newColor) {
{ for (RenderGlyph& glyph : m_glyphs)
glyph.m_color = newColor;
invalidateGlyphs();
}
void TextView::colorGlyphsTypeOn(const zeus::CColor& newColor, float startInterval, float fadeTime) {}
void TextView::invalidateGlyphs() {
if (m_glyphBuf) {
RenderGlyph* out = m_glyphBuf.access();
size_t i = 0;
for (RenderGlyph& glyph : m_glyphs) for (RenderGlyph& glyph : m_glyphs)
glyph.m_color = newColor; out[i++] = glyph;
invalidateGlyphs(); }
} }
void TextView::colorGlyphsTypeOn(const zeus::CColor& newColor, float startInterval, float fadeTime) void TextView::think() {}
{
void TextView::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) { View::resized(root, sub); }
void TextView::draw(boo::IGraphicsCommandQueue* gfxQ) {
View::draw(gfxQ);
if (m_glyphs.size()) {
gfxQ->setShaderDataBinding(m_shaderBinding);
gfxQ->drawInstances(0, 4, m_glyphs.size());
}
} }
void TextView::invalidateGlyphs() std::pair<int, int> TextView::queryGlyphDimensions(size_t pos) const {
{ if (pos >= m_glyphInfo.size())
if (m_glyphBuf) Log.report(logvisor::Fatal, "TextView::queryGlyphWidth(%" PRISize ") out of bounds: %" PRISize, pos,
{ m_glyphInfo.size());
RenderGlyph* out = m_glyphBuf.access();
size_t i = 0; return m_glyphInfo[pos].m_dims;
for (RenderGlyph& glyph : m_glyphs) }
out[i++] = glyph;
size_t TextView::reverseSelectGlyph(int x) const {
size_t ret = 0;
size_t idx = 1;
int minDelta = abs(x);
for (const RenderGlyphInfo& info : m_glyphInfo) {
int thisDelta = abs(info.m_adv - x);
if (thisDelta < minDelta) {
minDelta = thisDelta;
ret = idx;
} }
++idx;
}
return ret;
} }
void TextView::think() int TextView::queryReverseAdvance(size_t idx) const {
{ if (idx > m_glyphInfo.size())
Log.report(logvisor::Fatal, "TextView::queryReverseGlyph(%" PRISize ") out of inclusive bounds: %" PRISize, idx,
m_glyphInfo.size());
if (!idx)
return 0;
return m_glyphInfo[idx - 1].m_adv;
} }
void TextView::resized(const boo::SWindowRect &root, const boo::SWindowRect& sub) std::pair<size_t, size_t> TextView::queryWholeWordRange(size_t idx) const {
{ if (idx > m_glyphInfo.size())
View::resized(root, sub); Log.report(logvisor::Fatal, "TextView::queryWholeWordRange(%" PRISize ") out of inclusive bounds: %" PRISize, idx,
m_glyphInfo.size());
if (m_glyphInfo.empty())
return {0, 0};
if (idx == m_glyphInfo.size())
--idx;
size_t begin = idx;
while (begin > 0 && !m_glyphInfo[begin - 1].m_space)
--begin;
size_t end = idx;
while (end < m_glyphInfo.size() && !m_glyphInfo[end].m_space)
++end;
return {begin, end - begin};
} }
void TextView::draw(boo::IGraphicsCommandQueue* gfxQ) } // namespace specter
{
View::draw(gfxQ);
if (m_glyphs.size())
{
gfxQ->setShaderDataBinding(m_shaderBinding);
gfxQ->drawInstances(0, 4, m_glyphs.size());
}
}
std::pair<int,int> TextView::queryGlyphDimensions(size_t pos) const
{
if (pos >= m_glyphInfo.size())
Log.report(logvisor::Fatal,
"TextView::queryGlyphWidth(%" PRISize ") out of bounds: %" PRISize,
pos, m_glyphInfo.size());
return m_glyphInfo[pos].m_dims;
}
size_t TextView::reverseSelectGlyph(int x) const
{
size_t ret = 0;
size_t idx = 1;
int minDelta = abs(x);
for (const RenderGlyphInfo& info : m_glyphInfo)
{
int thisDelta = abs(info.m_adv-x);
if (thisDelta < minDelta)
{
minDelta = thisDelta;
ret = idx;
}
++idx;
}
return ret;
}
int TextView::queryReverseAdvance(size_t idx) const
{
if (idx > m_glyphInfo.size())
Log.report(logvisor::Fatal,
"TextView::queryReverseGlyph(%" PRISize ") out of inclusive bounds: %" PRISize,
idx, m_glyphInfo.size());
if (!idx) return 0;
return m_glyphInfo[idx-1].m_adv;
}
std::pair<size_t,size_t> TextView::queryWholeWordRange(size_t idx) const
{
if (idx > m_glyphInfo.size())
Log.report(logvisor::Fatal,
"TextView::queryWholeWordRange(%" PRISize ") out of inclusive bounds: %" PRISize,
idx, m_glyphInfo.size());
if (m_glyphInfo.empty())
return {0,0};
if (idx == m_glyphInfo.size())
--idx;
size_t begin = idx;
while (begin > 0 && !m_glyphInfo[begin-1].m_space)
--begin;
size_t end = idx;
while (end < m_glyphInfo.size() && !m_glyphInfo[end].m_space)
++end;
return {begin, end-begin};
}
}

View File

@ -5,180 +5,158 @@
#define TOOLBAR_PADDING 10 #define TOOLBAR_PADDING 10
namespace specter namespace specter {
{
static logvisor::Module Log("specter::Space"); static logvisor::Module Log("specter::Space");
static const zeus::RGBA32 Tex[] = static const zeus::RGBA32 Tex[] = {{{255, 255, 255, 64}}, {{255, 255, 255, 64}}, {{0, 0, 0, 64}}, {{0, 0, 0, 64}}};
{
{{255,255,255,64}},
{{255,255,255,64}},
{{0,0,0,64}},
{{0,0,0,64}}
};
void Toolbar::Resources::init(boo::IGraphicsDataFactory::Context& ctx, const IThemeData& theme) void Toolbar::Resources::init(boo::IGraphicsDataFactory::Context& ctx, const IThemeData& theme) {
{ m_shadingTex = ctx.newStaticTexture(4, 1, 1, boo::TextureFormat::RGBA8, boo::TextureClampMode::Repeat, Tex, 16);
m_shadingTex = ctx.newStaticTexture(4, 1, 1, boo::TextureFormat::RGBA8, boo::TextureClampMode::Repeat, Tex, 16);
} }
Toolbar::Toolbar(ViewResources& res, View& parentView, Position tbPos, unsigned units) Toolbar::Toolbar(ViewResources& res, View& parentView, Position tbPos, unsigned units)
: View(res, parentView), m_units(units), : View(res, parentView)
m_nomGauge(res.pixelFactor() * SPECTER_TOOLBAR_GAUGE * units), , m_units(units)
m_padding(res.pixelFactor() * TOOLBAR_PADDING) , m_nomGauge(res.pixelFactor() * SPECTER_TOOLBAR_GAUGE * units)
{ , m_padding(res.pixelFactor() * TOOLBAR_PADDING) {
m_children.reserve(units); m_children.reserve(units);
for (unsigned u=0 ; u<units ; ++u) for (unsigned u = 0; u < units; ++u)
m_children.emplace_back(); m_children.emplace_back();
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool {
{ buildResources(ctx, res);
buildResources(ctx, res); m_tbBlockBuf = res.m_viewRes.m_bufPool.allocateBlock(res.m_factory);
m_tbBlockBuf = res.m_viewRes.m_bufPool.allocateBlock(res.m_factory); m_vertsBinding.init(ctx, res, 10, m_tbBlockBuf, res.m_toolbarRes.m_shadingTex.get());
m_vertsBinding.init(ctx, res, 10, m_tbBlockBuf, res.m_toolbarRes.m_shadingTex.get()); return true;
return true; });
}); setBackground(res.themeData().toolbarBackground());
setBackground(res.themeData().toolbarBackground());
} }
void Toolbar::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) void Toolbar::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
{ for (std::vector<ViewChild<View*>>& u : m_children)
for (std::vector<ViewChild<View*>>& u : m_children) for (ViewChild<View*>& c : u)
for (ViewChild<View*>& c : u) c.mouseDown(coord, button, mod);
c.mouseDown(coord, button, mod);
} }
void Toolbar::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) void Toolbar::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
{ for (std::vector<ViewChild<View*>>& u : m_children)
for (std::vector<ViewChild<View*>>& u : m_children) for (ViewChild<View*>& c : u)
for (ViewChild<View*>& c : u) c.mouseUp(coord, button, mod);
c.mouseUp(coord, button, mod);
} }
void Toolbar::mouseMove(const boo::SWindowCoord& coord) void Toolbar::mouseMove(const boo::SWindowCoord& coord) {
{ for (std::vector<ViewChild<View*>>& u : m_children)
for (std::vector<ViewChild<View*>>& u : m_children) for (ViewChild<View*>& c : u)
for (ViewChild<View*>& c : u) c.mouseMove(coord);
c.mouseMove(coord);
} }
void Toolbar::mouseEnter(const boo::SWindowCoord& coord) void Toolbar::mouseEnter(const boo::SWindowCoord& coord) {
{ for (std::vector<ViewChild<View*>>& u : m_children)
for (std::vector<ViewChild<View*>>& u : m_children) for (ViewChild<View*>& c : u)
for (ViewChild<View*>& c : u) c.mouseEnter(coord);
c.mouseEnter(coord);
} }
void Toolbar::mouseLeave(const boo::SWindowCoord& coord) void Toolbar::mouseLeave(const boo::SWindowCoord& coord) {
{ for (std::vector<ViewChild<View*>>& u : m_children)
for (std::vector<ViewChild<View*>>& u : m_children) for (ViewChild<View*>& c : u)
for (ViewChild<View*>& c : u) c.mouseLeave(coord);
c.mouseLeave(coord);
} }
void Toolbar::setHorizontalVerts(int width) void Toolbar::setHorizontalVerts(int width) {
{ m_tbVerts[0].m_pos.assign(0, 1 + m_nomGauge, 0);
m_tbVerts[0].m_pos.assign(0, 1 + m_nomGauge, 0); m_tbVerts[0].m_uv.assign(0, 0);
m_tbVerts[0].m_uv.assign(0, 0); m_tbVerts[1].m_pos.assign(0, -1 + m_nomGauge, 0);
m_tbVerts[1].m_pos.assign(0, -1 + m_nomGauge, 0); m_tbVerts[1].m_uv.assign(0.5, 0);
m_tbVerts[1].m_uv.assign(0.5, 0); m_tbVerts[2].m_pos.assign(width, 1 + m_nomGauge, 0);
m_tbVerts[2].m_pos.assign(width, 1 + m_nomGauge, 0); m_tbVerts[2].m_uv.assign(0, 0);
m_tbVerts[2].m_uv.assign(0, 0); m_tbVerts[3].m_pos.assign(width, -1 + m_nomGauge, 0);
m_tbVerts[3].m_pos.assign(width, -1 + m_nomGauge, 0); m_tbVerts[3].m_uv.assign(0.5, 0);
m_tbVerts[3].m_uv.assign(0.5, 0); m_tbVerts[4].m_pos.assign(width, -1 + m_nomGauge, 0);
m_tbVerts[4].m_pos.assign(width, -1 + m_nomGauge, 0); m_tbVerts[4].m_uv.assign(0.5, 0);
m_tbVerts[4].m_uv.assign(0.5, 0);
m_tbVerts[5].m_pos.assign(0, 1, 0); m_tbVerts[5].m_pos.assign(0, 1, 0);
m_tbVerts[5].m_uv.assign(0.5, 0); m_tbVerts[5].m_uv.assign(0.5, 0);
m_tbVerts[6].m_pos.assign(0, 1, 0); m_tbVerts[6].m_pos.assign(0, 1, 0);
m_tbVerts[6].m_uv.assign(0.5, 0); m_tbVerts[6].m_uv.assign(0.5, 0);
m_tbVerts[7].m_pos.assign(0, -1, 0); m_tbVerts[7].m_pos.assign(0, -1, 0);
m_tbVerts[7].m_uv.assign(1, 0); m_tbVerts[7].m_uv.assign(1, 0);
m_tbVerts[8].m_pos.assign(width, 1, 0); m_tbVerts[8].m_pos.assign(width, 1, 0);
m_tbVerts[8].m_uv.assign(0.5, 0); m_tbVerts[8].m_uv.assign(0.5, 0);
m_tbVerts[9].m_pos.assign(width, -1, 0); m_tbVerts[9].m_pos.assign(width, -1, 0);
m_tbVerts[9].m_uv.assign(1, 0); m_tbVerts[9].m_uv.assign(1, 0);
} }
void Toolbar::setVerticalVerts(int height) void Toolbar::setVerticalVerts(int height) {
{ m_tbVerts[0].m_pos.assign(-1, height, 0);
m_tbVerts[0].m_pos.assign(-1, height, 0); m_tbVerts[0].m_uv.assign(0, 0);
m_tbVerts[0].m_uv.assign(0, 0); m_tbVerts[1].m_pos.assign(-1, 0, 0);
m_tbVerts[1].m_pos.assign(-1, 0, 0); m_tbVerts[1].m_uv.assign(0, 0);
m_tbVerts[1].m_uv.assign(0, 0); m_tbVerts[2].m_pos.assign(1, height, 0);
m_tbVerts[2].m_pos.assign(1, height, 0); m_tbVerts[2].m_uv.assign(0.5, 0);
m_tbVerts[2].m_uv.assign(0.5, 0); m_tbVerts[3].m_pos.assign(1, 0, 0);
m_tbVerts[3].m_pos.assign(1, 0, 0); m_tbVerts[3].m_uv.assign(0.5, 0);
m_tbVerts[3].m_uv.assign(0.5, 0); m_tbVerts[4].m_pos.assign(1, 0, 0);
m_tbVerts[4].m_pos.assign(1, 0, 0); m_tbVerts[4].m_uv.assign(0.5, 0);
m_tbVerts[4].m_uv.assign(0.5, 0);
m_tbVerts[5].m_pos.assign(-1 + m_nomGauge, height, 0); m_tbVerts[5].m_pos.assign(-1 + m_nomGauge, height, 0);
m_tbVerts[5].m_uv.assign(0.5, 0); m_tbVerts[5].m_uv.assign(0.5, 0);
m_tbVerts[6].m_pos.assign(-1 + m_nomGauge, height, 0); m_tbVerts[6].m_pos.assign(-1 + m_nomGauge, height, 0);
m_tbVerts[6].m_uv.assign(0.5, 0); m_tbVerts[6].m_uv.assign(0.5, 0);
m_tbVerts[7].m_pos.assign(-1 + m_nomGauge, 0, 0); m_tbVerts[7].m_pos.assign(-1 + m_nomGauge, 0, 0);
m_tbVerts[7].m_uv.assign(0.5, 0); m_tbVerts[7].m_uv.assign(0.5, 0);
m_tbVerts[8].m_pos.assign(1 + m_nomGauge, height, 0); m_tbVerts[8].m_pos.assign(1 + m_nomGauge, height, 0);
m_tbVerts[8].m_uv.assign(1, 0); m_tbVerts[8].m_uv.assign(1, 0);
m_tbVerts[9].m_pos.assign(1 + m_nomGauge, 0, 0); m_tbVerts[9].m_pos.assign(1 + m_nomGauge, 0, 0);
m_tbVerts[9].m_uv.assign(1, 0); m_tbVerts[9].m_uv.assign(1, 0);
} }
void Toolbar::push_back(View* v, unsigned unit) void Toolbar::push_back(View* v, unsigned unit) {
{ if (unit >= m_units)
if (unit >= m_units) Log.report(logvisor::Fatal, "unit %u out of range %u", unit, m_units);
Log.report(logvisor::Fatal, "unit %u out of range %u", unit, m_units); std::vector<ViewChild<View*>>& u = m_children[unit];
std::vector<ViewChild<View*>>& u = m_children[unit]; u.emplace_back();
u.emplace_back(); u.back().m_view = v;
u.back().m_view = v;
} }
void Toolbar::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) void Toolbar::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) {
{ View::resized(root, sub);
View::resized(root, sub); setHorizontalVerts(sub.size[0]);
setHorizontalVerts(sub.size[0]); m_vertsBinding.load<decltype(m_tbVerts)>(m_tbVerts);
m_vertsBinding.load<decltype(m_tbVerts)>(m_tbVerts); m_tbBlock.setViewRect(root, sub);
m_tbBlock.setViewRect(root, sub); m_tbBlockBuf.access().finalAssign(m_tbBlock);
m_tbBlockBuf.access().finalAssign(m_tbBlock);
float gaugeUnit = rootView().viewRes().pixelFactor() * SPECTER_TOOLBAR_GAUGE; float gaugeUnit = rootView().viewRes().pixelFactor() * SPECTER_TOOLBAR_GAUGE;
float yOff = 0.0; float yOff = 0.0;
for (std::vector<ViewChild<View*>>& u : m_children) for (std::vector<ViewChild<View*>>& u : m_children) {
{ boo::SWindowRect childRect = sub;
boo::SWindowRect childRect = sub; boo::SWindowRect containRect = sub;
boo::SWindowRect containRect = sub; containRect.location[0] += m_padding;
containRect.location[0] += m_padding; containRect.size[0] -= m_padding * 2;
containRect.size[0] -= m_padding * 2; containRect.size[1] = gaugeUnit;
containRect.size[1] = gaugeUnit; for (ViewChild<View*>& c : u) {
for (ViewChild<View*>& c : u) c.m_view->containerResized(root, containRect);
{ childRect.size[0] = c.m_view->nominalWidth();
c.m_view->containerResized(root, containRect); childRect.size[1] = c.m_view->nominalHeight();
childRect.size[0] = c.m_view->nominalWidth(); childRect.location[0] += m_padding;
childRect.size[1] = c.m_view->nominalHeight(); childRect.location[1] = sub.location[1] + (gaugeUnit - childRect.size[1]) / 2 - 1 + yOff;
childRect.location[0] += m_padding; c.m_view->resized(root, childRect);
childRect.location[1] = sub.location[1] + (gaugeUnit - childRect.size[1]) / 2 - 1 + yOff; childRect.location[0] += childRect.size[0];
c.m_view->resized(root, childRect);
childRect.location[0] += childRect.size[0];
containRect.location[0] += m_padding + childRect.size[0]; containRect.location[0] += m_padding + childRect.size[0];
containRect.size[0] -= m_padding + childRect.size[0]; containRect.size[0] -= m_padding + childRect.size[0];
containRect.size[1] = gaugeUnit; containRect.size[1] = gaugeUnit;
}
yOff += gaugeUnit;
} }
yOff += gaugeUnit;
}
} }
void Toolbar::draw(boo::IGraphicsCommandQueue* gfxQ) void Toolbar::draw(boo::IGraphicsCommandQueue* gfxQ) {
{ View::draw(gfxQ);
View::draw(gfxQ); gfxQ->setShaderDataBinding(m_vertsBinding);
gfxQ->setShaderDataBinding(m_vertsBinding); gfxQ->draw(0, 10);
gfxQ->draw(0, 10);
for (std::vector<ViewChild<View*>>& u : m_children)
for (ViewChild<View*>& c : u)
c.m_view->draw(gfxQ);
}
for (std::vector<ViewChild<View*>>& u : m_children)
for (ViewChild<View*>& c : u)
c.m_view->draw(gfxQ);
} }
} // namespace specter

View File

@ -2,125 +2,116 @@
#include "specter/ViewResources.hpp" #include "specter/ViewResources.hpp"
#include "specter/RootView.hpp" #include "specter/RootView.hpp"
namespace specter namespace specter {
{
#define TOOLTIP_MAX_WIDTH 316 #define TOOLTIP_MAX_WIDTH 316
#define TOOLTIP_MAX_TEXT_WIDTH 300 #define TOOLTIP_MAX_TEXT_WIDTH 300
Tooltip::Tooltip(ViewResources& res, View& parentView, std::string_view title, Tooltip::Tooltip(ViewResources& res, View& parentView, std::string_view title, std::string_view message)
std::string_view message) : View(res, parentView), m_titleStr(title), m_messageStr(message) {
: View(res, parentView), m_titleStr(title), m_messageStr(message) for (int i = 0; i < 16; ++i)
{ m_ttVerts[i].m_color = res.themeData().tooltipBackground();
for (int i=0 ; i<16 ; ++i)
m_ttVerts[i].m_color = res.themeData().tooltipBackground();
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool {
{ buildResources(ctx, res);
buildResources(ctx, res); m_ttBlockBuf = res.m_viewRes.m_bufPool.allocateBlock(res.m_factory);
m_ttBlockBuf = res.m_viewRes.m_bufPool.allocateBlock(res.m_factory); m_vertsBinding.init(ctx, res, 16, m_ttBlockBuf);
m_vertsBinding.init(ctx, res, 16, m_ttBlockBuf); return true;
return true; });
});
for (int i=0 ; i<4 ; ++i) for (int i = 0; i < 4; ++i) {
{ m_cornersOutline[i].reset(new TextView(res, *this, res.m_curveFont, TextView::Alignment::Left, 1));
m_cornersOutline[i].reset(new TextView(res, *this, res.m_curveFont, TextView::Alignment::Left, 1)); m_cornersFilled[i].reset(new TextView(res, *this, res.m_curveFont, TextView::Alignment::Left, 1));
m_cornersFilled[i].reset(new TextView(res, *this, res.m_curveFont, TextView::Alignment::Left, 1)); }
} m_cornersOutline[0]->typesetGlyphs(L"\xF4F0");
m_cornersOutline[0]->typesetGlyphs(L"\xF4F0"); m_cornersFilled[0]->typesetGlyphs(L"\xF4F1", res.themeData().tooltipBackground());
m_cornersFilled[0]->typesetGlyphs(L"\xF4F1", res.themeData().tooltipBackground()); m_cornersOutline[1]->typesetGlyphs(L"\xF4F2");
m_cornersOutline[1]->typesetGlyphs(L"\xF4F2"); m_cornersFilled[1]->typesetGlyphs(L"\xF4F3", res.themeData().tooltipBackground());
m_cornersFilled[1]->typesetGlyphs(L"\xF4F3", res.themeData().tooltipBackground()); m_cornersOutline[2]->typesetGlyphs(L"\xF4F4");
m_cornersOutline[2]->typesetGlyphs(L"\xF4F4"); m_cornersFilled[2]->typesetGlyphs(L"\xF4F5", res.themeData().tooltipBackground());
m_cornersFilled[2]->typesetGlyphs(L"\xF4F5", res.themeData().tooltipBackground()); m_cornersOutline[3]->typesetGlyphs(L"\xF4F6");
m_cornersOutline[3]->typesetGlyphs(L"\xF4F6"); m_cornersFilled[3]->typesetGlyphs(L"\xF4F7", res.themeData().tooltipBackground());
m_cornersFilled[3]->typesetGlyphs(L"\xF4F7", res.themeData().tooltipBackground());
m_title.reset(new TextView(res, *this, res.m_heading14)); m_title.reset(new TextView(res, *this, res.m_heading14));
m_title->typesetGlyphs(m_titleStr); m_title->typesetGlyphs(m_titleStr);
m_message.reset(new MultiLineTextView(res, *this, res.m_mainFont)); m_message.reset(new MultiLineTextView(res, *this, res.m_mainFont));
m_message->typesetGlyphs(m_messageStr, zeus::CColor::skWhite, m_message->typesetGlyphs(m_messageStr, zeus::CColor::skWhite, int(TOOLTIP_MAX_TEXT_WIDTH * res.pixelFactor()));
int(TOOLTIP_MAX_TEXT_WIDTH * res.pixelFactor()));
float pf = res.pixelFactor(); float pf = res.pixelFactor();
std::pair<int,int> margin = m_cornersOutline[0]->queryGlyphDimensions(0); std::pair<int, int> margin = m_cornersOutline[0]->queryGlyphDimensions(0);
m_nomWidth = std::min(int(TOOLTIP_MAX_WIDTH * pf), m_nomWidth = std::min(int(TOOLTIP_MAX_WIDTH * pf),
int(std::max(m_title->nominalWidth(), m_message->nominalWidth()) + margin.first * 2)); int(std::max(m_title->nominalWidth(), m_message->nominalWidth()) + margin.first * 2));
m_nomHeight = m_title->nominalHeight() + m_message->nominalHeight() + margin.second * 3; m_nomHeight = m_title->nominalHeight() + m_message->nominalHeight() + margin.second * 3;
} }
void Tooltip::setVerts(int width, int height, float pf) void Tooltip::setVerts(int width, int height, float pf) {
{ std::pair<int, int> margin = m_cornersFilled[0]->queryGlyphDimensions(0);
std::pair<int,int> margin = m_cornersFilled[0]->queryGlyphDimensions(0); width = std::max(width, margin.first * 2);
width = std::max(width, margin.first*2); height = std::max(height, margin.second * 2);
height = std::max(height, margin.second*2);
m_ttVerts[0].m_pos.assign(0, height-margin.second, 0); m_ttVerts[0].m_pos.assign(0, height - margin.second, 0);
m_ttVerts[1].m_pos.assign(0, margin.second, 0); m_ttVerts[1].m_pos.assign(0, margin.second, 0);
m_ttVerts[2].m_pos.assign(width, height-margin.second, 0); m_ttVerts[2].m_pos.assign(width, height - margin.second, 0);
m_ttVerts[3].m_pos.assign(width, margin.second, 0); m_ttVerts[3].m_pos.assign(width, margin.second, 0);
m_ttVerts[4].m_pos.assign(width, margin.second, 0); m_ttVerts[4].m_pos.assign(width, margin.second, 0);
m_ttVerts[5].m_pos.assign(margin.first, height, 0); m_ttVerts[5].m_pos.assign(margin.first, height, 0);
m_ttVerts[6].m_pos.assign(margin.first, height, 0); m_ttVerts[6].m_pos.assign(margin.first, height, 0);
m_ttVerts[7].m_pos.assign(margin.first, height-margin.second, 0); m_ttVerts[7].m_pos.assign(margin.first, height - margin.second, 0);
m_ttVerts[8].m_pos.assign(width-margin.first, height, 0); m_ttVerts[8].m_pos.assign(width - margin.first, height, 0);
m_ttVerts[9].m_pos.assign(width-margin.first, height-margin.second, 0); m_ttVerts[9].m_pos.assign(width - margin.first, height - margin.second, 0);
m_ttVerts[10].m_pos.assign(width-margin.first, height-margin.second, 0); m_ttVerts[10].m_pos.assign(width - margin.first, height - margin.second, 0);
m_ttVerts[11].m_pos.assign(margin.first, margin.second, 0); m_ttVerts[11].m_pos.assign(margin.first, margin.second, 0);
m_ttVerts[12].m_pos.assign(margin.first, margin.second, 0); m_ttVerts[12].m_pos.assign(margin.first, margin.second, 0);
m_ttVerts[13].m_pos.assign(margin.first, 0, 0); m_ttVerts[13].m_pos.assign(margin.first, 0, 0);
m_ttVerts[14].m_pos.assign(width-margin.first, margin.second, 0); m_ttVerts[14].m_pos.assign(width - margin.first, margin.second, 0);
m_ttVerts[15].m_pos.assign(width-margin.first, 0, 0); m_ttVerts[15].m_pos.assign(width - margin.first, 0, 0);
m_vertsBinding.load<decltype(m_ttVerts)>(m_ttVerts); m_vertsBinding.load<decltype(m_ttVerts)>(m_ttVerts);
} }
void Tooltip::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) void Tooltip::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) {
{ View::resized(root, sub);
View::resized(root, sub); float pf = rootView().viewRes().pixelFactor();
float pf = rootView().viewRes().pixelFactor(); setVerts(m_nomWidth, m_nomHeight, pf);
setVerts(m_nomWidth, m_nomHeight, pf); m_ttBlock.setViewRect(root, sub);
m_ttBlock.setViewRect(root, sub); m_ttBlockBuf.access().finalAssign(m_ttBlock);
m_ttBlockBuf.access().finalAssign(m_ttBlock);
std::pair<int,int> margin = m_cornersFilled[0]->queryGlyphDimensions(0); std::pair<int, int> margin = m_cornersFilled[0]->queryGlyphDimensions(0);
boo::SWindowRect textRect = sub; boo::SWindowRect textRect = sub;
textRect.location[0] += margin.first; textRect.location[0] += margin.first;
textRect.location[1] += margin.second * 1.5; textRect.location[1] += margin.second * 1.5;
m_message->resized(root, textRect); m_message->resized(root, textRect);
textRect.location[1] += m_message->nominalHeight() + margin.second; textRect.location[1] += m_message->nominalHeight() + margin.second;
m_title->resized(root, textRect); m_title->resized(root, textRect);
boo::SWindowRect cornerRect = sub; boo::SWindowRect cornerRect = sub;
cornerRect.location[1] += m_nomHeight - margin.second; // Upper left cornerRect.location[1] += m_nomHeight - margin.second; // Upper left
m_cornersOutline[0]->resized(root, cornerRect); m_cornersOutline[0]->resized(root, cornerRect);
m_cornersFilled[0]->resized(root, cornerRect); m_cornersFilled[0]->resized(root, cornerRect);
cornerRect.location[0] += m_nomWidth - margin.first; // Upper right cornerRect.location[0] += m_nomWidth - margin.first; // Upper right
m_cornersOutline[1]->resized(root, cornerRect); m_cornersOutline[1]->resized(root, cornerRect);
m_cornersFilled[1]->resized(root, cornerRect); m_cornersFilled[1]->resized(root, cornerRect);
cornerRect.location[1] = sub.location[1]; // Lower right cornerRect.location[1] = sub.location[1]; // Lower right
m_cornersOutline[2]->resized(root, cornerRect); m_cornersOutline[2]->resized(root, cornerRect);
m_cornersFilled[2]->resized(root, cornerRect); m_cornersFilled[2]->resized(root, cornerRect);
cornerRect.location[0] = sub.location[0]; // Lower left cornerRect.location[0] = sub.location[0]; // Lower left
m_cornersOutline[3]->resized(root, cornerRect); m_cornersOutline[3]->resized(root, cornerRect);
m_cornersFilled[3]->resized(root, cornerRect); m_cornersFilled[3]->resized(root, cornerRect);
} }
void Tooltip::draw(boo::IGraphicsCommandQueue* gfxQ) void Tooltip::draw(boo::IGraphicsCommandQueue* gfxQ) {
{ gfxQ->setShaderDataBinding(m_vertsBinding);
gfxQ->setShaderDataBinding(m_vertsBinding); gfxQ->draw(0, 16);
gfxQ->draw(0, 16);
for (int i=0 ; i<4 ; ++i) for (int i = 0; i < 4; ++i)
m_cornersFilled[i]->draw(gfxQ); m_cornersFilled[i]->draw(gfxQ);
m_title->draw(gfxQ); m_title->draw(gfxQ);
m_message->draw(gfxQ); m_message->draw(gfxQ);
} }
} } // namespace specter

View File

@ -1,69 +1,57 @@
#include "specter/Translator.hpp" #include "specter/Translator.hpp"
#include "logvisor/logvisor.hpp" #include "logvisor/logvisor.hpp"
namespace specter namespace specter {
{
static logvisor::Module Log("specter::Translator"); static logvisor::Module Log("specter::Translator");
Locale::Locale(std::string_view name, std::string_view fullName, Locale::Locale(std::string_view name, std::string_view fullName, const unsigned char* yamlSource, size_t yamlLength)
const unsigned char* yamlSource, size_t yamlLength) : m_name(name), m_fullName(fullName) {
: m_name(name), m_fullName(fullName) athena::io::YAMLDocReader reader;
{ yaml_parser_set_input_string(reader.getParser(), yamlSource, yamlLength);
athena::io::YAMLDocReader reader; reader.parse(nullptr);
yaml_parser_set_input_string(reader.getParser(), yamlSource, yamlLength); m_rootNode = reader.releaseRootNode();
reader.parse(nullptr); if (m_rootNode) {
m_rootNode = reader.releaseRootNode(); m_langNode = m_rootNode->findMapChild(name.data());
if (m_rootNode) if (!m_langNode)
{ Log.report(logvisor::Fatal, "no root node '%s' found in locale", name.data());
m_langNode = m_rootNode->findMapChild(name.data()); } else
if (!m_langNode) Log.report(logvisor::Warning, "locale empty");
Log.report(logvisor::Fatal, "no root node '%s' found in locale", name.data());
}
else
Log.report(logvisor::Warning, "locale empty");
} }
void Translator::setLocale(const Locale* targetLocale) void Translator::setLocale(const Locale* targetLocale) {
{ if (!targetLocale)
if (!targetLocale) Log.report(logvisor::Fatal, "null locale");
Log.report(logvisor::Fatal, "null locale"); m_targetLocale = targetLocale;
m_targetLocale = targetLocale;
} }
static std::string_view RecursiveLookup(const athena::io::YAMLNode* node, static std::string_view RecursiveLookup(const athena::io::YAMLNode* node, std::string_view::const_iterator start,
std::string_view::const_iterator start, std::string_view::const_iterator end) {
std::string_view::const_iterator end) for (std::string_view::const_iterator it = start; it != end; ++it) {
{ if (*it == '/') {
for (std::string_view::const_iterator it = start ; it != end ; ++it) const athena::io::YAMLNode* ch = node->findMapChild(std::string(start, it));
{ if (!ch)
if (*it == '/')
{
const athena::io::YAMLNode* ch = node->findMapChild(std::string(start, it));
if (!ch)
return nullptr;
return RecursiveLookup(ch, it+1, end);
}
}
const athena::io::YAMLNode* ch = node->findMapChild(std::string(start, end));
if (!ch)
return {};
return ch->m_scalarString;
}
std::string_view Translator::translate(std::string_view key) const
{
if (!m_targetLocale->rootNode())
return nullptr; return nullptr;
return RecursiveLookup(ch, it + 1, end);
return RecursiveLookup(m_targetLocale->rootNode(), key.cbegin(), key.cend()); }
}
const athena::io::YAMLNode* ch = node->findMapChild(std::string(start, end));
if (!ch)
return {};
return ch->m_scalarString;
} }
std::string_view Translator::translateOr(std::string_view key, std::string_view vor) const std::string_view Translator::translate(std::string_view key) const {
{ if (!m_targetLocale->rootNode())
std::string_view find = translate(key); return nullptr;
if (!find.empty())
return find; return RecursiveLookup(m_targetLocale->rootNode(), key.cbegin(), key.cend());
return vor;
} }
std::string_view Translator::translateOr(std::string_view key, std::string_view vor) const {
std::string_view find = translate(key);
if (!find.empty())
return find;
return vor;
} }
} // namespace specter

View File

@ -3,121 +3,98 @@
#include "specter/RootView.hpp" #include "specter/RootView.hpp"
#include "hecl/Pipeline.hpp" #include "hecl/Pipeline.hpp"
namespace specter namespace specter {
{
static logvisor::Module Log("specter::View"); static logvisor::Module Log("specter::View");
zeus::CMatrix4f g_PlatformMatrix; zeus::CMatrix4f g_PlatformMatrix;
void View::Resources::init(boo::IGraphicsDataFactory::Context& ctx, const IThemeData& theme) void View::Resources::init(boo::IGraphicsDataFactory::Context& ctx, const IThemeData& theme) {
{ switch (ctx.platform()) {
switch (ctx.platform()) case boo::IGraphicsDataFactory::Platform::Vulkan:
{ g_PlatformMatrix.m[1][1] = -1.f;
case boo::IGraphicsDataFactory::Platform::Vulkan: break;
g_PlatformMatrix.m[1][1] = -1.f; default:
break; break;
default: }
break; m_solidShader = hecl::conv->convert(ctx, Shader_SpecterViewShaderSolid{});
} m_texShader = hecl::conv->convert(ctx, Shader_SpecterViewShaderTex{});
m_solidShader = hecl::conv->convert(ctx, Shader_SpecterViewShaderSolid{});
m_texShader = hecl::conv->convert(ctx, Shader_SpecterViewShaderTex{});
} }
void View::buildResources(boo::IGraphicsDataFactory::Context& ctx, ViewResources& res) void View::buildResources(boo::IGraphicsDataFactory::Context& ctx, ViewResources& res) {
{ m_viewVertBlockBuf = res.m_viewRes.m_bufPool.allocateBlock(res.m_factory);
m_viewVertBlockBuf = res.m_viewRes.m_bufPool.allocateBlock(res.m_factory); m_bgVertsBinding.init(ctx, res, 4, m_viewVertBlockBuf);
m_bgVertsBinding.init(ctx, res, 4, m_viewVertBlockBuf);
} }
View::View(ViewResources& res) View::View(ViewResources& res)
: m_rootView(*static_cast<RootView*>(this)), : m_rootView(*static_cast<RootView*>(this)), m_parentView(*static_cast<RootView*>(this)) {}
m_parentView(*static_cast<RootView*>(this)) {}
View::View(ViewResources& res, View& parentView) View::View(ViewResources& res, View& parentView) : m_rootView(parentView.rootView()), m_parentView(parentView) {}
: m_rootView(parentView.rootView()),
m_parentView(parentView) {}
void View::updateSize() void View::updateSize() { resized(m_rootView.rootRect(), m_subRect); }
{
resized(m_rootView.rootRect(), m_subRect); void View::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) {
m_subRect = sub;
m_viewVertBlock.setViewRect(root, sub);
m_bgRect[0].m_pos.assign(0.f, sub.size[1], 0.f);
m_bgRect[1].m_pos.assign(0.f, 0.f, 0.f);
m_bgRect[2].m_pos.assign(sub.size[0], sub.size[1], 0.f);
m_bgRect[3].m_pos.assign(sub.size[0], 0.f, 0.f);
if (m_viewVertBlockBuf)
m_viewVertBlockBuf.access().finalAssign(m_viewVertBlock);
m_bgVertsBinding.load<decltype(m_bgRect)>(m_bgRect);
} }
void View::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) void View::resized(const ViewBlock& vb, const boo::SWindowRect& sub) {
{ m_subRect = sub;
m_subRect = sub; m_bgRect[0].m_pos.assign(0.f, sub.size[1], 0.f);
m_viewVertBlock.setViewRect(root, sub); m_bgRect[1].m_pos.assign(0.f, 0.f, 0.f);
m_bgRect[0].m_pos.assign(0.f, sub.size[1], 0.f); m_bgRect[2].m_pos.assign(sub.size[0], sub.size[1], 0.f);
m_bgRect[1].m_pos.assign(0.f, 0.f, 0.f); m_bgRect[3].m_pos.assign(sub.size[0], 0.f, 0.f);
m_bgRect[2].m_pos.assign(sub.size[0], sub.size[1], 0.f); if (m_viewVertBlockBuf)
m_bgRect[3].m_pos.assign(sub.size[0], 0.f, 0.f); m_viewVertBlockBuf.access().finalAssign(vb);
if (m_viewVertBlockBuf) m_bgVertsBinding.load<decltype(m_bgRect)>(m_bgRect);
m_viewVertBlockBuf.access().finalAssign(m_viewVertBlock);
m_bgVertsBinding.load<decltype(m_bgRect)>(m_bgRect);
} }
void View::resized(const ViewBlock& vb, const boo::SWindowRect& sub) void View::draw(boo::IGraphicsCommandQueue* gfxQ) {
{ if (m_bgVertsBinding.m_shaderBinding) {
m_subRect = sub; gfxQ->setShaderDataBinding(m_bgVertsBinding);
m_bgRect[0].m_pos.assign(0.f, sub.size[1], 0.f); gfxQ->draw(0, 4);
m_bgRect[1].m_pos.assign(0.f, 0.f, 0.f); }
m_bgRect[2].m_pos.assign(sub.size[0], sub.size[1], 0.f);
m_bgRect[3].m_pos.assign(sub.size[0], 0.f, 0.f);
if (m_viewVertBlockBuf)
m_viewVertBlockBuf.access().finalAssign(vb);
m_bgVertsBinding.load<decltype(m_bgRect)>(m_bgRect);
} }
void View::draw(boo::IGraphicsCommandQueue* gfxQ) void View::commitResources(ViewResources& res, const boo::FactoryCommitFunc& commitFunc) {
{ res.m_factory->commitTransaction(commitFunc BooTrace);
if (m_bgVertsBinding.m_shaderBinding)
{
gfxQ->setShaderDataBinding(m_bgVertsBinding);
gfxQ->draw(0, 4);
}
} }
void View::commitResources(ViewResources& res, const boo::FactoryCommitFunc& commitFunc) void View::VertexBufferBindingSolid::init(boo::IGraphicsDataFactory::Context& ctx, ViewResources& res, size_t count,
{ const hecl::UniformBufferPool<ViewBlock>::Token& viewBlockBuf) {
res.m_factory->commitTransaction(commitFunc BooTrace); m_vertsBuf = res.m_viewRes.m_solidPool.allocateBlock(res.m_factory, count);
auto vBufInfo = m_vertsBuf.getBufferInfo();
auto uBufInfo = viewBlockBuf.getBufferInfo();
boo::ObjToken<boo::IGraphicsBuffer> bufs[] = {uBufInfo.first.get()};
size_t bufOffs[] = {size_t(uBufInfo.second)};
size_t bufSizes[] = {sizeof(ViewBlock)};
m_shaderBinding =
ctx.newShaderDataBinding(res.m_viewRes.m_solidShader, vBufInfo.first.get(), nullptr, nullptr, 1, bufs, nullptr,
bufOffs, bufSizes, 0, nullptr, nullptr, nullptr, vBufInfo.second);
} }
void View::VertexBufferBindingSolid::init(boo::IGraphicsDataFactory::Context& ctx, void View::VertexBufferBindingTex::init(boo::IGraphicsDataFactory::Context& ctx, ViewResources& res, size_t count,
ViewResources& res, size_t count,
const hecl::UniformBufferPool<ViewBlock>::Token& viewBlockBuf)
{
m_vertsBuf = res.m_viewRes.m_solidPool.allocateBlock(res.m_factory, count);
auto vBufInfo = m_vertsBuf.getBufferInfo();
auto uBufInfo = viewBlockBuf.getBufferInfo();
boo::ObjToken<boo::IGraphicsBuffer> bufs[] = {uBufInfo.first.get()};
size_t bufOffs[] = {size_t(uBufInfo.second)};
size_t bufSizes[] = {sizeof(ViewBlock)};
m_shaderBinding = ctx.newShaderDataBinding(res.m_viewRes.m_solidShader,
vBufInfo.first.get(), nullptr,
nullptr, 1, bufs, nullptr, bufOffs,
bufSizes, 0, nullptr, nullptr, nullptr, vBufInfo.second);
}
void View::VertexBufferBindingTex::init(boo::IGraphicsDataFactory::Context& ctx,
ViewResources& res, size_t count,
const hecl::UniformBufferPool<ViewBlock>::Token& viewBlockBuf, const hecl::UniformBufferPool<ViewBlock>::Token& viewBlockBuf,
const boo::ObjToken<boo::ITexture>& texture) const boo::ObjToken<boo::ITexture>& texture) {
{ m_vertsBuf = res.m_viewRes.m_texPool.allocateBlock(res.m_factory, count);
m_vertsBuf = res.m_viewRes.m_texPool.allocateBlock(res.m_factory, count); auto vBufInfo = m_vertsBuf.getBufferInfo();
auto vBufInfo = m_vertsBuf.getBufferInfo(); auto uBufInfo = viewBlockBuf.getBufferInfo();
auto uBufInfo = viewBlockBuf.getBufferInfo();
boo::ObjToken<boo::IGraphicsBuffer> bufs[] = {uBufInfo.first.get()}; boo::ObjToken<boo::IGraphicsBuffer> bufs[] = {uBufInfo.first.get()};
size_t bufOffs[] = {size_t(uBufInfo.second)}; size_t bufOffs[] = {size_t(uBufInfo.second)};
size_t bufSizes[] = {sizeof(ViewBlock)}; size_t bufSizes[] = {sizeof(ViewBlock)};
boo::ObjToken<boo::ITexture> tex[] = {texture}; boo::ObjToken<boo::ITexture> tex[] = {texture};
m_shaderBinding = ctx.newShaderDataBinding(res.m_viewRes.m_texShader, m_shaderBinding = ctx.newShaderDataBinding(res.m_viewRes.m_texShader, vBufInfo.first.get(), nullptr, nullptr, 1, bufs,
vBufInfo.first.get(), nullptr, nullptr, bufOffs, bufSizes, 1, tex, nullptr, nullptr, vBufInfo.second);
nullptr, 1, bufs, nullptr, bufOffs,
bufSizes, 1, tex, nullptr, nullptr, vBufInfo.second);
} }
} // namespace specter
}

View File

@ -1,75 +1,69 @@
#include "specter/ViewResources.hpp" #include "specter/ViewResources.hpp"
namespace specter namespace specter {
{
static logvisor::Module Log("specter::ViewResources"); static logvisor::Module Log("specter::ViewResources");
void ViewResources::init(boo::IGraphicsDataFactory* factory, FontCache* fcache, const IThemeData* theme, float pf) void ViewResources::init(boo::IGraphicsDataFactory* factory, FontCache* fcache, const IThemeData* theme, float pf) {
{ if (!factory || !fcache || !theme)
if (!factory || !fcache || !theme) Log.report(logvisor::Fatal, "all arguments of ViewResources::init() must be non-null");
Log.report(logvisor::Fatal, "all arguments of ViewResources::init() must be non-null"); m_pixelFactor = pf;
m_pixelFactor = pf; m_factory = factory;
m_factory = factory; m_theme = theme;
m_theme = theme; m_fcache = fcache;
m_fcache = fcache; unsigned dpi = 72.f * m_pixelFactor;
unsigned dpi = 72.f * m_pixelFactor;
m_curveFont = fcache->prepCurvesFont(AllCharFilter, false, 8.f, dpi); m_curveFont = fcache->prepCurvesFont(AllCharFilter, false, 8.f, dpi);
factory->commitTransaction([&](boo::IGraphicsDataFactory::Context& ctx) { factory->commitTransaction([&](boo::IGraphicsDataFactory::Context& ctx) {
init(ctx, *theme, fcache); init(ctx, *theme, fcache);
return true; return true;
} BooTrace); } BooTrace);
} }
void ViewResources::destroyResData() void ViewResources::destroyResData() {
{ m_viewRes.destroy();
m_viewRes.destroy(); m_textRes.destroy();
m_textRes.destroy(); m_splitRes.destroy();
m_splitRes.destroy(); m_toolbarRes.destroy();
m_toolbarRes.destroy(); m_buttonRes.destroy();
m_buttonRes.destroy();
} }
void ViewResources::prepFontCacheSync() void ViewResources::prepFontCacheSync() {
{ unsigned dpi = 72.f * m_pixelFactor;
unsigned dpi = 72.f * m_pixelFactor; if (m_fcacheInterrupt.load())
if (m_fcacheInterrupt.load()) return;
return; m_mainFont = m_fcache->prepMainFont(AllCharFilter, false, 10.f, dpi);
m_mainFont = m_fcache->prepMainFont(AllCharFilter, false, 10.f, dpi); if (m_fcacheInterrupt.load())
if (m_fcacheInterrupt.load()) return;
return; m_monoFont10 = m_fcache->prepMonoFont(AllCharFilter, false, 10.f, dpi);
m_monoFont10 = m_fcache->prepMonoFont(AllCharFilter, false, 10.f, dpi); if (m_fcacheInterrupt.load())
if (m_fcacheInterrupt.load()) return;
return; m_monoFont18 = m_fcache->prepMonoFont(AllCharFilter, false, 18.f, dpi);
m_monoFont18 = m_fcache->prepMonoFont(AllCharFilter, false, 18.f, dpi); if (m_fcacheInterrupt.load())
if (m_fcacheInterrupt.load()) return;
return; m_heading14 = m_fcache->prepMainFont(LatinAndJapaneseCharFilter, false, 14.f, dpi);
m_heading14 = m_fcache->prepMainFont(LatinAndJapaneseCharFilter, false, 14.f, dpi); if (m_fcacheInterrupt.load())
if (m_fcacheInterrupt.load()) return;
return; m_heading18 = m_fcache->prepMainFont(LatinAndJapaneseCharFilter, false, 18.f, dpi);
m_heading18 = m_fcache->prepMainFont(LatinAndJapaneseCharFilter, false, 18.f, dpi); if (m_fcacheInterrupt.load())
if (m_fcacheInterrupt.load()) return;
return; m_titleFont = m_fcache->prepMainFont(LatinCharFilter, false, 36.f, dpi);
m_titleFont = m_fcache->prepMainFont(LatinCharFilter, false, 36.f, dpi); if (m_fcacheInterrupt.load())
if (m_fcacheInterrupt.load()) return;
return; m_fcache->closeBuiltinFonts();
m_fcache->closeBuiltinFonts(); m_fcacheReady.store(true);
m_fcacheReady.store(true);
} }
void ViewResources::prepFontCacheAsync(boo::IWindow* window) void ViewResources::prepFontCacheAsync(boo::IWindow* window) {
{ m_fcacheReady.store(false);
m_fcacheReady.store(false); m_fcacheThread = std::thread([this]() { prepFontCacheSync(); });
m_fcacheThread = std::thread([this]() { prepFontCacheSync(); });
} }
void ViewResources::resetPixelFactor(float pf) void ViewResources::resetPixelFactor(float pf) {
{ m_pixelFactor = pf;
m_pixelFactor = pf; unsigned dpi = 72.f * m_pixelFactor;
unsigned dpi = 72.f * m_pixelFactor; m_curveFont = m_fcache->prepCurvesFont(AllCharFilter, false, 8.f, dpi);
m_curveFont = m_fcache->prepCurvesFont(AllCharFilter, false, 8.f, dpi); prepFontCacheSync();
prepFontCacheSync();
} }
void ViewResources::resetTheme(const IThemeData* theme) { m_theme = theme; } void ViewResources::resetTheme(const IThemeData* theme) { m_theme = theme; }

@ -1 +1 @@
Subproject commit e8dfecbb6e60dd79e01b62645ac8cf967cfd0a59 Subproject commit e172225845f7e683e40d809f60c6677b289adc64