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/Icon.hpp"
namespace specter
{
namespace specter {
class Button : public Control
{
class Button : public Control {
public:
enum class Style
{
Block,
Text,
};
enum class Style {
Block,
Text,
};
private:
Style m_style;
IButtonBinding::MenuStyle m_menuStyle = IButtonBinding::MenuStyle::None;
zeus::CColor m_textColor;
zeus::CColor m_bgColor;
std::string m_textStr;
std::unique_ptr<TextView> m_text;
std::unique_ptr<IconView> m_icon;
Style m_style;
IButtonBinding::MenuStyle m_menuStyle = IButtonBinding::MenuStyle::None;
zeus::CColor m_textColor;
zeus::CColor m_bgColor;
std::string m_textStr;
std::unique_ptr<TextView> m_text;
std::unique_ptr<IconView> m_icon;
SolidShaderVert m_verts[40];
VertexBufferBindingSolid m_vertsBinding;
SolidShaderVert m_verts[40];
VertexBufferBindingSolid m_vertsBinding;
void _loadVerts()
{
m_vertsBinding.load<decltype(m_verts)>(m_verts);
}
void _loadVerts() { m_vertsBinding.load<decltype(m_verts)>(m_verts); }
RectangleConstraint m_constraint;
int m_nomWidth, m_nomHeight;
int m_textWidth, m_textIconWidth;
RectangleConstraint m_constraint;
int m_nomWidth, m_nomHeight;
int m_textWidth, m_textIconWidth;
struct ButtonTarget : View
{
Button& m_button;
struct ButtonTarget : View {
Button& m_button;
bool m_pressed = false;
bool m_hovered = false;
bool m_pressed = false;
bool m_hovered = false;
void setInactive();
void setHover();
void setPressed();
void setDisabled();
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&);
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 mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey);
void mouseMove(const boo::SWindowCoord&);
void mouseEnter(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);
ButtonTarget(ViewResources& res, Button& button) : View(res, button), m_button(button) {}
};
ViewChild<std::unique_ptr<ButtonTarget>> m_buttonTarget;
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;}
struct MenuTarget : View {
Button& m_button;
void closeMenu(const boo::SWindowCoord& coord);
ViewChild<std::unique_ptr<View>>& getMenu() {return m_modalMenu;}
bool m_pressed = false;
bool m_hovered = false;
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);
}
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 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"
namespace specter
{
namespace specter {
class Control;
class Button;
enum class ControlType
{
Button,
Float,
Int,
String,
CVar
enum class ControlType { Button, Float, Int, String, CVar };
struct IControlBinding {
virtual ControlType type() const = 0;
virtual std::string_view name(const Control* control) const = 0;
virtual std::string_view help(const Control* control) const { return {}; }
};
struct IControlBinding
{
virtual ControlType type() const = 0;
virtual std::string_view name(const Control* control) const=0;
virtual std::string_view help(const Control* control) const {return {};}
struct IButtonBinding : IControlBinding {
ControlType type() const { return ControlType::Button; }
static IButtonBinding* castTo(IControlBinding* bind) {
return bind->type() == ControlType::Button ? static_cast<IButtonBinding*>(bind) : nullptr;
}
/** 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
{
ControlType type() const { return ControlType::Button; }
static IButtonBinding* castTo(IControlBinding* bind)
{ return bind->type() == ControlType::Button ? static_cast<IButtonBinding*>(bind) : nullptr; }
/** 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 IFloatBinding : IControlBinding {
ControlType type() const { return ControlType::Float; }
static IFloatBinding* castTo(IControlBinding* bind) {
return bind->type() == ControlType::Float ? static_cast<IFloatBinding*>(bind) : nullptr;
}
virtual float getDefault(const Control* control) const { return 0.0; }
virtual std::pair<float, float> getBounds(const Control* control) const { return std::make_pair(FLT_MIN, FLT_MAX); }
virtual void changed(const Control* control, float val) = 0;
};
struct IFloatBinding : IControlBinding
{
ControlType type() const { return ControlType::Float; }
static IFloatBinding* castTo(IControlBinding* bind)
{ return bind->type() == ControlType::Float ? static_cast<IFloatBinding*>(bind) : nullptr; }
virtual float getDefault(const Control* control) const {return 0.0;}
virtual std::pair<float,float> getBounds(const Control* control) const {return std::make_pair(FLT_MIN, FLT_MAX);}
virtual void changed(const Control* control, float val)=0;
struct IIntBinding : IControlBinding {
ControlType type() const { return ControlType::Int; }
static IIntBinding* castTo(IControlBinding* bind) {
return bind->type() == ControlType::Int ? static_cast<IIntBinding*>(bind) : nullptr;
}
virtual int getDefault(const Control* control) const { return 0; }
virtual std::pair<int, int> getBounds(const Control* control) const { return std::make_pair(INT_MIN, INT_MAX); }
virtual void changed(const Control* control, int val) = 0;
};
struct IIntBinding : IControlBinding
{
ControlType type() const { return ControlType::Int; }
static IIntBinding* castTo(IControlBinding* bind)
{ return bind->type() == ControlType::Int ? static_cast<IIntBinding*>(bind) : nullptr; }
virtual int getDefault(const Control* control) const {return 0;}
virtual std::pair<int,int> getBounds(const Control* control) const {return std::make_pair(INT_MIN, INT_MAX);}
virtual void changed(const Control* control, int val)=0;
struct IStringBinding : IControlBinding {
ControlType type() const { return ControlType::String; }
static IStringBinding* castTo(IControlBinding* bind) {
return bind->type() == ControlType::String ? static_cast<IStringBinding*>(bind) : nullptr;
}
virtual std::string getDefault(const Control* control) const { return ""; }
virtual void changed(const Control* control, std::string_view val) = 0;
};
struct IStringBinding : IControlBinding
{
ControlType type() const { return ControlType::String; }
static IStringBinding* castTo(IControlBinding* bind)
{ return bind->type() == ControlType::String ? static_cast<IStringBinding*>(bind) : nullptr; }
virtual std::string getDefault(const Control* control) const {return "";}
virtual void changed(const Control* control, std::string_view val)=0;
struct CVarControlBinding : IControlBinding {
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(); }
};
struct CVarControlBinding : IControlBinding
{
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
{
class Control : public View {
protected:
IControlBinding* m_controlBinding = nullptr;
IControlBinding* m_controlBinding = nullptr;
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:
static std::recursive_mutex m_textInputLk;
ITextInputView(ViewResources& res, View& parentView,
IControlBinding* controlBinding)
: Control(res, parentView, controlBinding) {}
static std::recursive_mutex m_textInputLk;
ITextInputView(ViewResources& res, View& parentView, IControlBinding* controlBinding)
: Control(res, parentView, controlBinding) {}
public:
virtual void clipboardCopy() {}
virtual void clipboardCut() {}
virtual void clipboardPaste() {}
virtual void clipboardCopy() {}
virtual void clipboardCut() {}
virtual void clipboardPaste() {}
};
}
} // namespace specter

View File

@ -12,343 +12,286 @@
#include "PathButtons.hpp"
#include <hecl/hecl.hpp>
namespace specter
{
namespace specter {
class FileBrowser : public ModalWindow, public IPathButtonsBinding
{
class FileBrowser : public ModalWindow, public IPathButtonsBinding {
public:
enum class Type
{
SaveFile,
SaveDirectory,
OpenFile,
OpenDirectory,
NewHECLProject,
OpenHECLProject
};
enum class Type { SaveFile, SaveDirectory, OpenFile, OpenDirectory, NewHECLProject, OpenHECLProject };
private:
Type m_type;
hecl::SystemString m_path;
std::vector<hecl::SystemString> m_comps;
bool m_showingHidden = false;
Type m_type;
hecl::SystemString m_path;
std::vector<hecl::SystemString> m_comps;
bool m_showingHidden = false;
class LeftSide : public View
{
friend class FileBrowser;
FileBrowser& m_fb;
LeftSide(FileBrowser& fb, ViewResources& res) : View(res, fb), m_fb(fb) {}
void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub);
void draw(boo::IGraphicsCommandQueue* gfxQ);
} m_left;
class LeftSide : public View {
friend class FileBrowser;
FileBrowser& m_fb;
LeftSide(FileBrowser& fb, ViewResources& res) : View(res, fb), m_fb(fb) {}
void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub);
void draw(boo::IGraphicsCommandQueue* gfxQ);
} m_left;
class RightSide : public View
{
friend class FileBrowser;
FileBrowser& m_fb;
RightSide(FileBrowser& fb, ViewResources& res) : View(res, fb), m_fb(fb) {}
void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub);
void draw(boo::IGraphicsCommandQueue* gfxQ);
} m_right;
class RightSide : public View {
friend class FileBrowser;
FileBrowser& m_fb;
RightSide(FileBrowser& fb, ViewResources& res) : View(res, fb), m_fb(fb) {}
void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub);
void draw(boo::IGraphicsCommandQueue* gfxQ);
} m_right;
ViewChild<std::unique_ptr<SplitView>> m_split;
ViewChild<std::unique_ptr<SplitView>> m_split;
void okActivated(bool viaButton);
struct OKButton : IButtonBinding
{
FileBrowser& m_fb;
ViewChild<std::unique_ptr<Button>> m_button;
std::string m_text;
OKButton(FileBrowser& fb, ViewResources& res, std::string_view text)
: m_fb(fb), m_text(text)
{
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);}
} m_ok;
void okActivated(bool viaButton);
struct OKButton : IButtonBinding {
FileBrowser& m_fb;
ViewChild<std::unique_ptr<Button>> m_button;
std::string m_text;
OKButton(FileBrowser& fb, ViewResources& res, std::string_view text) : m_fb(fb), m_text(text) {
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); }
} m_ok;
void cancelActivated();
struct CancelButton : IButtonBinding
{
FileBrowser& m_fb;
ViewChild<std::unique_ptr<Button>> m_button;
std::string m_text;
CancelButton(FileBrowser& fb, ViewResources& res, std::string_view text)
: m_fb(fb), m_text(text)
{
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();}
} m_cancel;
void cancelActivated();
struct CancelButton : IButtonBinding {
FileBrowser& m_fb;
ViewChild<std::unique_ptr<Button>> m_button;
std::string m_text;
CancelButton(FileBrowser& fb, ViewResources& res, std::string_view text) : m_fb(fb), m_text(text) {
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(); }
} m_cancel;
void pathButtonActivated(size_t idx);
ViewChild<std::unique_ptr<PathButtons>> m_pathButtons;
void pathButtonActivated(size_t idx);
ViewChild<std::unique_ptr<PathButtons>> m_pathButtons;
ViewChild<std::unique_ptr<TextField>> m_fileField;
struct FileFieldBind : IStringBinding
{
FileBrowser& m_browser;
std::string m_name;
FileFieldBind(FileBrowser& browser, const IViewManager& vm)
: m_browser(browser), m_name(vm.translateOr("file_name", "File Name")) {}
std::string_view name(const Control* control) const {return m_name;}
void changed(const Control* control, std::string_view val)
{
}
} m_fileFieldBind;
ViewChild<std::unique_ptr<TextField>> m_fileField;
struct FileFieldBind : IStringBinding {
FileBrowser& m_browser;
std::string m_name;
FileFieldBind(FileBrowser& browser, const IViewManager& vm)
: m_browser(browser), m_name(vm.translateOr("file_name", "File Name")) {}
std::string_view name(const Control* control) const { return m_name; }
void changed(const Control* control, std::string_view val) {}
} m_fileFieldBind;
std::unique_ptr<MessageWindow> m_confirmWindow;
std::unique_ptr<MessageWindow> m_confirmWindow;
struct FileListingDataBind : ITableDataBinding, ITableStateBinding
{
FileBrowser& m_fb;
struct FileListingDataBind : ITableDataBinding, ITableStateBinding {
FileBrowser& m_fb;
struct Entry
{
hecl::SystemString m_path;
std::string m_name;
std::string m_type;
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);
}
struct Entry {
hecl::SystemString m_path;
std::string m_name;
std::string m_type;
std::string m_size;
};
std::vector<Entry> m_entries;
BookmarkDataBind m_systemBookmarkBind;
std::unique_ptr<TextView> m_systemBookmarksLabel;
ViewChild<std::unique_ptr<Table>> m_systemBookmarks;
std::string m_nameCol;
std::string m_typeCol;
std::string m_sizeCol;
BookmarkDataBind m_projectBookmarkBind;
std::unique_ptr<TextView> m_projectBookmarksLabel;
ViewChild<std::unique_ptr<Table>> m_projectBookmarks;
std::string m_dirStr;
std::string m_projStr;
std::string m_fileStr;
BookmarkDataBind m_recentBookmarkBind;
std::unique_ptr<TextView> m_recentBookmarksLabel;
ViewChild<std::unique_ptr<Table>> m_recentBookmarks;
size_t columnCount() const { return 3; }
size_t rowCount() const { return m_entries.size(); }
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:
FileBrowser(ViewResources& res, View& parentView, std::string_view title, Type type,
std::function<void(bool, hecl::SystemStringView)> returnFunc)
: FileBrowser(res, parentView, title, type, hecl::GetcwdStr(), returnFunc) {}
FileBrowser(ViewResources& res, View& parentView, std::string_view title, Type type,
hecl::SystemStringView initialPath,
std::function<void(bool, hecl::SystemStringView)> returnFunc);
FileBrowser(ViewResources& res, View& parentView, std::string_view title, Type type,
std::function<void(bool, hecl::SystemStringView)> returnFunc)
: FileBrowser(res, parentView, title, type, hecl::GetcwdStr(), returnFunc) {}
FileBrowser(ViewResources& res, View& parentView, std::string_view title, Type type,
hecl::SystemStringView initialPath, std::function<void(bool, hecl::SystemStringView)> returnFunc);
static std::vector<hecl::SystemString> PathComponents(hecl::SystemStringView path);
static void SyncBookmarkSelections(Table& table, BookmarkDataBind& binding,
const hecl::SystemString& sel);
static std::vector<hecl::SystemString> PathComponents(hecl::SystemStringView path);
static void SyncBookmarkSelections(Table& table, BookmarkDataBind& binding, const hecl::SystemString& sel);
void navigateToPath(hecl::SystemStringView path);
bool showingHidden() const {return m_showingHidden;}
void setShowingHidden(bool showingHidden)
{
m_showingHidden = showingHidden;
navigateToPath(m_path);
}
void updateContentOpacity(float opacity);
void navigateToPath(hecl::SystemStringView path);
bool showingHidden() const { return m_showingHidden; }
void setShowingHidden(bool showingHidden) {
m_showingHidden = showingHidden;
navigateToPath(m_path);
}
void updateContentOpacity(float opacity);
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 touchDown(const boo::STouchCoord&, uintptr_t);
void touchUp(const boo::STouchCoord&, uintptr_t);
void touchMove(const boo::STouchCoord&, uintptr_t);
void charKeyDown(unsigned long, boo::EModifierKey, bool);
void specialKeyDown(boo::ESpecialKey, boo::EModifierKey, bool);
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 touchDown(const boo::STouchCoord&, uintptr_t);
void touchUp(const boo::STouchCoord&, uintptr_t);
void touchMove(const boo::STouchCoord&, uintptr_t);
void charKeyDown(unsigned long, boo::EModifierKey, bool);
void specialKeyDown(boo::ESpecialKey, boo::EModifierKey, bool);
void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub);
void think();
void draw(boo::IGraphicsCommandQueue* gfxQ);
void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub);
void think();
void draw(boo::IGraphicsCommandQueue* gfxQ);
};
}
} // namespace specter

View File

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

View File

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

View File

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

View File

@ -5,89 +5,82 @@
#include "ScrollView.hpp"
#include "IMenuNode.hpp"
namespace specter
{
namespace specter {
class Menu : public View
{
IMenuNode* m_rootNode;
IMenuNode* m_thisNode;
std::unique_ptr<Menu> m_subMenu;
std::unique_ptr<TextView> m_headText;
class Menu : public View {
IMenuNode* m_rootNode;
IMenuNode* m_thisNode;
std::unique_ptr<Menu> m_subMenu;
std::unique_ptr<TextView> m_headText;
int m_cWidth, m_cHeight, m_cTop;
int m_cWidth, m_cHeight, m_cTop;
SolidShaderVert m_verts[8];
VertexBufferBindingSolid m_vertsBinding;
void setVerts(int width, int height, float pf);
SolidShaderVert m_verts[8];
VertexBufferBindingSolid m_vertsBinding;
void setVerts(int width, int height, float pf);
struct ContentView : View
{
Menu& m_menu;
ContentView(ViewResources& res, Menu& menu);
struct ContentView : View {
Menu& m_menu;
ContentView(ViewResources& res, Menu& menu);
boo::SWindowRect m_scissorRect;
SolidShaderVert m_hlVerts[4];
VertexBufferBindingSolid m_hlVertsBinding;
boo::SWindowRect m_scissorRect;
SolidShaderVert m_hlVerts[4];
VertexBufferBindingSolid m_hlVertsBinding;
size_t m_highlightedItem = -1;
void setHighlightedItem(size_t idx);
void unsetHighlightedItem(size_t idx)
{
if (m_highlightedItem == idx)
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);
size_t m_highlightedItem = -1;
void setHighlightedItem(size_t idx);
void unsetHighlightedItem(size_t idx) {
if (m_highlightedItem == idx)
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 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 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 "Button.hpp"
namespace specter
{
namespace specter {
class MessageWindow : public ModalWindow
{
class MessageWindow : public ModalWindow {
public:
enum class Type
{
InfoOk,
ErrorOk,
ConfirmOkCancel
};
enum class Type { InfoOk, ErrorOk, ConfirmOkCancel };
private:
Type m_type;
std::function<void(bool ok)> m_func;
Type m_type;
std::function<void(bool ok)> m_func;
std::unique_ptr<MultiLineTextView> m_text;
std::unique_ptr<MultiLineTextView> m_text;
struct OKBinding : IButtonBinding
{
MessageWindow& m_mw;
std::string m_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;}
void activated(const Button* button, const boo::SWindowCoord& coord)
{
m_mw.m_func(true);
}
} m_okBind;
ViewChild<std::unique_ptr<Button>> m_ok;
struct OKBinding : IButtonBinding {
MessageWindow& m_mw;
std::string m_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; }
void activated(const Button* button, const boo::SWindowCoord& coord) { m_mw.m_func(true); }
} m_okBind;
ViewChild<std::unique_ptr<Button>> m_ok;
struct CancelBinding : IButtonBinding
{
MessageWindow& m_mw;
std::string m_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;}
void activated(const Button* button, const boo::SWindowCoord& coord)
{
m_mw.m_func(false);
}
} m_cancelBind;
ViewChild<std::unique_ptr<Button>> m_cancel;
struct CancelBinding : IButtonBinding {
MessageWindow& m_mw;
std::string m_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; }
void activated(const Button* button, const boo::SWindowCoord& coord) { m_mw.m_func(false); }
} m_cancelBind;
ViewChild<std::unique_ptr<Button>> m_cancel;
public:
MessageWindow(ViewResources& res, View& parentView,
Type type, std::string_view message, std::function<void(bool ok)> func);
MessageWindow(ViewResources& res, View& parentView, Type type, std::string_view message,
std::function<void(bool ok)> func);
void updateContentOpacity(float opacity)
{
zeus::CColor color = zeus::CColor::lerp({1,1,1,0}, {1,1,1,1}, opacity);
ModalWindow::setMultiplyColor(color);
m_text->setMultiplyColor(color);
m_ok.m_view->setMultiplyColor(color);
m_cancel.m_view->setMultiplyColor(color);
}
void updateContentOpacity(float opacity) {
zeus::CColor color = zeus::CColor::lerp({1, 1, 1, 0}, {1, 1, 1, 1}, opacity);
ModalWindow::setMultiplyColor(color);
m_text->setMultiplyColor(color);
m_ok.m_view->setMultiplyColor(color);
m_cancel.m_view->setMultiplyColor(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 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& root, const boo::SWindowRect& sub);
void draw(boo::IGraphicsCommandQueue* gfxQ);
void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub);
void draw(boo::IGraphicsCommandQueue* gfxQ);
};
}
} // namespace specter

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,42 +1,36 @@
#pragma once
namespace specter
{
class Outliner
{
class Node : public View
{
struct INodeController
{
virtual boo::ITexture* icon() const { return nullptr; }
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();
namespace specter {
class Outliner {
class Node : public View {
struct INodeController {
virtual boo::ITexture* icon() const { return nullptr; }
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();
};
};
} // namespace specter

View File

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

View File

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

View File

@ -12,242 +12,215 @@
#include "optional.hpp"
#include "boo/boo.hpp"
namespace specter
{
namespace specter {
class RootView : public View
{
boo::IWindow* m_window = nullptr;
boo::ObjToken<boo::ITextureR> m_renderTex;
boo::SWindowRect m_rootRect = {};
bool m_resizeRTDirty = false;
bool m_destroyed = false;
IViewManager& m_viewMan;
ViewResources* m_viewRes;
ITextInputView* m_activeTextView = nullptr;
View* m_activeDragView = nullptr;
Button* m_activeMenuButton = nullptr;
class RootView : public View {
boo::IWindow* m_window = nullptr;
boo::ObjToken<boo::ITextureR> m_renderTex;
boo::SWindowRect m_rootRect = {};
bool m_resizeRTDirty = false;
bool m_destroyed = false;
IViewManager& m_viewMan;
ViewResources* m_viewRes;
ITextInputView* m_activeTextView = nullptr;
View* m_activeDragView = nullptr;
Button* m_activeMenuButton = nullptr;
ViewChild<std::unique_ptr<View>> m_rightClickMenu;
boo::SWindowRect m_rightClickMenuRootAndLoc;
ViewChild<std::unique_ptr<View>> m_rightClickMenu;
boo::SWindowRect m_rightClickMenuRootAndLoc;
SplitView* m_hoverSplitDragView = nullptr;
bool m_activeSplitDragView = false;
SplitView* recursiveTestSplitHover(SplitView* sv, const boo::SWindowCoord& coord) const;
SplitView* m_hoverSplitDragView = nullptr;
bool m_activeSplitDragView = false;
SplitView* recursiveTestSplitHover(SplitView* sv, const boo::SWindowCoord& coord) const;
boo::DeferredWindowEvents<RootView> m_events;
boo::DeferredWindowEvents<RootView> m_events;
struct SplitMenuSystem : IMenuNode
{
RootView& m_rv;
std::string m_text;
struct SplitMenuSystem : IMenuNode {
RootView& m_rv;
std::string m_text;
SplitView* m_splitView = nullptr;
enum class Phase
{
Inactive,
InteractiveSplit,
InteractiveJoin,
} m_phase = Phase::Inactive;
int m_interactiveSlot = 0;
float m_interactiveSplit = 0.5;
bool m_interactiveDown = false;
SplitView* m_splitView = nullptr;
enum class Phase {
Inactive,
InteractiveSplit,
InteractiveJoin,
} m_phase = Phase::Inactive;
int m_interactiveSlot = 0;
float m_interactiveSplit = 0.5;
bool m_interactiveDown = false;
VertexBufferBindingSolid m_vertsBinding;
ViewBlock m_viewBlock;
hecl::UniformBufferPool<ViewBlock>::Token m_viewVertBlockBuf;
SolidShaderVert m_verts[32];
void setArrowVerts(const boo::SWindowRect& rect, SplitView::ArrowDir dir);
void setLineVerts(const boo::SWindowRect& rect, float split, SplitView::Axis axis);
VertexBufferBindingSolid m_vertsBinding;
ViewBlock m_viewBlock;
hecl::UniformBufferPool<ViewBlock>::Token m_viewVertBlockBuf;
SolidShaderVert m_verts[32];
void setArrowVerts(const boo::SWindowRect& rect, SplitView::ArrowDir dir);
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 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 resized();
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;
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;
}
void startSplitDrag(SplitView* sv, const boo::SWindowCoord& coord)
{
m_hoverSplitDragView = sv;
m_activeSplitDragView = true;
sv->startDragSplit(coord);
}
boo::SWindowCoord m_deferredCoord;
bool m_deferredSplit = false;
bool m_deferredJoin = false;
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();
}
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;
void resetTooltip(ViewResources& res);
void displayTooltip(std::string_view name, std::string_view help);
public:
RootView(IViewManager& viewMan, ViewResources& res, boo::IWindow* window);
~RootView();
void beginInteractiveJoin(SplitView* sv, const boo::SWindowCoord& coord)
{
m_splitMenuSystem->m_phase = SplitMenuSystem::Phase::InteractiveJoin;
m_splitMenuSystem->m_splitView = sv;
m_splitMenuSystem->mouseMove(coord);
}
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 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:
void _updateCursor()
{
if (m_spaceCornerHover)
m_window->setCursor(boo::EMouseCursor::Crosshairs);
else if (m_vSplitHover)
m_window->setCursor(boo::EMouseCursor::HorizontalArrow);
else if (m_hSplitHover)
m_window->setCursor(boo::EMouseCursor::VerticalArrow);
else if (m_textFieldHover)
m_window->setCursor(boo::EMouseCursor::IBeam);
else
m_window->setCursor(boo::EMouseCursor::Pointer);
}
void _updateCursor() {
if (m_spaceCornerHover)
m_window->setCursor(boo::EMouseCursor::Crosshairs);
else if (m_vSplitHover)
m_window->setCursor(boo::EMouseCursor::HorizontalArrow);
else if (m_hSplitHover)
m_window->setCursor(boo::EMouseCursor::VerticalArrow);
else if (m_textFieldHover)
m_window->setCursor(boo::EMouseCursor::IBeam);
else
m_window->setCursor(boo::EMouseCursor::Pointer);
}
std::vector<View*> m_views;
std::unique_ptr<Tooltip> m_tooltip;
std::vector<View*> m_views;
std::unique_ptr<Tooltip> m_tooltip;
};
}
} // namespace specter

View File

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

View File

@ -4,79 +4,72 @@
#include "Toolbar.hpp"
#include "SplitView.hpp"
namespace specter
{
namespace specter {
class Space;
struct ISplitSpaceController;
struct ISpaceController
{
virtual bool spaceSplitAllowed() const {return false;}
virtual ISplitSpaceController* spaceSplit(SplitView::Axis axis, int thisSlot) {return nullptr;}
struct ISpaceController {
virtual bool spaceSplitAllowed() const { return false; }
virtual ISplitSpaceController* spaceSplit(SplitView::Axis axis, int thisSlot) { return nullptr; }
};
struct ISplitSpaceController
{
virtual SplitView* splitView()=0;
virtual void updateSplit(float split)=0;
virtual void joinViews(SplitView* thisSplit, int thisSlot, SplitView* otherSplit, int otherSlot)=0;
struct ISplitSpaceController {
virtual SplitView* splitView() = 0;
virtual void updateSplit(float split) = 0;
virtual void joinViews(SplitView* thisSplit, int thisSlot, SplitView* otherSplit, int otherSlot) = 0;
};
class Space : public View
{
friend class RootView;
ISpaceController& m_controller;
Toolbar::Position m_tbPos;
ViewChild<std::unique_ptr<Toolbar>> m_toolbar;
ViewChild<View*> m_contentView;
class Space : public View {
friend class RootView;
ISpaceController& m_controller;
Toolbar::Position m_tbPos;
ViewChild<std::unique_ptr<Toolbar>> m_toolbar;
ViewChild<View*> m_contentView;
bool m_cornerDrag = false;
int m_cornerDragPoint[2];
bool m_cornerDrag = false;
int m_cornerDragPoint[2];
struct CornerView : View
{
Space& m_space;
VertexBufferBindingSolid m_vertexBinding;
bool m_flip;
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&);
struct CornerView : View {
Space& m_space;
VertexBufferBindingSolid m_vertexBinding;
bool m_flip;
CornerView(ViewResources& res, Space& space, const zeus::CColor& triColor);
void mouseEnter(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);
};
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)
{
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);
}
SplitView* findSplitViewOnSide(SplitView::Axis axis, int side);
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; }
}
} // namespace specter

View File

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

View File

@ -5,139 +5,128 @@
#include "TextView.hpp"
#include <array>
namespace specter
{
namespace specter {
#define SPECTER_TABLE_MAX_ROWS 128ul
enum class SortDirection
{
None,
Ascending,
Descending
enum class SortDirection { None, Ascending, Descending };
struct ITableDataBinding {
virtual size_t columnCount() const = 0;
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
{
virtual size_t columnCount() const=0;
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 ITableStateBinding {
virtual float getColumnSplit(size_t cIdx) const { return -1.0; }
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) {}
};
struct ITableStateBinding
{
virtual float getColumnSplit(size_t cIdx) const {return -1.0;}
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 {
ITableDataBinding* m_data;
ITableStateBinding* m_state;
class Table : public View
{
ITableDataBinding* m_data;
ITableStateBinding* m_state;
size_t m_maxColumns;
size_t m_rows = 0;
size_t m_columns = 0;
size_t m_selectedRow = -1;
size_t m_deferredActivation = -1;
size_t m_clickFrames = 15;
size_t m_maxColumns;
size_t m_rows = 0;
size_t m_columns = 0;
size_t m_selectedRow = -1;
size_t m_deferredActivation = -1;
size_t m_clickFrames = 15;
struct CellView : public View {
Table& m_t;
std::unique_ptr<TextView> m_text;
size_t m_c, m_r;
boo::SWindowRect m_scissorRect;
uint64_t m_textHash = 0;
CellView(Table& t, ViewResources& res);
struct CellView : public View
{
Table& m_t;
std::unique_ptr<TextView> m_text;
size_t m_c, m_r;
boo::SWindowRect m_scissorRect;
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);
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 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 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 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 <boo/IWindow.hpp>
namespace specter
{
namespace specter {
class TextField : public ITextInputView
{
bool m_hasTextSet = false;
bool m_hasMarkSet = false;
std::string m_textStr;
std::string m_deferredTextStr;
std::string m_deferredMarkStr;
std::unique_ptr<TextView> m_text;
std::unique_ptr<TextView> m_errText;
class TextField : public ITextInputView {
bool m_hasTextSet = false;
bool m_hasMarkSet = false;
std::string m_textStr;
std::string m_deferredTextStr;
std::string m_deferredMarkStr;
std::unique_ptr<TextView> m_text;
std::unique_ptr<TextView> m_errText;
SolidShaderVert m_verts[41];
VertexBufferBindingSolid m_vertsBinding;
SolidShaderVert m_verts[41];
VertexBufferBindingSolid m_vertsBinding;
int m_nomWidth = 0;
int m_nomHeight = 0;
int m_nomWidth = 0;
int m_nomHeight = 0;
bool m_hasSelectionClear = false;
bool m_hasSelectionSet = false;
bool m_hasCursorSet = false;
size_t m_selectionStart = 0;
size_t m_deferredSelectionStart = 0;
size_t m_selectionCount = 0;
size_t m_deferredSelectionCount = 0;
size_t m_markReplStart = 0;
size_t m_deferredMarkReplStart = 0;
size_t m_markReplCount = 0;
size_t m_deferredMarkReplCount = 0;
size_t m_markSelStart = 0;
size_t m_deferredMarkSelStart = 0;
size_t m_markSelCount = 0;
size_t m_deferredMarkSelCount = 0;
size_t m_cursorPos = 0;
size_t m_deferredCursorPos = SIZE_MAX;
size_t m_cursorFrames = 0;
size_t m_clickFrames = 15;
size_t m_clickFrames2 = 15;
size_t m_errorFrames = 360;
bool m_hasSelectionClear = false;
bool m_hasSelectionSet = false;
bool m_hasCursorSet = false;
size_t m_selectionStart = 0;
size_t m_deferredSelectionStart = 0;
size_t m_selectionCount = 0;
size_t m_deferredSelectionCount = 0;
size_t m_dragStart = 0;
size_t m_dragging = 0;
size_t m_markReplStart = 0;
size_t m_deferredMarkReplStart = 0;
size_t m_markReplCount = 0;
size_t m_deferredMarkReplCount = 0;
bool m_active = false;
bool m_error = false;
size_t m_markSelStart = 0;
size_t m_deferredMarkSelStart = 0;
size_t m_markSelCount = 0;
size_t m_deferredMarkSelCount = 0;
enum class BGState
{
Inactive,
Hover,
Disabled
} m_bgState = BGState::Inactive;
void setInactive();
void setHover();
void setDisabled();
void refreshBg();
size_t m_cursorPos = 0;
size_t m_deferredCursorPos = SIZE_MAX;
size_t m_cursorFrames = 0;
size_t m_clickFrames = 15;
size_t m_clickFrames2 = 15;
size_t m_errorFrames = 360;
size_t m_dragStart = 0;
size_t m_dragging = 0;
bool m_active = false;
bool m_error = false;
enum class BGState { Inactive, Hover, Disabled } m_bgState = BGState::Inactive;
void setInactive();
void setHover();
void setDisabled();
void refreshBg();
public:
TextField(ViewResources& res, View& parentView, IStringBinding* strBind);
TextField(ViewResources& res, View& parentView, IStringBinding* strBind);
std::string_view getText() const {return m_textStr;}
void setText(std::string_view str);
std::string_view getText() const { return m_textStr; }
void setText(std::string_view str);
void clipboardCopy();
void clipboardCut();
void clipboardPaste();
void clipboardCopy();
void clipboardCut();
void clipboardPaste();
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 specialKeyDown(boo::ESpecialKey, boo::EModifierKey, bool);
bool hasMarkedText() const;
std::pair<int,int> markedRange() const;
std::pair<int,int> selectedRange() const;
void setMarkedText(std::string_view str,
const std::pair<int,int>& selectedRange,
const std::pair<int,int>& replacementRange);
void unmarkText();
std::string substringForRange(const std::pair<int,int>& range,
std::pair<int,int>& actualRange) const;
void insertText(std::string_view str, const std::pair<int,int>& range);
int characterIndexAtPoint(const boo::SWindowCoord& point) const;
boo::SWindowRect rectForCharacterRange(const std::pair<int,int>& range,
std::pair<int,int>& actualRange) const;
void think();
void resized(const boo::SWindowRect& rootView, const boo::SWindowRect& sub);
void draw(boo::IGraphicsCommandQueue* gfxQ);
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 specialKeyDown(boo::ESpecialKey, boo::EModifierKey, bool);
int nominalWidth() const {return m_nomWidth;}
int nominalHeight() const {return m_nomHeight;}
bool hasMarkedText() const;
std::pair<int, int> markedRange() const;
std::pair<int, int> selectedRange() const;
void setMarkedText(std::string_view str, const std::pair<int, int>& selectedRange,
const std::pair<int, int>& replacementRange);
void unmarkText();
void setActive(bool active);
void setCursorPos(size_t pos);
void setErrorState(std::string_view message);
void clearErrorState();
std::string substringForRange(const std::pair<int, int>& range, std::pair<int, int>& actualRange) const;
void insertText(std::string_view str, const std::pair<int, int>& range);
int characterIndexAtPoint(const boo::SWindowCoord& point) const;
boo::SWindowRect rectForCharacterRange(const std::pair<int, int>& range, std::pair<int, int>& actualRange) const;
void setSelectionRange(size_t start, size_t count);
void clearSelectionRange();
void think();
void resized(const boo::SWindowRect& rootView, const boo::SWindowRect& sub);
void draw(boo::IGraphicsCommandQueue* gfxQ);
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_errText)
m_errText->setMultiplyColor(color);
}
int nominalWidth() const { return m_nomWidth; }
int nominalHeight() const { return m_nomHeight; }
void setActive(bool active);
void setCursorPos(size_t pos);
void setErrorState(std::string_view message);
void clearErrorState();
void setSelectionRange(size_t start, size_t count);
void clearSelectionRange();
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_errText)
m_errText->setMultiplyColor(color);
}
private:
void _setCursorPos();
void _reallySetCursorPos(size_t pos);
void _setSelectionRange();
void _reallySetSelectionRange(size_t start, size_t len);
void _reallySetMarkRange(size_t start, size_t len);
void _clearSelectionRange();
void _setText();
void _setMarkedText();
void _setCursorPos();
void _reallySetCursorPos(size_t pos);
void _setSelectionRange();
void _reallySetSelectionRange(size_t start, size_t len);
void _reallySetMarkRange(size_t start, size_t len);
void _clearSelectionRange();
void _setText();
void _setMarkedText();
};
}
} // namespace specter

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

@ -2,8 +2,7 @@
#include "specter/ViewResources.hpp"
#include "specter/RootView.hpp"
namespace specter
{
namespace specter {
#define WIRE_START 0
#define WIRE_FRAMES 40
@ -16,483 +15,451 @@ namespace specter
#define CONTENT_MARGIN 10
#define WINDOW_MIN_DIM 16
void ModalWindow::setLineVerts(int width, int height, float pf, float t)
{
std::pair<int,int> margin = m_cornersOutline[0]->queryGlyphDimensions(0);
float t1 = zeus::clamp(0.f, t * 2.f, 1.f);
float t2 = zeus::clamp(0.f, t * 2.f - 1.f, 1.f);
void ModalWindow::setLineVerts(int width, int height, float pf, float t) {
std::pair<int, int> margin = m_cornersOutline[0]->queryGlyphDimensions(0);
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 lineLeft = 0;
float lineRight = pf*LINE_WIDTH;
float lineTop = height-margin.second;
float lineBottom = margin.second;
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[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[4].m_pos = m_verts.lineVerts[3].m_pos;
float lineLeft = 0;
float lineRight = pf * LINE_WIDTH;
float lineTop = height - margin.second;
float lineBottom = margin.second;
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[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[4].m_pos = m_verts.lineVerts[3].m_pos;
lineLeft = margin.first;
lineRight = width-margin.first;
lineTop = height;
lineBottom = height-pf*LINE_WIDTH;
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[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[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;
lineLeft = margin.first;
lineRight = width - margin.first;
lineTop = height;
lineBottom = height - pf * LINE_WIDTH;
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[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[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;
lineLeft = width-pf*LINE_WIDTH;
lineRight = width;
lineTop = height-margin.second;
lineBottom = margin.second;
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[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[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;
lineLeft = width - pf * LINE_WIDTH;
lineRight = width;
lineTop = height - margin.second;
lineBottom = margin.second;
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[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[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;
lineLeft = margin.first;
lineRight = width-margin.first;
lineTop = pf*LINE_WIDTH;
lineBottom = 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[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[21].m_pos = zeus::CVector3f::lerp({lineLeft, lineBottom, 0}, {lineRight, lineBottom, 0}, t2);
lineLeft = margin.first;
lineRight = width - margin.first;
lineTop = pf * LINE_WIDTH;
lineBottom = 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[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[21].m_pos = zeus::CVector3f::lerp({lineLeft, lineBottom, 0}, {lineRight, lineBottom, 0}, t2);
}
void ModalWindow::setLineVertsOut(int width, int height, float pf, float t)
{
std::pair<int,int> margin = m_cornersOutline[0]->queryGlyphDimensions(0);
float t1 = zeus::clamp(0.f, t * 2.f - 1.f, 1.f);
float t2 = zeus::clamp(0.f, t * 2.f, 1.f);
void ModalWindow::setLineVertsOut(int width, int height, float pf, float t) {
std::pair<int, int> margin = m_cornersOutline[0]->queryGlyphDimensions(0);
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 lineLeft = 0;
float lineRight = pf*LINE_WIDTH;
float lineTop = height-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[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[3].m_pos.assign(lineRight, lineBottom, 0);
m_verts.lineVerts[4].m_pos = m_verts.lineVerts[3].m_pos;
float lineLeft = 0;
float lineRight = pf * LINE_WIDTH;
float lineTop = height - 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[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[3].m_pos.assign(lineRight, lineBottom, 0);
m_verts.lineVerts[4].m_pos = m_verts.lineVerts[3].m_pos;
lineLeft = margin.first;
lineRight = width-margin.first;
lineTop = height;
lineBottom = height-pf*LINE_WIDTH;
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[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[9].m_pos.assign(lineRight, lineBottom, 0);
m_verts.lineVerts[10].m_pos = m_verts.lineVerts[9].m_pos;
lineLeft = margin.first;
lineRight = width - margin.first;
lineTop = height;
lineBottom = height - pf * LINE_WIDTH;
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[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[9].m_pos.assign(lineRight, lineBottom, 0);
m_verts.lineVerts[10].m_pos = m_verts.lineVerts[9].m_pos;
lineLeft = width-pf*LINE_WIDTH;
lineRight = width;
lineTop = height-margin.second;
lineBottom = margin.second;
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[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[15].m_pos.assign(lineRight, lineBottom, 0);
m_verts.lineVerts[16].m_pos = m_verts.lineVerts[15].m_pos;
lineLeft = width - pf * LINE_WIDTH;
lineRight = width;
lineTop = height - margin.second;
lineBottom = margin.second;
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[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[15].m_pos.assign(lineRight, lineBottom, 0);
m_verts.lineVerts[16].m_pos = m_verts.lineVerts[15].m_pos;
lineLeft = margin.first;
lineRight = width-margin.first;
lineTop = pf*LINE_WIDTH;
lineBottom = 0;
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[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[21].m_pos.assign(lineRight, lineBottom, 0);
lineLeft = margin.first;
lineRight = width - margin.first;
lineTop = pf * LINE_WIDTH;
lineBottom = 0;
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[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[21].m_pos.assign(lineRight, lineBottom, 0);
}
void ModalWindow::setLineColors(float t)
{
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 t3 = zeus::clamp(0.f, t * 2.f - 2.f, 1.f);
void ModalWindow::setLineColors(float t) {
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 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 c2 = zeus::CColor::lerp(m_line1, m_line2, t2);
zeus::CColor c3 = zeus::CColor::lerp(m_line1, m_line2, t3);
zeus::CColor c1 = zeus::CColor::lerp(m_line1, m_line2, t1);
zeus::CColor c2 = zeus::CColor::lerp(m_line1, m_line2, t2);
zeus::CColor c3 = zeus::CColor::lerp(m_line1, m_line2, t3);
m_cornersOutline[0]->colorGlyphs(c1);
if (t < 0.5)
{
m_cornersOutline[1]->colorGlyphs(zeus::CColor::skClear);
m_cornersOutline[2]->colorGlyphs(zeus::CColor::skClear);
m_cornersOutline[3]->colorGlyphs(zeus::CColor::skClear);
}
else if (t < 1.0)
{
m_cornersOutline[1]->colorGlyphs(c2);
m_cornersOutline[2]->colorGlyphs(zeus::CColor::skClear);
m_cornersOutline[3]->colorGlyphs(c2);
}
else
{
m_cornersOutline[1]->colorGlyphs(c2);
m_cornersOutline[2]->colorGlyphs(c3);
m_cornersOutline[3]->colorGlyphs(c2);
}
m_cornersOutline[0]->colorGlyphs(c1);
if (t < 0.5) {
m_cornersOutline[1]->colorGlyphs(zeus::CColor::skClear);
m_cornersOutline[2]->colorGlyphs(zeus::CColor::skClear);
m_cornersOutline[3]->colorGlyphs(zeus::CColor::skClear);
} else if (t < 1.0) {
m_cornersOutline[1]->colorGlyphs(c2);
m_cornersOutline[2]->colorGlyphs(zeus::CColor::skClear);
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[1].m_color = c2;
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[4].m_color = m_verts.lineVerts[3].m_color;
m_verts.lineVerts[0].m_color = c1;
m_verts.lineVerts[1].m_color = c2;
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[4].m_color = m_verts.lineVerts[3].m_color;
m_verts.lineVerts[5].m_color = c1;
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[8].m_color = c2;
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[5].m_color = c1;
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[8].m_color = c2;
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[11].m_color = c2;
m_verts.lineVerts[12].m_color = m_verts.lineVerts[11].m_color;
m_verts.lineVerts[13].m_color = c3;
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[16].m_color = m_verts.lineVerts[15].m_color;
m_verts.lineVerts[11].m_color = c2;
m_verts.lineVerts[12].m_color = m_verts.lineVerts[11].m_color;
m_verts.lineVerts[13].m_color = c3;
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[16].m_color = m_verts.lineVerts[15].m_color;
m_verts.lineVerts[17].m_color = c2;
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[20].m_color = c3;
m_verts.lineVerts[21].m_color = m_verts.lineVerts[20].m_color;
m_verts.lineVerts[17].m_color = c2;
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[20].m_color = c3;
m_verts.lineVerts[21].m_color = m_verts.lineVerts[20].m_color;
}
void ModalWindow::setLineColorsOut(float t)
{
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 t3 = zeus::clamp(0.f, t * 2.f - 2.f, 1.f);
void ModalWindow::setLineColorsOut(float t) {
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 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 c2 = zeus::CColor::lerp(m_line2Clear, m_line2, t2);
zeus::CColor c3 = zeus::CColor::lerp(m_line2Clear, m_line2, t3);
zeus::CColor c1 = zeus::CColor::lerp(m_line2Clear, m_line2, t1);
zeus::CColor c2 = zeus::CColor::lerp(m_line2Clear, m_line2, t2);
zeus::CColor c3 = zeus::CColor::lerp(m_line2Clear, m_line2, t3);
m_cornersOutline[2]->colorGlyphs(c1);
if (t < 0.5)
{
m_cornersOutline[1]->colorGlyphs(zeus::CColor::skClear);
m_cornersOutline[0]->colorGlyphs(zeus::CColor::skClear);
m_cornersOutline[3]->colorGlyphs(zeus::CColor::skClear);
}
else if (t < 1.0)
{
m_cornersOutline[1]->colorGlyphs(c2);
m_cornersOutline[0]->colorGlyphs(zeus::CColor::skClear);
m_cornersOutline[3]->colorGlyphs(c2);
}
else
{
m_cornersOutline[1]->colorGlyphs(c2);
m_cornersOutline[0]->colorGlyphs(c3);
m_cornersOutline[3]->colorGlyphs(c2);
}
m_cornersOutline[2]->colorGlyphs(c1);
if (t < 0.5) {
m_cornersOutline[1]->colorGlyphs(zeus::CColor::skClear);
m_cornersOutline[0]->colorGlyphs(zeus::CColor::skClear);
m_cornersOutline[3]->colorGlyphs(zeus::CColor::skClear);
} else if (t < 1.0) {
m_cornersOutline[1]->colorGlyphs(c2);
m_cornersOutline[0]->colorGlyphs(zeus::CColor::skClear);
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[1].m_color = c2;
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[4].m_color = m_verts.lineVerts[3].m_color;
m_verts.lineVerts[0].m_color = c3;
m_verts.lineVerts[1].m_color = c2;
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[4].m_color = m_verts.lineVerts[3].m_color;
m_verts.lineVerts[5].m_color = c3;
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[8].m_color = c2;
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[5].m_color = c3;
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[8].m_color = c2;
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[11].m_color = c2;
m_verts.lineVerts[12].m_color = m_verts.lineVerts[11].m_color;
m_verts.lineVerts[13].m_color = c1;
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[16].m_color = m_verts.lineVerts[15].m_color;
m_verts.lineVerts[11].m_color = c2;
m_verts.lineVerts[12].m_color = m_verts.lineVerts[11].m_color;
m_verts.lineVerts[13].m_color = c1;
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[16].m_color = m_verts.lineVerts[15].m_color;
m_verts.lineVerts[17].m_color = c2;
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[20].m_color = c1;
m_verts.lineVerts[21].m_color = m_verts.lineVerts[20].m_color;
m_verts.lineVerts[17].m_color = c2;
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[20].m_color = c1;
m_verts.lineVerts[21].m_color = m_verts.lineVerts[20].m_color;
}
void ModalWindow::setFillVerts(int width, int height, float pf)
{
std::pair<int,int> margin = m_cornersFilled[0]->queryGlyphDimensions(0);
void ModalWindow::setFillVerts(int width, int height, float pf) {
std::pair<int, int> margin = m_cornersFilled[0]->queryGlyphDimensions(0);
float fillLeft = pf*LINE_WIDTH;
float fillRight = width-pf*LINE_WIDTH;
float fillTop = height-margin.second;
float fillBottom = margin.second;
m_verts.fillVerts[0].m_pos.assign(fillLeft, fillTop, 0);
m_verts.fillVerts[1].m_pos.assign(fillLeft, fillBottom, 0);
m_verts.fillVerts[2].m_pos.assign(fillRight, fillTop, 0);
m_verts.fillVerts[3].m_pos.assign(fillRight, fillBottom, 0);
m_verts.fillVerts[4].m_pos = m_verts.fillVerts[3].m_pos;
float fillLeft = pf * LINE_WIDTH;
float fillRight = width - pf * LINE_WIDTH;
float fillTop = height - margin.second;
float fillBottom = margin.second;
m_verts.fillVerts[0].m_pos.assign(fillLeft, fillTop, 0);
m_verts.fillVerts[1].m_pos.assign(fillLeft, fillBottom, 0);
m_verts.fillVerts[2].m_pos.assign(fillRight, fillTop, 0);
m_verts.fillVerts[3].m_pos.assign(fillRight, fillBottom, 0);
m_verts.fillVerts[4].m_pos = m_verts.fillVerts[3].m_pos;
fillLeft = margin.first;
fillRight = width-margin.first;
fillTop = height-pf*LINE_WIDTH;
fillBottom = height-margin.second;
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[7].m_pos.assign(fillLeft, fillBottom, 0);
m_verts.fillVerts[8].m_pos.assign(fillRight, fillTop, 0);
m_verts.fillVerts[9].m_pos.assign(fillRight, fillBottom, 0);
m_verts.fillVerts[10].m_pos = m_verts.fillVerts[9].m_pos;
fillLeft = margin.first;
fillRight = width - margin.first;
fillTop = height - pf * LINE_WIDTH;
fillBottom = height - margin.second;
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[7].m_pos.assign(fillLeft, fillBottom, 0);
m_verts.fillVerts[8].m_pos.assign(fillRight, fillTop, 0);
m_verts.fillVerts[9].m_pos.assign(fillRight, fillBottom, 0);
m_verts.fillVerts[10].m_pos = m_verts.fillVerts[9].m_pos;
fillLeft = margin.first;
fillRight = width-margin.first;
fillTop = margin.second;
fillBottom = pf*LINE_WIDTH;
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[13].m_pos.assign(fillLeft, fillBottom, 0);
m_verts.fillVerts[14].m_pos.assign(fillRight, fillTop, 0);
m_verts.fillVerts[15].m_pos.assign(fillRight, fillBottom, 0);
fillLeft = margin.first;
fillRight = width - margin.first;
fillTop = margin.second;
fillBottom = pf * LINE_WIDTH;
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[13].m_pos.assign(fillLeft, fillBottom, 0);
m_verts.fillVerts[14].m_pos.assign(fillRight, fillTop, 0);
m_verts.fillVerts[15].m_pos.assign(fillRight, fillBottom, 0);
}
void ModalWindow::setFillColors(float t)
{
t = zeus::clamp(0.f, t, 1.f);
zeus::CColor color = zeus::CColor::lerp(m_windowBgClear, m_windowBg, t);
void ModalWindow::setFillColors(float t) {
t = zeus::clamp(0.f, t, 1.f);
zeus::CColor color = zeus::CColor::lerp(m_windowBgClear, m_windowBg, t);
for (int i=0 ; i<16 ; ++i)
m_verts.fillVerts[i].m_color = color;
for (int i=0 ; i<4 ; ++i)
m_cornersFilled[i]->colorGlyphs(color);
for (int i = 0; i < 16; ++i)
m_verts.fillVerts[i].m_color = color;
for (int i = 0; i < 4; ++i)
m_cornersFilled[i]->colorGlyphs(color);
}
ModalWindow::ModalWindow(ViewResources& res, View& parentView, const RectangleConstraint& constraint)
: ModalWindow(res, parentView, constraint, res.themeData().splashBackground()) {}
ModalWindow::ModalWindow(ViewResources& res, View& parentView,
const RectangleConstraint& constraint,
ModalWindow::ModalWindow(ViewResources& res, View& parentView, const RectangleConstraint& constraint,
const zeus::CColor& bgColor)
: View(res, parentView),
m_constraint(constraint),
m_windowBg(bgColor),
m_windowBgClear(m_windowBg),
m_line1(res.themeData().splash1()),
m_line2(res.themeData().splash2()),
m_line2Clear(m_line2)
{
m_windowBgClear[3] = 0.0;
m_line2Clear[3] = 0.0;
: View(res, parentView)
, m_constraint(constraint)
, m_windowBg(bgColor)
, m_windowBgClear(m_windowBg)
, m_line1(res.themeData().splash1())
, m_line2(res.themeData().splash2())
, m_line2Clear(m_line2) {
m_windowBgClear[3] = 0.0;
m_line2Clear[3] = 0.0;
res.m_factory->commitTransaction([&](boo::IGraphicsDataFactory::Context& ctx)
{
buildResources(ctx, res);
m_viewBlockBuf = res.m_viewRes.m_bufPool.allocateBlock(res.m_factory);
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;
res.m_factory->commitTransaction([&](boo::IGraphicsDataFactory::Context& ctx) {
buildResources(ctx, res);
m_viewBlockBuf = res.m_viewRes.m_bufPool.allocateBlock(res.m_factory);
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();
}
void ModalWindow::close(bool skipAnimation)
{
m_phase = skipAnimation ? Phase::Done : Phase::BuildOut;
m_frame = 0;
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::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub)
{
float pf = rootView().viewRes().pixelFactor();
void ModalWindow::think() {
specter::ViewResources& res = rootView().viewRes();
float pf = res.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);
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();
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);
++m_frame;
break;
}
default:
break;
}
}
void ModalWindow::draw(boo::IGraphicsCommandQueue* gfxQ)
{
if (m_phase == Phase::Done)
return;
bool ModalWindow::skipBuildInAnimation() {
if (m_phase != Phase::BuildIn)
return false;
gfxQ->setShaderDataBinding(m_vertsBinding);
gfxQ->draw(0, 22);
gfxQ->draw(22, 16);
specter::ViewResources& res = rootView().viewRes();
float pf = res.pixelFactor();
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);
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;
}
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/ViewResources.hpp"
namespace specter
{
namespace specter {
static logvisor::Module Log("specter::MultiLineTextView");
std::string MultiLineTextView::LineWrap(std::string_view str, int wrap)
{
size_t rem = str.size();
const utf8proc_uint8_t* it = reinterpret_cast<const utf8proc_uint8_t*>(str.data());
uint32_t lCh = -1;
int adv = 0;
std::string MultiLineTextView::LineWrap(std::string_view str, int wrap) {
size_t rem = str.size();
const utf8proc_uint8_t* it = reinterpret_cast<const utf8proc_uint8_t*>(str.data());
uint32_t lCh = -1;
int adv = 0;
std::string ret;
ret.reserve(str.size());
size_t lastSpaceRem;
const utf8proc_uint8_t* lastSpaceIt = nullptr;
size_t rollbackPos;
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')
{
ret += '\n';
lCh = -1;
rem -= sz;
it += sz;
lastSpaceIt = nullptr;
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;
std::string ret;
ret.reserve(str.size());
size_t lastSpaceRem;
const utf8proc_uint8_t* lastSpaceIt = nullptr;
size_t rollbackPos;
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') {
ret += '\n';
lCh = -1;
rem -= sz;
it += sz;
lastSpaceIt = nullptr;
adv = 0;
continue;
}
return ret;
}
std::wstring MultiLineTextView::LineWrap(std::wstring_view str, int wrap)
{
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;
const FontAtlas::Glyph* glyph = m_fontAtlas.lookupGlyph(ch);
if (!glyph) {
rem -= sz;
it += sz;
continue;
}
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,
View& parentView,
const FontAtlas& font,
TextView::Alignment align,
size_t lineCapacity,
float lineHeight)
: View(res, parentView),
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;
});
}
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;
if (adv > wrap && lastSpaceIt) {
ret.assign(ret.cbegin(), ret.cbegin() + rollbackPos);
ret += '\n';
lCh = -1;
rem = lastSpaceRem;
it = lastSpaceIt;
lastSpaceIt = nullptr;
adv = 0;
continue;
}
m_width = 0;
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;
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;
}
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();
return ret;
}
void MultiLineTextView::typesetGlyphs(std::wstring_view str,
const zeus::CColor& defaultColor,
unsigned wrap)
{
if (wrap)
{
typesetGlyphs(LineWrap(str, wrap), defaultColor);
return;
std::wstring MultiLineTextView::LineWrap(std::wstring_view str, int wrap) {
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;
}
m_width = 0;
size_t rem = str.size() + 1;
auto it = str.cbegin();
const FontAtlas::Glyph* glyph = m_fontAtlas.lookupGlyph(ch);
if (!glyph)
continue;
size_t lineCount = 0;
while (rem)
{
if (*it == L'\n' || *it == L'\0')
++lineCount;
--rem;
++it;
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;
}
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;
if (ch == L' ' || ch == L'-') {
lastSpaceIt = it + 1;
rollbackPos = ret.size() + 1;
}
ret += ch;
lCh = glyph->m_glyphIdx;
}
updateSize();
return ret;
}
void MultiLineTextView::colorGlyphs(const zeus::CColor& newColor)
{
for (std::unique_ptr<TextView>& tv : m_lines)
tv->colorGlyphs(newColor);
MultiLineTextView::MultiLineTextView(ViewResources& res, View& parentView, const FontAtlas& font,
TextView::Alignment align, size_t lineCapacity, float lineHeight)
: View(res, parentView)
, 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)
{
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);
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;
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)
{
View::draw(gfxQ);
for (std::unique_ptr<TextView>& tv : m_lines)
tv->draw(gfxQ);
void MultiLineTextView::typesetGlyphs(std::wstring_view str, const zeus::CColor& defaultColor, unsigned wrap) {
if (wrap) {
typesetGlyphs(LineWrap(str, wrap), defaultColor);
return;
}
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/ViewResources.hpp"
namespace specter
{
namespace specter {
PathButtons::PathButtons(ViewResources& res, View& parentView, IPathButtonsBinding& binding, bool fillContainer)
: ScrollView(res, parentView, ScrollView::Style::SideButtons), m_binding(binding), m_fillContainer(fillContainer)
{
m_contentView.m_view.reset(new ContentView(res, *this));
setContentView(m_contentView.m_view.get());
: ScrollView(res, parentView, ScrollView::Style::SideButtons), m_binding(binding), m_fillContainer(fillContainer) {
m_contentView.m_view.reset(new ContentView(res, *this));
setContentView(m_contentView.m_view.get());
}
void PathButtons::setButtons(const std::vector<hecl::SystemString>& comps)
{
m_pathButtons.clear();
m_pathButtons.reserve(comps.size());
size_t idx = 0;
ViewResources& res = rootView().viewRes();
for (const hecl::SystemString& c : comps)
m_pathButtons.emplace_back(*this, res, idx++, c);
void PathButtons::setButtons(const std::vector<hecl::SystemString>& comps) {
m_pathButtons.clear();
m_pathButtons.reserve(comps.size());
size_t idx = 0;
ViewResources& res = rootView().viewRes();
for (const hecl::SystemString& c : comps)
m_pathButtons.emplace_back(*this, res, idx++, c);
}
void PathButtons::setMultiplyColor(const zeus::CColor& color)
{
ScrollView::setMultiplyColor(color);
for (PathButton& b : m_pathButtons)
b.m_button.m_view->setMultiplyColor(color);
void PathButtons::setMultiplyColor(const zeus::CColor& color) {
ScrollView::setMultiplyColor(color);
for (PathButton& b : m_pathButtons)
b.m_button.m_view->setMultiplyColor(color);
}
void PathButtons::ContentView::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod)
{
for (PathButton& b : m_pb.m_pathButtons)
b.m_button.mouseDown(coord, button, mod);
void PathButtons::ContentView::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button,
boo::EModifierKey mod) {
for (PathButton& b : m_pb.m_pathButtons)
b.m_button.mouseDown(coord, button, mod);
}
void PathButtons::ContentView::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod)
{
for (PathButton& b : m_pb.m_pathButtons)
b.m_button.mouseUp(coord, button, mod);
if (m_pb.m_pathButtonPending >= 0)
{
m_pb.m_binding.pathButtonActivated(m_pb.m_pathButtonPending);
m_pb.m_pathButtonPending = -1;
}
void PathButtons::ContentView::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button,
boo::EModifierKey mod) {
for (PathButton& b : m_pb.m_pathButtons)
b.m_button.mouseUp(coord, button, mod);
if (m_pb.m_pathButtonPending >= 0) {
m_pb.m_binding.pathButtonActivated(m_pb.m_pathButtonPending);
m_pb.m_pathButtonPending = -1;
}
}
void PathButtons::ContentView::mouseMove(const boo::SWindowCoord& coord)
{
for (PathButton& b : m_pb.m_pathButtons)
b.m_button.mouseMove(coord);
void PathButtons::ContentView::mouseMove(const boo::SWindowCoord& coord) {
for (PathButton& b : m_pb.m_pathButtons)
b.m_button.mouseMove(coord);
}
void PathButtons::ContentView::mouseLeave(const boo::SWindowCoord& coord)
{
for (PathButton& b : m_pb.m_pathButtons)
b.m_button.mouseLeave(coord);
void PathButtons::ContentView::mouseLeave(const boo::SWindowCoord& coord) {
for (PathButton& b : m_pb.m_pathButtons)
b.m_button.mouseLeave(coord);
}
void PathButtons::ContentView::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub,
const boo::SWindowRect& scissor)
{
View::resized(root, sub);
m_scissorRect = scissor;
m_scissorRect.size[1] += 2;
boo::SWindowRect pathRect = sub;
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();
b.m_button.m_view->resized(root, pathRect);
pathRect.location[0] += pathRect.size[0] + 2;
}
const boo::SWindowRect& scissor) {
View::resized(root, sub);
m_scissorRect = scissor;
m_scissorRect.size[1] += 2;
boo::SWindowRect pathRect = sub;
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();
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)
{
if (m_fillContainer)
{
boo::SWindowRect fillRect = sub;
fillRect.size[1] = 20 * rootView().viewRes().pixelFactor();
View::resized(root, fillRect);
}
void PathButtons::containerResized(const boo::SWindowRect& root, const boo::SWindowRect& sub) {
if (m_fillContainer) {
boo::SWindowRect fillRect = sub;
fillRect.size[1] = 20 * rootView().viewRes().pixelFactor();
View::resized(root, fillRect);
}
}
void PathButtons::ContentView::draw(boo::IGraphicsCommandQueue* gfxQ)
{
gfxQ->setScissor(m_scissorRect);
for (PathButton& b : m_pb.m_pathButtons)
b.m_button.m_view->draw(gfxQ);
gfxQ->setScissor(rootView().subRect());
void PathButtons::ContentView::draw(boo::IGraphicsCommandQueue* gfxQ) {
gfxQ->setScissor(m_scissorRect);
for (PathButton& b : m_pb.m_pathButtons)
b.m_button.m_view->draw(gfxQ);
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/Button.hpp"
namespace specter
{
namespace specter {
#define MAX_SCROLL_SPEED 100
ScrollView::ScrollView(ViewResources& res, View& parentView, Style style)
: View(res, parentView), m_style(style), m_sideButtonBind(*this, rootView().viewManager())
{
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool
{
buildResources(ctx, res);
m_vertsBinding.init(ctx, res, 4, m_viewVertBlockBuf);
return true;
});
: View(res, parentView), m_style(style), m_sideButtonBind(*this, rootView().viewManager()) {
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool {
buildResources(ctx, res);
m_vertsBinding.init(ctx, res, 4, m_viewVertBlockBuf);
return true;
});
if (style == Style::SideButtons)
{
m_sideButtons[0].m_view.reset(new Button(res, *this, &m_sideButtonBind, "<"));
m_sideButtons[1].m_view.reset(new Button(res, *this, &m_sideButtonBind, ">"));
}
if (style == Style::SideButtons) {
m_sideButtons[0].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)
{
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());
bool ScrollView::_scroll(const boo::SScrollDelta& scroll) {
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 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();
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)));
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;
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);
}
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 (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 (update)
updateSize();
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;
}
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);
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);
}
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);
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);
}
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);
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);
}
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::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::draw(boo::IGraphicsCommandQueue* gfxQ)
{
if (m_contentView.m_view)
{
m_contentView.m_view->draw(gfxQ);
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);
}
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);
}
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();
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/RootView.hpp"
namespace specter
{
namespace specter {
static logvisor::Module Log("specter::Space");
#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};
Space::Space(ViewResources& res, View& parentView, ISpaceController& controller,
Toolbar::Position tbPos, unsigned tbUnits)
: View(res, parentView), m_controller(controller), m_tbPos(tbPos)
{
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool
{
buildResources(ctx, res);
return true;
});
setBackground(res.themeData().spaceBackground());
if (controller.spaceSplitAllowed())
m_cornerView.m_view.reset(new CornerView(res, *this, TriColor));
if (tbPos != Toolbar::Position::None)
m_toolbar.m_view.reset(new Toolbar(res, *this, tbPos, tbUnits));
Space::Space(ViewResources& res, View& parentView, ISpaceController& controller, Toolbar::Position tbPos,
unsigned tbUnits)
: View(res, parentView), m_controller(controller), m_tbPos(tbPos) {
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool {
buildResources(ctx, res);
return true;
});
setBackground(res.themeData().spaceBackground());
if (controller.spaceSplitAllowed())
m_cornerView.m_view.reset(new CornerView(res, *this, TriColor));
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)
: View(res, space), m_space(space)
{
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool
{
buildResources(ctx, res);
m_vertexBinding.init(ctx, res, 34, m_viewVertBlockBuf);
return true;
});
float pf = res.pixelFactor();
: View(res, space), m_space(space) {
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool {
buildResources(ctx, res);
m_vertexBinding.init(ctx, res, 34, m_viewVertBlockBuf);
return true;
});
float pf = res.pixelFactor();
zeus::CColor edgeColor1 = triColor * res.themeData().spaceTriangleShading1();
zeus::CColor edgeColor2 = triColor * res.themeData().spaceTriangleShading2();
View::SolidShaderVert verts[34];
zeus::CColor edgeColor1 = triColor * res.themeData().spaceTriangleShading1();
zeus::CColor edgeColor2 = triColor * res.themeData().spaceTriangleShading2();
View::SolidShaderVert verts[34];
verts[0].m_pos.assign(0, TRIANGLE_DIM * pf, 0);
verts[0].m_color = edgeColor1;
verts[1].m_pos.assign(TRIANGLE_DIM * pf, 0, 0);
verts[1].m_color = edgeColor1;
verts[2].m_pos.assign(0, (TRIANGLE_DIM + 1) * pf, 0);
verts[2].m_color = edgeColor1;
verts[3].m_pos.assign((TRIANGLE_DIM + 1) * pf, 0, 0);
verts[3].m_color = edgeColor1;
verts[4] = verts[3];
verts[0].m_pos.assign(0, TRIANGLE_DIM * pf, 0);
verts[0].m_color = edgeColor1;
verts[1].m_pos.assign(TRIANGLE_DIM * pf, 0, 0);
verts[1].m_color = edgeColor1;
verts[2].m_pos.assign(0, (TRIANGLE_DIM + 1) * pf, 0);
verts[2].m_color = edgeColor1;
verts[3].m_pos.assign((TRIANGLE_DIM + 1) * pf, 0, 0);
verts[3].m_color = edgeColor1;
verts[4] = verts[3];
verts[5].m_pos.assign(0, TRIANGLE_DIM1 * pf, 0);
verts[5].m_color = edgeColor2;
verts[6] = verts[5];
verts[7].m_pos.assign(TRIANGLE_DIM1 * pf, 0, 0);
verts[7].m_color = edgeColor2;
verts[8].m_pos.assign(0, (TRIANGLE_DIM1 + 1) * pf, 0);
verts[8].m_color = edgeColor2;
verts[9].m_pos.assign((TRIANGLE_DIM1 + 1) * pf, 0, 0);
verts[9].m_color = edgeColor2;
verts[10] = verts[9];
verts[5].m_pos.assign(0, TRIANGLE_DIM1 * pf, 0);
verts[5].m_color = edgeColor2;
verts[6] = verts[5];
verts[7].m_pos.assign(TRIANGLE_DIM1 * pf, 0, 0);
verts[7].m_color = edgeColor2;
verts[8].m_pos.assign(0, (TRIANGLE_DIM1 + 1) * pf, 0);
verts[8].m_color = edgeColor2;
verts[9].m_pos.assign((TRIANGLE_DIM1 + 1) * pf, 0, 0);
verts[9].m_color = edgeColor2;
verts[10] = verts[9];
verts[11].m_pos.assign(0, TRIANGLE_DIM2 * pf, 0);
verts[11].m_color = edgeColor2;
verts[12] = verts[11];
verts[13].m_pos.assign(TRIANGLE_DIM2 * pf, 0, 0);
verts[13].m_color = edgeColor2;
verts[14].m_pos.assign(0, (TRIANGLE_DIM2 + 1) * pf, 0);
verts[14].m_color = edgeColor2;
verts[15].m_pos.assign((TRIANGLE_DIM2 + 1) * pf, 0, 0);
verts[15].m_color = edgeColor2;
verts[16] = verts[15];
verts[11].m_pos.assign(0, TRIANGLE_DIM2 * pf, 0);
verts[11].m_color = edgeColor2;
verts[12] = verts[11];
verts[13].m_pos.assign(TRIANGLE_DIM2 * pf, 0, 0);
verts[13].m_color = edgeColor2;
verts[14].m_pos.assign(0, (TRIANGLE_DIM2 + 1) * pf, 0);
verts[14].m_color = edgeColor2;
verts[15].m_pos.assign((TRIANGLE_DIM2 + 1) * pf, 0, 0);
verts[15].m_color = edgeColor2;
verts[16] = verts[15];
verts[17].m_pos.assign(0, TRIANGLE_DIM3 * pf, 0);
verts[17].m_color = edgeColor2;
verts[18] = verts[17];
verts[19].m_pos.assign(TRIANGLE_DIM3 * pf, 0, 0);
verts[19].m_color = edgeColor2;
verts[20].m_pos.assign(0, (TRIANGLE_DIM3 + 1) * pf, 0);
verts[20].m_color = edgeColor2;
verts[21].m_pos.assign((TRIANGLE_DIM3 + 1) * pf, 0, 0);
verts[21].m_color = edgeColor2;
verts[22] = verts[21];
verts[17].m_pos.assign(0, TRIANGLE_DIM3 * pf, 0);
verts[17].m_color = edgeColor2;
verts[18] = verts[17];
verts[19].m_pos.assign(TRIANGLE_DIM3 * pf, 0, 0);
verts[19].m_color = edgeColor2;
verts[20].m_pos.assign(0, (TRIANGLE_DIM3 + 1) * pf, 0);
verts[20].m_color = edgeColor2;
verts[21].m_pos.assign((TRIANGLE_DIM3 + 1) * pf, 0, 0);
verts[21].m_color = edgeColor2;
verts[22] = verts[21];
verts[23].m_pos.assign(0, TRIANGLE_DIM4 * pf, 0);
verts[23].m_color = edgeColor2;
verts[24] = verts[23];
verts[25].m_pos.assign(TRIANGLE_DIM4 * pf, 0, 0);
verts[25].m_color = edgeColor2;
verts[26].m_pos.assign(0, (TRIANGLE_DIM4 + 1) * pf, 0);
verts[26].m_color = edgeColor2;
verts[27].m_pos.assign((TRIANGLE_DIM4 + 1) * pf, 0, 0);
verts[27].m_color = edgeColor2;
verts[28] = verts[27];
verts[23].m_pos.assign(0, TRIANGLE_DIM4 * pf, 0);
verts[23].m_color = edgeColor2;
verts[24] = verts[23];
verts[25].m_pos.assign(TRIANGLE_DIM4 * pf, 0, 0);
verts[25].m_color = edgeColor2;
verts[26].m_pos.assign(0, (TRIANGLE_DIM4 + 1) * pf, 0);
verts[26].m_color = edgeColor2;
verts[27].m_pos.assign((TRIANGLE_DIM4 + 1) * pf, 0, 0);
verts[27].m_color = edgeColor2;
verts[28] = verts[27];
verts[29].m_pos.assign(0, TRIANGLE_DIM5 * pf, 0);
verts[29].m_color = edgeColor2;
verts[30] = verts[29];
verts[31].m_pos.assign(TRIANGLE_DIM5 * pf, 0, 0);
verts[31].m_color = edgeColor2;
verts[32].m_pos.assign(0, (TRIANGLE_DIM5 + 1) * pf, 0);
verts[32].m_color = edgeColor2;
verts[33].m_pos.assign((TRIANGLE_DIM5 + 1) * pf, 0, 0);
verts[33].m_color = edgeColor2;
verts[29].m_pos.assign(0, TRIANGLE_DIM5 * pf, 0);
verts[29].m_color = edgeColor2;
verts[30] = verts[29];
verts[31].m_pos.assign(TRIANGLE_DIM5 * pf, 0, 0);
verts[31].m_color = edgeColor2;
verts[32].m_pos.assign(0, (TRIANGLE_DIM5 + 1) * pf, 0);
verts[32].m_color = edgeColor2;
verts[33].m_pos.assign((TRIANGLE_DIM5 + 1) * pf, 0, 0);
verts[33].m_color = edgeColor2;
m_vertexBinding.load<decltype(verts)>(verts);
m_vertexBinding.load<decltype(verts)>(verts);
}
View* Space::setContentView(View* view)
{
View* ret = m_contentView.m_view;
m_contentView.m_view = view;
updateSize();
return ret;
View* Space::setContentView(View* view) {
View* ret = m_contentView.m_view;
m_contentView.m_view = view;
updateSize();
return ret;
}
void Space::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod)
{
if (m_cornerView.mouseDown(coord, button, mod))
return;
m_contentView.mouseDown(coord, button, mod);
m_toolbar.mouseDown(coord, button, mod);
void Space::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
if (m_cornerView.mouseDown(coord, button, mod))
return;
m_contentView.mouseDown(coord, button, mod);
m_toolbar.mouseDown(coord, button, mod);
}
void Space::CornerView::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod)
{
if (button == boo::EMouseButton::Primary)
{
m_space.m_cornerDrag = true;
m_space.m_cornerDragPoint[0] = coord.pixel[0];
m_space.m_cornerDragPoint[1] = coord.pixel[1];
rootView().setActiveDragView(&m_space);
}
void Space::CornerView::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
if (button == boo::EMouseButton::Primary) {
m_space.m_cornerDrag = true;
m_space.m_cornerDragPoint[0] = coord.pixel[0];
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)
{
m_cornerView.mouseUp(coord, button, mod);
m_contentView.mouseUp(coord, button, mod);
m_toolbar.mouseUp(coord, button, mod);
void Space::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
m_cornerView.mouseUp(coord, button, mod);
m_contentView.mouseUp(coord, button, mod);
m_toolbar.mouseUp(coord, button, mod);
}
void Space::CornerView::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod)
{
if (button == boo::EMouseButton::Primary)
{
m_space.m_cornerDrag = false;
rootView().unsetActiveDragView(&m_space);
}
void Space::CornerView::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
if (button == boo::EMouseButton::Primary) {
m_space.m_cornerDrag = false;
rootView().unsetActiveDragView(&m_space);
}
}
void Space::mouseMove(const boo::SWindowCoord& coord)
{
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);
void Space::mouseMove(const boo::SWindowCoord& coord) {
if (m_cornerDrag) {
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);
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
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);
}
} 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::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::mouseEnter(const boo::SWindowCoord& coord) {
m_cornerView.mouseEnter(coord);
m_contentView.mouseEnter(coord);
m_toolbar.mouseEnter(coord);
}
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::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::draw(boo::IGraphicsCommandQueue* gfxQ)
{
gfxQ->setShaderDataBinding(m_vertexBinding);
gfxQ->draw(0, 34);
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();
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/Space.hpp"
namespace specter
{
namespace specter {
static logvisor::Module Log("specter::SplitView");
static const zeus::RGBA32 Tex[3] =
{
{{0,0,0,64}},
{{0,0,0,255}},
{{255,255,255,64}}
};
static const zeus::RGBA32 Tex[3] = {{{0, 0, 0, 64}}, {{0, 0, 0, 255}}, {{255, 255, 255, 64}}};
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);
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);
}
SplitView::SplitView(ViewResources& res, View& parentView, ISplitSpaceController* controller,
Axis axis, float split, int clearanceA, int clearanceB)
: View(res, parentView), m_controller(controller), m_axis(axis), m_slide(split),
m_clearanceA(clearanceA), m_clearanceB(clearanceB)
{
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool
{
buildResources(ctx, res);
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;
});
SplitView::SplitView(ViewResources& res, View& parentView, ISplitSpaceController* controller, Axis axis, float split,
int clearanceA, int clearanceB)
: View(res, parentView)
, m_controller(controller)
, m_axis(axis)
, m_slide(split)
, m_clearanceA(clearanceA)
, m_clearanceB(clearanceB) {
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool {
buildResources(ctx, res);
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)
{
if (slot < 0 || slot > 1)
Log.report(logvisor::Fatal, "out-of-range slot to RootView::SplitView::setContentView");
View* ret = m_views[slot].m_view;
m_views[slot].m_view = view;
m_views[slot].m_mouseDown = 0;
m_views[slot].m_mouseIn = false;
updateSize();
return ret;
View* SplitView::setContentView(int slot, View* view) {
if (slot < 0 || slot > 1)
Log.report(logvisor::Fatal, "out-of-range slot to RootView::SplitView::setContentView");
View* ret = m_views[slot].m_view;
m_views[slot].m_view = view;
m_views[slot].m_mouseDown = 0;
m_views[slot].m_mouseIn = false;
updateSize();
return ret;
}
void SplitView::_setSplit(float slide)
{
m_slide = std::min(std::max(slide, 0.0f), 1.0f);
const boo::SWindowRect& rect = subRect();
if (rect.size[0] && rect.size[1] &&
(m_clearanceA >= 0 || m_clearanceB >= 0))
{
if (m_axis == Axis::Horizontal)
{
int slidePx = rect.size[1] * m_slide;
if (m_clearanceA >= 0 && slidePx < m_clearanceA)
m_slide = m_clearanceA / float(rect.size[1]);
if (m_clearanceB >= 0 && (rect.size[1] - slidePx) < m_clearanceB)
m_slide = 1.0 - m_clearanceB / float(rect.size[1]);
}
else if (m_axis == Axis::Vertical)
{
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);
void SplitView::_setSplit(float slide) {
m_slide = std::min(std::max(slide, 0.0f), 1.0f);
const boo::SWindowRect& rect = subRect();
if (rect.size[0] && rect.size[1] && (m_clearanceA >= 0 || m_clearanceB >= 0)) {
if (m_axis == Axis::Horizontal) {
int slidePx = rect.size[1] * m_slide;
if (m_clearanceA >= 0 && slidePx < m_clearanceA)
m_slide = m_clearanceA / float(rect.size[1]);
if (m_clearanceB >= 0 && (rect.size[1] - slidePx) < m_clearanceB)
m_slide = 1.0 - m_clearanceB / float(rect.size[1]);
} else if (m_axis == Axis::Vertical) {
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]);
}
if (m_controller)
m_controller->updateSplit(m_slide);
m_slide = std::min(std::max(m_slide, 0.0f), 1.0f);
}
if (m_controller)
m_controller->updateSplit(m_slide);
}
void SplitView::setSplit(float slide)
{
_setSplit(slide);
updateSize();
void SplitView::setSplit(float slide) {
_setSplit(slide);
updateSize();
}
void SplitView::setAxis(Axis axis)
{
m_axis = axis;
setSplit(m_slide);
void SplitView::setAxis(Axis axis) {
m_axis = axis;
setSplit(m_slide);
}
bool SplitView::testSplitHover(const boo::SWindowCoord& coord)
{
if (m_axis == Axis::Horizontal)
{
int slidePx = subRect().size[1] * m_slide;
if (abs(int(coord.pixel[1] - subRect().location[1]) - slidePx) < 4)
return true;
}
else if (m_axis == Axis::Vertical)
{
int slidePx = subRect().size[0] * m_slide;
if (abs(int(coord.pixel[0] - subRect().location[0]) - slidePx) < 4)
return true;
}
bool SplitView::testSplitHover(const boo::SWindowCoord& coord) {
if (m_axis == Axis::Horizontal) {
int slidePx = subRect().size[1] * m_slide;
if (abs(int(coord.pixel[1] - subRect().location[1]) - slidePx) < 4)
return true;
} else if (m_axis == Axis::Vertical) {
int slidePx = subRect().size[0] * m_slide;
if (abs(int(coord.pixel[0] - subRect().location[0]) - slidePx) < 4)
return true;
}
return false;
}
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;
}
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;
int origDummy;
ArrowDir dirDummy;
int origDummy;
ArrowDir dirDummy;
if (m_axis == Axis::Horizontal)
{
int slidePx = subRect().size[1] * m_slide;
if ((forceSlot == -1 && coord.pixel[1] - subRect().location[1] - slidePx >= 0) || forceSlot == 1)
{
origSlotOut = 0;
dirOut = ArrowDir::Up;
if (m_views[1].m_view)
{
SplitView* chSplit = m_views[1].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Horizontal)
return chSplit->testJoinArrowHover(coord, origDummy, splitOut, slotOut, rectOut, dirDummy, 0);
}
splitOut = this;
slotOut = 1;
rectOut = subRect();
rectOut.location[1] += slidePx;
rectOut.size[1] -= slidePx;
return true;
}
else
{
origSlotOut = 1;
dirOut = ArrowDir::Down;
if (m_views[0].m_view)
{
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;
}
if (m_axis == Axis::Horizontal) {
int slidePx = subRect().size[1] * m_slide;
if ((forceSlot == -1 && coord.pixel[1] - subRect().location[1] - slidePx >= 0) || forceSlot == 1) {
origSlotOut = 0;
dirOut = ArrowDir::Up;
if (m_views[1].m_view) {
SplitView* chSplit = m_views[1].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Horizontal)
return chSplit->testJoinArrowHover(coord, origDummy, splitOut, slotOut, rectOut, dirDummy, 0);
}
splitOut = this;
slotOut = 1;
rectOut = subRect();
rectOut.location[1] += slidePx;
rectOut.size[1] -= slidePx;
return true;
} else {
origSlotOut = 1;
dirOut = ArrowDir::Down;
if (m_views[0].m_view) {
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
{
int slidePx = subRect().size[0] * m_slide;
if ((forceSlot == -1 && coord.pixel[0] - subRect().location[0] - slidePx >= 0) || forceSlot == 1)
{
origSlotOut = 0;
dirOut = ArrowDir::Right;
if (m_views[1].m_view)
{
SplitView* chSplit = m_views[1].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Vertical)
return chSplit->testJoinArrowHover(coord, origDummy, splitOut, slotOut, rectOut, dirDummy, 0);
}
splitOut = this;
slotOut = 1;
rectOut = subRect();
rectOut.location[0] += slidePx;
rectOut.size[0] -= slidePx;
return true;
}
else
{
origSlotOut = 1;
dirOut = ArrowDir::Left;
if (m_views[0].m_view)
{
SplitView* chSplit = m_views[0].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Vertical)
return chSplit->testJoinArrowHover(coord, origDummy, splitOut, slotOut, rectOut, dirDummy, 1);
}
splitOut = this;
slotOut = 0;
rectOut = subRect();
rectOut.size[0] = slidePx;
return true;
}
} else {
int slidePx = subRect().size[0] * m_slide;
if ((forceSlot == -1 && coord.pixel[0] - subRect().location[0] - slidePx >= 0) || forceSlot == 1) {
origSlotOut = 0;
dirOut = ArrowDir::Right;
if (m_views[1].m_view) {
SplitView* chSplit = m_views[1].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Vertical)
return chSplit->testJoinArrowHover(coord, origDummy, splitOut, slotOut, rectOut, dirDummy, 0);
}
splitOut = this;
slotOut = 1;
rectOut = subRect();
rectOut.location[0] += slidePx;
rectOut.size[0] -= slidePx;
return true;
} else {
origSlotOut = 1;
dirOut = ArrowDir::Left;
if (m_views[0].m_view) {
SplitView* chSplit = m_views[0].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Vertical)
return chSplit->testJoinArrowHover(coord, origDummy, splitOut, slotOut, rectOut, dirDummy, 1);
}
splitOut = this;
slotOut = 0;
rectOut = subRect();
rectOut.size[0] = slidePx;
return true;
}
}
}
void SplitView::getJoinArrowHover(int slot, boo::SWindowRect& rectOut, ArrowDir& dirOut)
{
if (m_axis == Axis::Horizontal)
{
int slidePx = subRect().size[1] * m_slide;
if (slot == 1)
{
if (m_views[1].m_view)
{
SplitView* chSplit = m_views[1].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Horizontal)
return chSplit->getJoinArrowHover(0, rectOut, dirOut);
}
rectOut = subRect();
rectOut.location[1] += slidePx;
rectOut.size[1] -= slidePx;
dirOut = ArrowDir::Up;
}
else
{
if (m_views[0].m_view)
{
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;
}
void SplitView::getJoinArrowHover(int slot, boo::SWindowRect& rectOut, ArrowDir& dirOut) {
if (m_axis == Axis::Horizontal) {
int slidePx = subRect().size[1] * m_slide;
if (slot == 1) {
if (m_views[1].m_view) {
SplitView* chSplit = m_views[1].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Horizontal)
return chSplit->getJoinArrowHover(0, rectOut, dirOut);
}
rectOut = subRect();
rectOut.location[1] += slidePx;
rectOut.size[1] -= slidePx;
dirOut = ArrowDir::Up;
} else {
if (m_views[0].m_view) {
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
{
int slidePx = subRect().size[0] * m_slide;
if (slot == 1)
{
if (m_views[1].m_view)
{
SplitView* chSplit = m_views[1].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Vertical)
return chSplit->getJoinArrowHover(0, rectOut, dirOut);
}
rectOut = subRect();
rectOut.location[0] += slidePx;
rectOut.size[0] -= slidePx;
dirOut = ArrowDir::Right;
}
else
{
if (m_views[0].m_view)
{
SplitView* chSplit = m_views[0].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Vertical)
return chSplit->getJoinArrowHover(1, rectOut, dirOut);
}
rectOut = subRect();
rectOut.size[0] = slidePx;
dirOut = ArrowDir::Left;
}
} else {
int slidePx = subRect().size[0] * m_slide;
if (slot == 1) {
if (m_views[1].m_view) {
SplitView* chSplit = m_views[1].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Vertical)
return chSplit->getJoinArrowHover(0, rectOut, dirOut);
}
rectOut = subRect();
rectOut.location[0] += slidePx;
rectOut.size[0] -= slidePx;
dirOut = ArrowDir::Right;
} else {
if (m_views[0].m_view) {
SplitView* chSplit = m_views[0].m_view->castToSplitView();
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,
boo::SWindowRect& rectOut, float& splitOut, Axis& axisOut)
{
if (!subRect().coordInRect(coord))
return false;
bool SplitView::testSplitLineHover(const boo::SWindowCoord& coord, int& slotOut, boo::SWindowRect& rectOut,
float& splitOut, Axis& axisOut) {
if (!subRect().coordInRect(coord))
return false;
if (m_axis == Axis::Horizontal)
{
int slidePx = subRect().size[1] * m_slide;
if (coord.pixel[1] - subRect().location[1] - slidePx >= 0)
{
if (m_views[1].m_view)
{
SplitView* chSplit = m_views[1].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Horizontal)
return chSplit->testSplitLineHover(coord, slotOut, rectOut, splitOut, axisOut);
}
slotOut = 1;
rectOut = subRect();
rectOut.location[1] += slidePx;
rectOut.size[1] -= slidePx;
splitOut = (coord.pixel[0] - rectOut.location[0]) / float(rectOut.size[0]);
axisOut = Axis::Vertical;
return true;
}
else
{
if (m_views[0].m_view)
{
SplitView* chSplit = m_views[0].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Horizontal)
return chSplit->testSplitLineHover(coord, slotOut, rectOut, splitOut, axisOut);
}
slotOut = 0;
rectOut = subRect();
rectOut.size[1] = slidePx;
splitOut = (coord.pixel[0] - rectOut.location[0]) / float(rectOut.size[0]);
axisOut = Axis::Vertical;
return true;
}
if (m_axis == Axis::Horizontal) {
int slidePx = subRect().size[1] * m_slide;
if (coord.pixel[1] - subRect().location[1] - slidePx >= 0) {
if (m_views[1].m_view) {
SplitView* chSplit = m_views[1].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Horizontal)
return chSplit->testSplitLineHover(coord, slotOut, rectOut, splitOut, axisOut);
}
slotOut = 1;
rectOut = subRect();
rectOut.location[1] += slidePx;
rectOut.size[1] -= slidePx;
splitOut = (coord.pixel[0] - rectOut.location[0]) / float(rectOut.size[0]);
axisOut = Axis::Vertical;
return true;
} else {
if (m_views[0].m_view) {
SplitView* chSplit = m_views[0].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Horizontal)
return chSplit->testSplitLineHover(coord, slotOut, rectOut, splitOut, axisOut);
}
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
{
int slidePx = subRect().size[0] * m_slide;
if (coord.pixel[0] - subRect().location[0] - slidePx >= 0)
{
if (m_views[1].m_view)
{
SplitView* chSplit = m_views[1].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Vertical)
return chSplit->testSplitLineHover(coord, slotOut, rectOut, splitOut, axisOut);
}
slotOut = 1;
rectOut = subRect();
rectOut.location[0] += slidePx;
rectOut.size[0] -= slidePx;
splitOut = (coord.pixel[1] - rectOut.location[1]) / float(rectOut.size[1]);
axisOut = Axis::Horizontal;
return true;
}
else
{
if (m_views[0].m_view)
{
SplitView* chSplit = m_views[0].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Vertical)
return chSplit->testSplitLineHover(coord, slotOut, rectOut, splitOut, axisOut);
}
slotOut = 0;
rectOut = subRect();
rectOut.size[0] = slidePx;
splitOut = (coord.pixel[1] - rectOut.location[1]) / float(rectOut.size[1]);
axisOut = Axis::Horizontal;
return true;
}
} else {
int slidePx = subRect().size[0] * m_slide;
if (coord.pixel[0] - subRect().location[0] - slidePx >= 0) {
if (m_views[1].m_view) {
SplitView* chSplit = m_views[1].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Vertical)
return chSplit->testSplitLineHover(coord, slotOut, rectOut, splitOut, axisOut);
}
slotOut = 1;
rectOut = subRect();
rectOut.location[0] += slidePx;
rectOut.size[0] -= slidePx;
splitOut = (coord.pixel[1] - rectOut.location[1]) / float(rectOut.size[1]);
axisOut = Axis::Horizontal;
return true;
} else {
if (m_views[0].m_view) {
SplitView* chSplit = m_views[0].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Vertical)
return chSplit->testSplitLineHover(coord, slotOut, rectOut, splitOut, axisOut);
}
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)
{
if (m_axis == Axis::Horizontal)
{
int slidePx = subRect().size[1] * m_slide;
if (slot == 1)
{
if (m_views[1].m_view)
{
SplitView* chSplit = m_views[1].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Horizontal)
return chSplit->getSplitLineHover(0, rectOut, axisOut);
}
rectOut = subRect();
rectOut.location[1] += slidePx;
rectOut.size[1] -= slidePx;
axisOut = Axis::Vertical;
}
else
{
if (m_views[0].m_view)
{
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;
}
void SplitView::getSplitLineHover(int slot, boo::SWindowRect& rectOut, Axis& axisOut) {
if (m_axis == Axis::Horizontal) {
int slidePx = subRect().size[1] * m_slide;
if (slot == 1) {
if (m_views[1].m_view) {
SplitView* chSplit = m_views[1].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Horizontal)
return chSplit->getSplitLineHover(0, rectOut, axisOut);
}
rectOut = subRect();
rectOut.location[1] += slidePx;
rectOut.size[1] -= slidePx;
axisOut = Axis::Vertical;
} else {
if (m_views[0].m_view) {
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
{
int slidePx = subRect().size[0] * m_slide;
if (slot == 1)
{
if (m_views[1].m_view)
{
SplitView* chSplit = m_views[1].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Vertical)
return chSplit->getSplitLineHover(0, rectOut, axisOut);
}
rectOut = subRect();
rectOut.location[0] += slidePx;
rectOut.size[0] -= slidePx;
axisOut = Axis::Horizontal;
}
else
{
if (m_views[0].m_view)
{
SplitView* chSplit = m_views[0].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Vertical)
return chSplit->getSplitLineHover(1, rectOut, axisOut);
}
rectOut = subRect();
rectOut.size[0] = slidePx;
axisOut = Axis::Horizontal;
}
} else {
int slidePx = subRect().size[0] * m_slide;
if (slot == 1) {
if (m_views[1].m_view) {
SplitView* chSplit = m_views[1].m_view->castToSplitView();
if (chSplit && chSplit->m_axis == Axis::Vertical)
return chSplit->getSplitLineHover(0, rectOut, axisOut);
}
rectOut = subRect();
rectOut.location[0] += slidePx;
rectOut.size[0] -= slidePx;
axisOut = Axis::Horizontal;
} else {
if (m_views[0].m_view) {
SplitView* chSplit = m_views[0].m_view->castToSplitView();
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)
{
m_dragging = true;
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::startDragSplit(const boo::SWindowCoord& coord) {
m_dragging = true;
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::endDragSplit()
{
m_dragging = false;
void SplitView::endDragSplit() { 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)
{
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::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
m_views[0].mouseDown(coord, button, mod);
m_views[1].mouseDown(coord, button, mod);
}
void SplitView::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod)
{
m_views[0].mouseDown(coord, button, mod);
m_views[1].mouseDown(coord, button, mod);
void SplitView::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
m_views[0].mouseUp(coord, button, mod);
m_views[1].mouseUp(coord, button, mod);
}
void SplitView::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod)
{
m_views[0].mouseUp(coord, button, mod);
m_views[1].mouseUp(coord, button, mod);
void SplitView::mouseMove(const boo::SWindowCoord& coord) {
m_views[0].mouseMove(coord);
m_views[1].mouseMove(coord);
}
void SplitView::mouseMove(const boo::SWindowCoord& coord)
{
m_views[0].mouseMove(coord);
m_views[1].mouseMove(coord);
void SplitView::mouseEnter(const boo::SWindowCoord& coord) {
m_views[0].mouseEnter(coord);
m_views[1].mouseEnter(coord);
}
void SplitView::mouseEnter(const boo::SWindowCoord& coord)
{
m_views[0].mouseEnter(coord);
m_views[1].mouseEnter(coord);
void SplitView::mouseLeave(const boo::SWindowCoord& coord) {
m_views[0].mouseLeave(coord);
m_views[1].mouseLeave(coord);
}
void SplitView::mouseLeave(const boo::SWindowCoord& coord)
{
m_views[0].mouseLeave(coord);
m_views[1].mouseLeave(coord);
}
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);
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->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)
m_views[1].m_view->draw(gfxQ);
gfxQ->setShaderDataBinding(m_splitVertsBinding);
gfxQ->draw(0, 4);
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)
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/ftobjs.h>
namespace specter
{
namespace specter {
static logvisor::Module Log("specter::TextView");
void TextView::Resources::init(boo::IGraphicsDataFactory::Context& ctx, FontCache* fcache)
{
m_fcache = fcache;
m_regular = hecl::conv->convert(ctx, Shader_SpecterTextViewShader{});
m_subpixel = hecl::conv->convert(ctx, Shader_SpecterTextViewShaderSubpixel{});
void TextView::Resources::init(boo::IGraphicsDataFactory::Context& ctx, FontCache* fcache) {
m_fcache = fcache;
m_regular = hecl::conv->convert(ctx, Shader_SpecterTextViewShader{});
m_subpixel = hecl::conv->convert(ctx, Shader_SpecterTextViewShaderSubpixel{});
}
void TextView::_commitResources(size_t capacity)
{
auto& res = rootView().viewRes();
auto fontTex = m_fontAtlas.texture(res.m_factory);
View::commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx)
{
buildResources(ctx, res);
void TextView::_commitResources(size_t capacity) {
auto& res = rootView().viewRes();
auto fontTex = m_fontAtlas.texture(res.m_factory);
View::commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) {
buildResources(ctx, res);
if (capacity)
{
m_glyphBuf = res.m_textRes.m_glyphPool.allocateBlock(res.m_factory, capacity);
if (capacity) {
m_glyphBuf = res.m_textRes.m_glyphPool.allocateBlock(res.m_factory, capacity);
boo::ObjToken<boo::IShaderPipeline> shader;
if (m_fontAtlas.subpixel())
shader = res.m_textRes.m_subpixel;
else
shader = res.m_textRes.m_regular;
boo::ObjToken<boo::IShaderPipeline> shader;
if (m_fontAtlas.subpixel())
shader = res.m_textRes.m_subpixel;
else
shader = res.m_textRes.m_regular;
auto vBufInfo = m_glyphBuf.getBufferInfo();
auto uBufInfo = m_viewVertBlockBuf.getBufferInfo();
boo::ObjToken<boo::IGraphicsBuffer> uBufs[] = {uBufInfo.first.get()};
size_t uBufOffs[] = {size_t(uBufInfo.second)};
size_t uBufSizes[] = {sizeof(ViewBlock)};
boo::ObjToken<boo::ITexture> texs[] = {fontTex.get()};
auto vBufInfo = m_glyphBuf.getBufferInfo();
auto uBufInfo = m_viewVertBlockBuf.getBufferInfo();
boo::ObjToken<boo::IGraphicsBuffer> uBufs[] = {uBufInfo.first.get()};
size_t uBufOffs[] = {size_t(uBufInfo.second)};
size_t uBufSizes[] = {sizeof(ViewBlock)};
boo::ObjToken<boo::ITexture> texs[] = {fontTex.get()};
m_shaderBinding = ctx.newShaderDataBinding(shader, {}, vBufInfo.first.get(), nullptr, 1,
uBufs, nullptr, uBufOffs, uBufSizes,
1, texs, nullptr, nullptr, 0, vBufInfo.second);
}
return true;
});
m_shaderBinding = ctx.newShaderDataBinding(shader, {}, vBufInfo.first.get(), nullptr, 1, uBufs, nullptr, uBufOffs,
uBufSizes, 1, texs, nullptr, nullptr, 0, vBufInfo.second);
}
return true;
});
}
TextView::TextView(ViewResources& res,
View& parentView, const FontAtlas& font,
Alignment align, size_t capacity)
: View(res, parentView),
m_capacity(capacity),
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());
TextView::TextView(ViewResources& res, View& parentView, const FontAtlas& font, Alignment align, size_t capacity)
: View(res, parentView), m_capacity(capacity), 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(res, parentView, res.m_textRes.m_fcache->lookupAtlas(font), align, capacity) {}
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[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[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[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[3].assign(glyph.m_uv[2], glyph.m_uv[3], glyph.m_layerFloat);
m_color = defaultColor;
adv += glyph.m_advance;
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[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[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[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[3].assign(glyph.m_uv[2], glyph.m_uv[3], glyph.m_layerFloat);
m_color = defaultColor;
adv += glyph.m_advance;
}
int TextView::DoKern(FT_Pos val, const FontAtlas& atlas)
{
if (!val) return 0;
val = FT_MulFix(val, atlas.FT_Xscale());
int TextView::DoKern(FT_Pos val, const FontAtlas& atlas) {
if (!val)
return 0;
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 */
/* to avoid that rounding makes them too big. */
/* `25' has been determined heuristically. */
if (atlas.FT_XPPem() < 25)
val = FT_MulDiv(orig_x, atlas.FT_XPPem(), 25);
/* we scale down kerning values for small ppem values */
/* to avoid that rounding makes them too big. */
/* `25' has been determined heuristically. */
if (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)
{
UTF8Iterator it(str.begin());
size_t charLen = str.size() ? std::min(it.countTo(str.end()), m_capacity) : 0;
if (charLen > m_curSize)
{
m_curSize = charLen;
_commitResources(charLen);
void TextView::typesetGlyphs(std::string_view str, const zeus::CColor& defaultColor) {
UTF8Iterator it(str.begin());
size_t charLen = str.size() ? std::min(it.countTo(str.end()), m_capacity) : 0;
if (charLen > m_curSize) {
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;
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;
}
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;
}
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)
{
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;
}
} 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();
m_width = adv;
invalidateGlyphs();
updateSize();
}
void TextView::typesetGlyphs(std::wstring_view str, const zeus::CColor& defaultColor)
{
size_t charLen = std::min(str.size(), m_capacity);
if (charLen > m_curSize)
{
m_curSize = charLen;
_commitResources(charLen);
void TextView::typesetGlyphs(std::wstring_view str, const zeus::CColor& defaultColor) {
size_t charLen = std::min(str.size(), m_capacity);
if (charLen > m_curSize) {
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;
}
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;
} 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;
}
}
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)
{
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();
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)
glyph.m_color = newColor;
invalidateGlyphs();
out[i++] = glyph;
}
}
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()
{
if (m_glyphBuf)
{
RenderGlyph* out = m_glyphBuf.access();
size_t i = 0;
for (RenderGlyph& glyph : m_glyphs)
out[i++] = glyph;
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;
}
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)
{
View::resized(root, sub);
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};
}
void TextView::draw(boo::IGraphicsCommandQueue* gfxQ)
{
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};
}
}
} // namespace specter

View File

@ -5,180 +5,158 @@
#define TOOLBAR_PADDING 10
namespace specter
{
namespace specter {
static logvisor::Module Log("specter::Space");
static const zeus::RGBA32 Tex[] =
{
{{255,255,255,64}},
{{255,255,255,64}},
{{0,0,0,64}},
{{0,0,0,64}}
};
static const zeus::RGBA32 Tex[] = {{{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)
{
m_shadingTex = ctx.newStaticTexture(4, 1, 1, boo::TextureFormat::RGBA8, boo::TextureClampMode::Repeat, Tex, 16);
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);
}
Toolbar::Toolbar(ViewResources& res, View& parentView, Position tbPos, unsigned units)
: View(res, parentView), m_units(units),
m_nomGauge(res.pixelFactor() * SPECTER_TOOLBAR_GAUGE * units),
m_padding(res.pixelFactor() * TOOLBAR_PADDING)
{
m_children.reserve(units);
for (unsigned u=0 ; u<units ; ++u)
m_children.emplace_back();
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool
{
buildResources(ctx, res);
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());
return true;
});
setBackground(res.themeData().toolbarBackground());
: View(res, parentView)
, m_units(units)
, m_nomGauge(res.pixelFactor() * SPECTER_TOOLBAR_GAUGE * units)
, m_padding(res.pixelFactor() * TOOLBAR_PADDING) {
m_children.reserve(units);
for (unsigned u = 0; u < units; ++u)
m_children.emplace_back();
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool {
buildResources(ctx, res);
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());
return true;
});
setBackground(res.themeData().toolbarBackground());
}
void Toolbar::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod)
{
for (std::vector<ViewChild<View*>>& u : m_children)
for (ViewChild<View*>& c : u)
c.mouseDown(coord, button, mod);
void Toolbar::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
for (std::vector<ViewChild<View*>>& u : m_children)
for (ViewChild<View*>& c : u)
c.mouseDown(coord, button, mod);
}
void Toolbar::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod)
{
for (std::vector<ViewChild<View*>>& u : m_children)
for (ViewChild<View*>& c : u)
c.mouseUp(coord, button, mod);
void Toolbar::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) {
for (std::vector<ViewChild<View*>>& u : m_children)
for (ViewChild<View*>& c : u)
c.mouseUp(coord, button, mod);
}
void Toolbar::mouseMove(const boo::SWindowCoord& coord)
{
for (std::vector<ViewChild<View*>>& u : m_children)
for (ViewChild<View*>& c : u)
c.mouseMove(coord);
void Toolbar::mouseMove(const boo::SWindowCoord& coord) {
for (std::vector<ViewChild<View*>>& u : m_children)
for (ViewChild<View*>& c : u)
c.mouseMove(coord);
}
void Toolbar::mouseEnter(const boo::SWindowCoord& coord)
{
for (std::vector<ViewChild<View*>>& u : m_children)
for (ViewChild<View*>& c : u)
c.mouseEnter(coord);
void Toolbar::mouseEnter(const boo::SWindowCoord& coord) {
for (std::vector<ViewChild<View*>>& u : m_children)
for (ViewChild<View*>& c : u)
c.mouseEnter(coord);
}
void Toolbar::mouseLeave(const boo::SWindowCoord& coord)
{
for (std::vector<ViewChild<View*>>& u : m_children)
for (ViewChild<View*>& c : u)
c.mouseLeave(coord);
void Toolbar::mouseLeave(const boo::SWindowCoord& coord) {
for (std::vector<ViewChild<View*>>& u : m_children)
for (ViewChild<View*>& c : u)
c.mouseLeave(coord);
}
void Toolbar::setHorizontalVerts(int width)
{
m_tbVerts[0].m_pos.assign(0, 1 + m_nomGauge, 0);
m_tbVerts[0].m_uv.assign(0, 0);
m_tbVerts[1].m_pos.assign(0, -1 + m_nomGauge, 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_uv.assign(0, 0);
m_tbVerts[3].m_pos.assign(width, -1 + m_nomGauge, 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_uv.assign(0.5, 0);
void Toolbar::setHorizontalVerts(int width) {
m_tbVerts[0].m_pos.assign(0, 1 + m_nomGauge, 0);
m_tbVerts[0].m_uv.assign(0, 0);
m_tbVerts[1].m_pos.assign(0, -1 + m_nomGauge, 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_uv.assign(0, 0);
m_tbVerts[3].m_pos.assign(width, -1 + m_nomGauge, 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_uv.assign(0.5, 0);
m_tbVerts[5].m_pos.assign(0, 1, 0);
m_tbVerts[5].m_uv.assign(0.5, 0);
m_tbVerts[6].m_pos.assign(0, 1, 0);
m_tbVerts[6].m_uv.assign(0.5, 0);
m_tbVerts[7].m_pos.assign(0, -1, 0);
m_tbVerts[7].m_uv.assign(1, 0);
m_tbVerts[8].m_pos.assign(width, 1, 0);
m_tbVerts[8].m_uv.assign(0.5, 0);
m_tbVerts[9].m_pos.assign(width, -1, 0);
m_tbVerts[9].m_uv.assign(1, 0);
m_tbVerts[5].m_pos.assign(0, 1, 0);
m_tbVerts[5].m_uv.assign(0.5, 0);
m_tbVerts[6].m_pos.assign(0, 1, 0);
m_tbVerts[6].m_uv.assign(0.5, 0);
m_tbVerts[7].m_pos.assign(0, -1, 0);
m_tbVerts[7].m_uv.assign(1, 0);
m_tbVerts[8].m_pos.assign(width, 1, 0);
m_tbVerts[8].m_uv.assign(0.5, 0);
m_tbVerts[9].m_pos.assign(width, -1, 0);
m_tbVerts[9].m_uv.assign(1, 0);
}
void Toolbar::setVerticalVerts(int height)
{
m_tbVerts[0].m_pos.assign(-1, height, 0);
m_tbVerts[0].m_uv.assign(0, 0);
m_tbVerts[1].m_pos.assign(-1, 0, 0);
m_tbVerts[1].m_uv.assign(0, 0);
m_tbVerts[2].m_pos.assign(1, height, 0);
m_tbVerts[2].m_uv.assign(0.5, 0);
m_tbVerts[3].m_pos.assign(1, 0, 0);
m_tbVerts[3].m_uv.assign(0.5, 0);
m_tbVerts[4].m_pos.assign(1, 0, 0);
m_tbVerts[4].m_uv.assign(0.5, 0);
void Toolbar::setVerticalVerts(int height) {
m_tbVerts[0].m_pos.assign(-1, height, 0);
m_tbVerts[0].m_uv.assign(0, 0);
m_tbVerts[1].m_pos.assign(-1, 0, 0);
m_tbVerts[1].m_uv.assign(0, 0);
m_tbVerts[2].m_pos.assign(1, height, 0);
m_tbVerts[2].m_uv.assign(0.5, 0);
m_tbVerts[3].m_pos.assign(1, 0, 0);
m_tbVerts[3].m_uv.assign(0.5, 0);
m_tbVerts[4].m_pos.assign(1, 0, 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_uv.assign(0.5, 0);
m_tbVerts[6].m_pos.assign(-1 + m_nomGauge, height, 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_uv.assign(0.5, 0);
m_tbVerts[8].m_pos.assign(1 + m_nomGauge, height, 0);
m_tbVerts[8].m_uv.assign(1, 0);
m_tbVerts[9].m_pos.assign(1 + m_nomGauge, 0, 0);
m_tbVerts[9].m_uv.assign(1, 0);
m_tbVerts[5].m_pos.assign(-1 + m_nomGauge, height, 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_uv.assign(0.5, 0);
m_tbVerts[7].m_pos.assign(-1 + m_nomGauge, 0, 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_uv.assign(1, 0);
m_tbVerts[9].m_pos.assign(1 + m_nomGauge, 0, 0);
m_tbVerts[9].m_uv.assign(1, 0);
}
void Toolbar::push_back(View* v, unsigned unit)
{
if (unit >= m_units)
Log.report(logvisor::Fatal, "unit %u out of range %u", unit, m_units);
std::vector<ViewChild<View*>>& u = m_children[unit];
u.emplace_back();
u.back().m_view = v;
void Toolbar::push_back(View* v, unsigned unit) {
if (unit >= m_units)
Log.report(logvisor::Fatal, "unit %u out of range %u", unit, m_units);
std::vector<ViewChild<View*>>& u = m_children[unit];
u.emplace_back();
u.back().m_view = v;
}
void Toolbar::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub)
{
View::resized(root, sub);
setHorizontalVerts(sub.size[0]);
m_vertsBinding.load<decltype(m_tbVerts)>(m_tbVerts);
m_tbBlock.setViewRect(root, sub);
m_tbBlockBuf.access().finalAssign(m_tbBlock);
void Toolbar::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) {
View::resized(root, sub);
setHorizontalVerts(sub.size[0]);
m_vertsBinding.load<decltype(m_tbVerts)>(m_tbVerts);
m_tbBlock.setViewRect(root, sub);
m_tbBlockBuf.access().finalAssign(m_tbBlock);
float gaugeUnit = rootView().viewRes().pixelFactor() * SPECTER_TOOLBAR_GAUGE;
float yOff = 0.0;
for (std::vector<ViewChild<View*>>& u : m_children)
{
boo::SWindowRect childRect = sub;
boo::SWindowRect containRect = sub;
containRect.location[0] += m_padding;
containRect.size[0] -= m_padding * 2;
containRect.size[1] = gaugeUnit;
for (ViewChild<View*>& c : u)
{
c.m_view->containerResized(root, containRect);
childRect.size[0] = c.m_view->nominalWidth();
childRect.size[1] = c.m_view->nominalHeight();
childRect.location[0] += m_padding;
childRect.location[1] = sub.location[1] + (gaugeUnit - childRect.size[1]) / 2 - 1 + yOff;
c.m_view->resized(root, childRect);
childRect.location[0] += childRect.size[0];
float gaugeUnit = rootView().viewRes().pixelFactor() * SPECTER_TOOLBAR_GAUGE;
float yOff = 0.0;
for (std::vector<ViewChild<View*>>& u : m_children) {
boo::SWindowRect childRect = sub;
boo::SWindowRect containRect = sub;
containRect.location[0] += m_padding;
containRect.size[0] -= m_padding * 2;
containRect.size[1] = gaugeUnit;
for (ViewChild<View*>& c : u) {
c.m_view->containerResized(root, containRect);
childRect.size[0] = c.m_view->nominalWidth();
childRect.size[1] = c.m_view->nominalHeight();
childRect.location[0] += m_padding;
childRect.location[1] = sub.location[1] + (gaugeUnit - childRect.size[1]) / 2 - 1 + yOff;
c.m_view->resized(root, childRect);
childRect.location[0] += childRect.size[0];
containRect.location[0] += m_padding + childRect.size[0];
containRect.size[0] -= m_padding + childRect.size[0];
containRect.size[1] = gaugeUnit;
}
yOff += gaugeUnit;
containRect.location[0] += m_padding + childRect.size[0];
containRect.size[0] -= m_padding + childRect.size[0];
containRect.size[1] = gaugeUnit;
}
yOff += gaugeUnit;
}
}
void Toolbar::draw(boo::IGraphicsCommandQueue* gfxQ)
{
View::draw(gfxQ);
gfxQ->setShaderDataBinding(m_vertsBinding);
gfxQ->draw(0, 10);
for (std::vector<ViewChild<View*>>& u : m_children)
for (ViewChild<View*>& c : u)
c.m_view->draw(gfxQ);
}
void Toolbar::draw(boo::IGraphicsCommandQueue* gfxQ) {
View::draw(gfxQ);
gfxQ->setShaderDataBinding(m_vertsBinding);
gfxQ->draw(0, 10);
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/RootView.hpp"
namespace specter
{
namespace specter {
#define TOOLTIP_MAX_WIDTH 316
#define TOOLTIP_MAX_TEXT_WIDTH 300
Tooltip::Tooltip(ViewResources& res, View& parentView, std::string_view title,
std::string_view 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();
Tooltip::Tooltip(ViewResources& res, View& parentView, std::string_view title, std::string_view 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();
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool
{
buildResources(ctx, res);
m_ttBlockBuf = res.m_viewRes.m_bufPool.allocateBlock(res.m_factory);
m_vertsBinding.init(ctx, res, 16, m_ttBlockBuf);
return true;
});
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool {
buildResources(ctx, res);
m_ttBlockBuf = res.m_viewRes.m_bufPool.allocateBlock(res.m_factory);
m_vertsBinding.init(ctx, res, 16, m_ttBlockBuf);
return true;
});
for (int i=0 ; i<4 ; ++i)
{
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_cornersOutline[0]->typesetGlyphs(L"\xF4F0");
m_cornersFilled[0]->typesetGlyphs(L"\xF4F1", res.themeData().tooltipBackground());
m_cornersOutline[1]->typesetGlyphs(L"\xF4F2");
m_cornersFilled[1]->typesetGlyphs(L"\xF4F3", res.themeData().tooltipBackground());
m_cornersOutline[2]->typesetGlyphs(L"\xF4F4");
m_cornersFilled[2]->typesetGlyphs(L"\xF4F5", res.themeData().tooltipBackground());
m_cornersOutline[3]->typesetGlyphs(L"\xF4F6");
m_cornersFilled[3]->typesetGlyphs(L"\xF4F7", res.themeData().tooltipBackground());
for (int i = 0; i < 4; ++i) {
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_cornersOutline[0]->typesetGlyphs(L"\xF4F0");
m_cornersFilled[0]->typesetGlyphs(L"\xF4F1", res.themeData().tooltipBackground());
m_cornersOutline[1]->typesetGlyphs(L"\xF4F2");
m_cornersFilled[1]->typesetGlyphs(L"\xF4F3", res.themeData().tooltipBackground());
m_cornersOutline[2]->typesetGlyphs(L"\xF4F4");
m_cornersFilled[2]->typesetGlyphs(L"\xF4F5", res.themeData().tooltipBackground());
m_cornersOutline[3]->typesetGlyphs(L"\xF4F6");
m_cornersFilled[3]->typesetGlyphs(L"\xF4F7", res.themeData().tooltipBackground());
m_title.reset(new TextView(res, *this, res.m_heading14));
m_title->typesetGlyphs(m_titleStr);
m_message.reset(new MultiLineTextView(res, *this, res.m_mainFont));
m_message->typesetGlyphs(m_messageStr, zeus::CColor::skWhite,
int(TOOLTIP_MAX_TEXT_WIDTH * res.pixelFactor()));
m_title.reset(new TextView(res, *this, res.m_heading14));
m_title->typesetGlyphs(m_titleStr);
m_message.reset(new MultiLineTextView(res, *this, res.m_mainFont));
m_message->typesetGlyphs(m_messageStr, zeus::CColor::skWhite, int(TOOLTIP_MAX_TEXT_WIDTH * res.pixelFactor()));
float pf = res.pixelFactor();
std::pair<int,int> margin = m_cornersOutline[0]->queryGlyphDimensions(0);
m_nomWidth = std::min(int(TOOLTIP_MAX_WIDTH * pf),
int(std::max(m_title->nominalWidth(), m_message->nominalWidth()) + margin.first * 2));
m_nomHeight = m_title->nominalHeight() + m_message->nominalHeight() + margin.second * 3;
float pf = res.pixelFactor();
std::pair<int, int> margin = m_cornersOutline[0]->queryGlyphDimensions(0);
m_nomWidth = std::min(int(TOOLTIP_MAX_WIDTH * pf),
int(std::max(m_title->nominalWidth(), m_message->nominalWidth()) + margin.first * 2));
m_nomHeight = m_title->nominalHeight() + m_message->nominalHeight() + margin.second * 3;
}
void Tooltip::setVerts(int width, int height, float pf)
{
std::pair<int,int> margin = m_cornersFilled[0]->queryGlyphDimensions(0);
width = std::max(width, margin.first*2);
height = std::max(height, margin.second*2);
void Tooltip::setVerts(int width, int height, float pf) {
std::pair<int, int> margin = m_cornersFilled[0]->queryGlyphDimensions(0);
width = std::max(width, margin.first * 2);
height = std::max(height, margin.second * 2);
m_ttVerts[0].m_pos.assign(0, height-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[3].m_pos.assign(width, margin.second, 0);
m_ttVerts[4].m_pos.assign(width, 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[2].m_pos.assign(width, height - 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[5].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[8].m_pos.assign(width-margin.first, height, 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[5].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[8].m_pos.assign(width - margin.first, height, 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[11].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[14].m_pos.assign(width-margin.first, margin.second, 0);
m_ttVerts[15].m_pos.assign(width-margin.first, 0, 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[13].m_pos.assign(margin.first, 0, 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_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)
{
View::resized(root, sub);
float pf = rootView().viewRes().pixelFactor();
setVerts(m_nomWidth, m_nomHeight, pf);
m_ttBlock.setViewRect(root, sub);
m_ttBlockBuf.access().finalAssign(m_ttBlock);
void Tooltip::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) {
View::resized(root, sub);
float pf = rootView().viewRes().pixelFactor();
setVerts(m_nomWidth, m_nomHeight, pf);
m_ttBlock.setViewRect(root, sub);
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;
textRect.location[0] += margin.first;
textRect.location[1] += margin.second * 1.5;
m_message->resized(root, textRect);
boo::SWindowRect textRect = sub;
textRect.location[0] += margin.first;
textRect.location[1] += margin.second * 1.5;
m_message->resized(root, textRect);
textRect.location[1] += m_message->nominalHeight() + margin.second;
m_title->resized(root, textRect);
textRect.location[1] += m_message->nominalHeight() + margin.second;
m_title->resized(root, textRect);
boo::SWindowRect cornerRect = sub;
cornerRect.location[1] += m_nomHeight - margin.second; // Upper left
m_cornersOutline[0]->resized(root, cornerRect);
m_cornersFilled[0]->resized(root, cornerRect);
cornerRect.location[0] += m_nomWidth - margin.first; // Upper right
m_cornersOutline[1]->resized(root, cornerRect);
m_cornersFilled[1]->resized(root, cornerRect);
cornerRect.location[1] = sub.location[1]; // Lower right
m_cornersOutline[2]->resized(root, cornerRect);
m_cornersFilled[2]->resized(root, cornerRect);
cornerRect.location[0] = sub.location[0]; // Lower left
m_cornersOutline[3]->resized(root, cornerRect);
m_cornersFilled[3]->resized(root, cornerRect);
boo::SWindowRect cornerRect = sub;
cornerRect.location[1] += m_nomHeight - margin.second; // Upper left
m_cornersOutline[0]->resized(root, cornerRect);
m_cornersFilled[0]->resized(root, cornerRect);
cornerRect.location[0] += m_nomWidth - margin.first; // Upper right
m_cornersOutline[1]->resized(root, cornerRect);
m_cornersFilled[1]->resized(root, cornerRect);
cornerRect.location[1] = sub.location[1]; // Lower right
m_cornersOutline[2]->resized(root, cornerRect);
m_cornersFilled[2]->resized(root, cornerRect);
cornerRect.location[0] = sub.location[0]; // Lower left
m_cornersOutline[3]->resized(root, cornerRect);
m_cornersFilled[3]->resized(root, cornerRect);
}
void Tooltip::draw(boo::IGraphicsCommandQueue* gfxQ)
{
gfxQ->setShaderDataBinding(m_vertsBinding);
gfxQ->draw(0, 16);
void Tooltip::draw(boo::IGraphicsCommandQueue* gfxQ) {
gfxQ->setShaderDataBinding(m_vertsBinding);
gfxQ->draw(0, 16);
for (int i=0 ; i<4 ; ++i)
m_cornersFilled[i]->draw(gfxQ);
for (int i = 0; i < 4; ++i)
m_cornersFilled[i]->draw(gfxQ);
m_title->draw(gfxQ);
m_message->draw(gfxQ);
m_title->draw(gfxQ);
m_message->draw(gfxQ);
}
}
} // namespace specter

View File

@ -1,69 +1,57 @@
#include "specter/Translator.hpp"
#include "logvisor/logvisor.hpp"
namespace specter
{
namespace specter {
static logvisor::Module Log("specter::Translator");
Locale::Locale(std::string_view name, std::string_view fullName,
const unsigned char* yamlSource, size_t yamlLength)
: m_name(name), m_fullName(fullName)
{
athena::io::YAMLDocReader reader;
yaml_parser_set_input_string(reader.getParser(), yamlSource, yamlLength);
reader.parse(nullptr);
m_rootNode = reader.releaseRootNode();
if (m_rootNode)
{
m_langNode = m_rootNode->findMapChild(name.data());
if (!m_langNode)
Log.report(logvisor::Fatal, "no root node '%s' found in locale", name.data());
}
else
Log.report(logvisor::Warning, "locale empty");
Locale::Locale(std::string_view name, std::string_view fullName, const unsigned char* yamlSource, size_t yamlLength)
: m_name(name), m_fullName(fullName) {
athena::io::YAMLDocReader reader;
yaml_parser_set_input_string(reader.getParser(), yamlSource, yamlLength);
reader.parse(nullptr);
m_rootNode = reader.releaseRootNode();
if (m_rootNode) {
m_langNode = m_rootNode->findMapChild(name.data());
if (!m_langNode)
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)
{
if (!targetLocale)
Log.report(logvisor::Fatal, "null locale");
m_targetLocale = targetLocale;
void Translator::setLocale(const Locale* targetLocale) {
if (!targetLocale)
Log.report(logvisor::Fatal, "null locale");
m_targetLocale = targetLocale;
}
static std::string_view RecursiveLookup(const athena::io::YAMLNode* node,
std::string_view::const_iterator start,
std::string_view::const_iterator end)
{
for (std::string_view::const_iterator it = start ; it != end ; ++it)
{
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())
static std::string_view RecursiveLookup(const athena::io::YAMLNode* node, std::string_view::const_iterator start,
std::string_view::const_iterator end) {
for (std::string_view::const_iterator it = start; it != end; ++it) {
if (*it == '/') {
const athena::io::YAMLNode* ch = node->findMapChild(std::string(start, it));
if (!ch)
return nullptr;
return RecursiveLookup(m_targetLocale->rootNode(), key.cbegin(), key.cend());
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::translateOr(std::string_view key, std::string_view vor) const
{
std::string_view find = translate(key);
if (!find.empty())
return find;
return vor;
std::string_view Translator::translate(std::string_view key) const {
if (!m_targetLocale->rootNode())
return nullptr;
return RecursiveLookup(m_targetLocale->rootNode(), key.cbegin(), key.cend());
}
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 "hecl/Pipeline.hpp"
namespace specter
{
namespace specter {
static logvisor::Module Log("specter::View");
zeus::CMatrix4f g_PlatformMatrix;
void View::Resources::init(boo::IGraphicsDataFactory::Context& ctx, const IThemeData& theme)
{
switch (ctx.platform())
{
case boo::IGraphicsDataFactory::Platform::Vulkan:
g_PlatformMatrix.m[1][1] = -1.f;
break;
default:
break;
}
m_solidShader = hecl::conv->convert(ctx, Shader_SpecterViewShaderSolid{});
m_texShader = hecl::conv->convert(ctx, Shader_SpecterViewShaderTex{});
void View::Resources::init(boo::IGraphicsDataFactory::Context& ctx, const IThemeData& theme) {
switch (ctx.platform()) {
case boo::IGraphicsDataFactory::Platform::Vulkan:
g_PlatformMatrix.m[1][1] = -1.f;
break;
default:
break;
}
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)
{
m_viewVertBlockBuf = res.m_viewRes.m_bufPool.allocateBlock(res.m_factory);
m_bgVertsBinding.init(ctx, res, 4, m_viewVertBlockBuf);
void View::buildResources(boo::IGraphicsDataFactory::Context& ctx, ViewResources& res) {
m_viewVertBlockBuf = res.m_viewRes.m_bufPool.allocateBlock(res.m_factory);
m_bgVertsBinding.init(ctx, res, 4, m_viewVertBlockBuf);
}
View::View(ViewResources& res)
: m_rootView(*static_cast<RootView*>(this)),
m_parentView(*static_cast<RootView*>(this)) {}
: m_rootView(*static_cast<RootView*>(this)), m_parentView(*static_cast<RootView*>(this)) {}
View::View(ViewResources& res, View& parentView)
: m_rootView(parentView.rootView()),
m_parentView(parentView) {}
View::View(ViewResources& res, View& parentView) : m_rootView(parentView.rootView()), m_parentView(parentView) {}
void View::updateSize()
{
resized(m_rootView.rootRect(), m_subRect);
void View::updateSize() { 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)
{
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 ViewBlock& vb, const boo::SWindowRect& sub) {
m_subRect = 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(vb);
m_bgVertsBinding.load<decltype(m_bgRect)>(m_bgRect);
}
void View::resized(const ViewBlock& vb, const boo::SWindowRect& sub)
{
m_subRect = 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(vb);
m_bgVertsBinding.load<decltype(m_bgRect)>(m_bgRect);
void View::draw(boo::IGraphicsCommandQueue* gfxQ) {
if (m_bgVertsBinding.m_shaderBinding) {
gfxQ->setShaderDataBinding(m_bgVertsBinding);
gfxQ->draw(0, 4);
}
}
void View::draw(boo::IGraphicsCommandQueue* gfxQ)
{
if (m_bgVertsBinding.m_shaderBinding)
{
gfxQ->setShaderDataBinding(m_bgVertsBinding);
gfxQ->draw(0, 4);
}
void View::commitResources(ViewResources& res, const boo::FactoryCommitFunc& commitFunc) {
res.m_factory->commitTransaction(commitFunc BooTrace);
}
void View::commitResources(ViewResources& res, const boo::FactoryCommitFunc& commitFunc)
{
res.m_factory->commitTransaction(commitFunc BooTrace);
void View::VertexBufferBindingSolid::init(boo::IGraphicsDataFactory::Context& ctx, 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::VertexBufferBindingSolid::init(boo::IGraphicsDataFactory::Context& ctx,
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,
void View::VertexBufferBindingTex::init(boo::IGraphicsDataFactory::Context& ctx, ViewResources& res, size_t count,
const hecl::UniformBufferPool<ViewBlock>::Token& viewBlockBuf,
const boo::ObjToken<boo::ITexture>& texture)
{
m_vertsBuf = res.m_viewRes.m_texPool.allocateBlock(res.m_factory, count);
auto vBufInfo = m_vertsBuf.getBufferInfo();
auto uBufInfo = viewBlockBuf.getBufferInfo();
const boo::ObjToken<boo::ITexture>& texture) {
m_vertsBuf = res.m_viewRes.m_texPool.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)};
boo::ObjToken<boo::ITexture> tex[] = {texture};
boo::ObjToken<boo::IGraphicsBuffer> bufs[] = {uBufInfo.first.get()};
size_t bufOffs[] = {size_t(uBufInfo.second)};
size_t bufSizes[] = {sizeof(ViewBlock)};
boo::ObjToken<boo::ITexture> tex[] = {texture};
m_shaderBinding = ctx.newShaderDataBinding(res.m_viewRes.m_texShader,
vBufInfo.first.get(), nullptr,
nullptr, 1, bufs, nullptr, bufOffs,
bufSizes, 1, tex, nullptr, nullptr, vBufInfo.second);
m_shaderBinding = ctx.newShaderDataBinding(res.m_viewRes.m_texShader, vBufInfo.first.get(), nullptr, nullptr, 1, bufs,
nullptr, bufOffs, bufSizes, 1, tex, nullptr, nullptr, vBufInfo.second);
}
}
} // namespace specter

View File

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

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