WidgetsNew Initial
This commit is contained in:
parent
3f49ee11ae
commit
279cf58dff
15 changed files with 741 additions and 0 deletions
29
WidgetsNew/private/AnimationTestWidget.cpp
Normal file
29
WidgetsNew/private/AnimationTestWidget.cpp
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
#include "AnimationTestWidget.hpp"
|
||||
|
||||
using namespace tp;
|
||||
|
||||
void AnimationTestWidget::process(const EventHandler& events) {
|
||||
if (events.isDown(tp::InputID::MOUSE1)) {
|
||||
mTestSpring.getStart().setTargetPosition(events.getPointer());
|
||||
}
|
||||
|
||||
if (events.isDown(tp::InputID::MOUSE2)) {
|
||||
mTestSpring.getEnd().setTargetPosition(events.getPointer());
|
||||
}
|
||||
|
||||
mTestSpring.updateCurrentRect();
|
||||
|
||||
if (mTestSpring.checkAnimationShouldEnd()) {
|
||||
mTestSpring.endAnimation();
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationTestWidget::draw(Canvas& canvas) {
|
||||
canvas.rect(getRelativeArea(), { 0, 0, 0, 1 }, 10);
|
||||
canvas.rect(mTestSpring.getCurrentRect(), RGBA(1.f), 10);
|
||||
}
|
||||
|
||||
bool AnimationTestWidget::needUpdate() const {
|
||||
if (Widget::needUpdate()) return true;
|
||||
return !mTestSpring.checkAnimationShouldEnd();
|
||||
}
|
||||
32
WidgetsNew/private/FloatingWidget.cpp
Normal file
32
WidgetsNew/private/FloatingWidget.cpp
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
#include "FloatingWidget.hpp"
|
||||
|
||||
using namespace tp;
|
||||
|
||||
void FloatingWidget::process(const EventHandler& events) {
|
||||
const auto relativePointer = events.getPointer();
|
||||
|
||||
bool inside = getRelativeArea().isInside(relativePointer);
|
||||
|
||||
if (inside && events.isPressed(InputID::MOUSE1)) {
|
||||
mPointerStart = relativePointer;
|
||||
mIsFloating = true;
|
||||
}
|
||||
|
||||
if (mIsFloating && events.isReleased(InputID::MOUSE1)) {
|
||||
mIsFloating = false;
|
||||
}
|
||||
|
||||
mPointerCurrent = relativePointer;
|
||||
|
||||
setActive(mIsFloating || needUpdate());
|
||||
}
|
||||
|
||||
void FloatingWidget::updateArea(RectF& area) const {
|
||||
if (mIsFloating) {
|
||||
area.pos += mPointerCurrent - mPointerStart;
|
||||
}
|
||||
}
|
||||
|
||||
void FloatingWidget::draw(Canvas& canvas) {
|
||||
canvas.rect(getRelativeArea(), RGBA(0.5f), 10);
|
||||
}
|
||||
155
WidgetsNew/private/RootWidget.cpp
Normal file
155
WidgetsNew/private/RootWidget.cpp
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
#include "RootWidget.hpp"
|
||||
|
||||
using namespace tp;
|
||||
|
||||
void RootWidget::setRootWidget(Widget* widget) { mRoot = widget; }
|
||||
|
||||
void RootWidget::processFrame(EventHandler* events, const RectF& screenArea) {
|
||||
mNeedUpdate = false;
|
||||
|
||||
auto currentPaths = &mActivePaths[mFlipFlop];
|
||||
auto prevPaths = &mActivePaths[!mFlipFlop];
|
||||
|
||||
updateActivePaths(currentPaths, events->getPointer());
|
||||
|
||||
mRoot->setArea(screenArea);
|
||||
|
||||
clearProcessedFlag(*currentPaths);
|
||||
clearProcessedFlag(*prevPaths);
|
||||
|
||||
processPaths(*currentPaths, *events);
|
||||
processPaths(*prevPaths, *events);
|
||||
|
||||
mActiveWidgets.erase_if([](auto widget) { return !widget->mIsActive; });
|
||||
|
||||
mFlipFlop = !mFlipFlop;
|
||||
}
|
||||
|
||||
bool RootWidget::needsUpdate() const { return mNeedUpdate; }
|
||||
|
||||
void RootWidget::drawFrame(Canvas& canvas) {
|
||||
// draw from top to bottom
|
||||
drawRecursion(canvas, mRoot, { 0, 0 });
|
||||
}
|
||||
|
||||
void RootWidget::drawRecursion(Canvas& canvas, Widget* active, const Vec2F& pos) {
|
||||
canvas.setOrigin(pos);
|
||||
canvas.pushClamp({ pos, active->getArea().size });
|
||||
|
||||
active->draw(canvas);
|
||||
for (auto child : active->mChildWidgets) {
|
||||
drawRecursion(canvas, child.data(), pos + child->getArea().pos);
|
||||
}
|
||||
|
||||
canvas.setOrigin(pos);
|
||||
canvas.popClamp();
|
||||
|
||||
active->drawOverlay(canvas);
|
||||
}
|
||||
|
||||
void RootWidget::updateActivePaths(Buffer<ActivePath>* activePaths, const Vec2F& pointer) {
|
||||
activePaths->clear();
|
||||
|
||||
// based on pointer position
|
||||
Widget* pointedWidget = nullptr;
|
||||
|
||||
{
|
||||
ActivePath& activePath = activePaths->append(ActivePath{});
|
||||
activePath.path.append({ mRoot, {} });
|
||||
|
||||
auto pointerIter = pointer;
|
||||
|
||||
bool newActive = true;
|
||||
while (newActive) {
|
||||
newActive = false;
|
||||
for (auto child : activePath.path.last().widget->mChildWidgets) {
|
||||
const auto area = child->mArea.getCurrentRect();
|
||||
if (area.isInside(pointerIter)) {
|
||||
activePath.path.append({ child.data(), {} });
|
||||
newActive = true;
|
||||
pointerIter -= child->getArea().pos;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pointedWidget = activePath.path.last().widget;
|
||||
}
|
||||
|
||||
// based on individual widget requirements
|
||||
{
|
||||
for (auto widget : mActiveWidgets) {
|
||||
if (widget.data() == pointedWidget) continue;
|
||||
|
||||
ActivePath& activePath = activePaths->append(ActivePath{});
|
||||
|
||||
for (Widget* iter = widget.data(); iter; iter = iter->mParent) {
|
||||
activePath.path.append({ iter, {} });
|
||||
}
|
||||
|
||||
activePath.path.reverse();
|
||||
}
|
||||
}
|
||||
|
||||
// update paths global pos
|
||||
for (auto activePath : *activePaths) {
|
||||
Vec2F iterPos = { 0, 0 };
|
||||
for (auto activeWidget : activePath->path) {
|
||||
iterPos += activeWidget->widget->getArea().pos;
|
||||
activeWidget->globalPos = iterPos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RootWidget::setWidgetArea(Widget& widget, const RectF& rect) {
|
||||
widget.mArea.setTargetRect(rect);
|
||||
widget.mArea.endAnimation();
|
||||
}
|
||||
|
||||
void RootWidget::processPaths(const Buffer<ActivePath>& paths, EventHandler& events) {
|
||||
EventHandler dummyEvents;
|
||||
bool eventsHandled = false;
|
||||
|
||||
for (auto path : paths) {
|
||||
|
||||
for (alni widgetIdx = (alni) path->path.size() - 1; widgetIdx >= 0; widgetIdx--) {
|
||||
auto activeWidgetNode = path->path[widgetIdx];
|
||||
auto activeWidget = activeWidgetNode.widget;
|
||||
|
||||
activeWidget->mArea.updateCurrentRect();
|
||||
|
||||
events.setCursorOrigin(activeWidgetNode.globalPos);
|
||||
|
||||
bool useEvents = !eventsHandled || activeWidget->mIsActive;
|
||||
|
||||
if (!activeWidget->mProcessedFlag) {
|
||||
activeWidget->process(useEvents ? events : dummyEvents);
|
||||
activeWidget->mProcessedFlag = true;
|
||||
}
|
||||
|
||||
eventsHandled = !activeWidget->isPassThroughEvents();
|
||||
|
||||
auto area = activeWidget->mArea.getCurrentRect();
|
||||
activeWidget->updateArea(area);
|
||||
activeWidget->setArea(area);
|
||||
|
||||
mNeedUpdate |= activeWidget->needUpdate();
|
||||
|
||||
if (!activeWidget->needUpdate()) activeWidget->finishAnimations();
|
||||
|
||||
if (activeWidget->mIsActive) {
|
||||
if (mActiveWidgets.find(activeWidget) == -1) {
|
||||
mActiveWidgets.append(activeWidget);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RootWidget::clearProcessedFlag(const Buffer<ActivePath>& paths) {
|
||||
for (auto path : paths) {
|
||||
for (auto widget : path->path) {
|
||||
widget->widget->mProcessedFlag = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
56
WidgetsNew/private/SimpleWidgets.cpp
Normal file
56
WidgetsNew/private/SimpleWidgets.cpp
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
|
||||
#include "SimpleWidgets.hpp"
|
||||
|
||||
using namespace tp;
|
||||
|
||||
void LabelWidget::setText(const std::string& text) {
|
||||
mText = text;
|
||||
}
|
||||
|
||||
const std::string& LabelWidget::getText() const {
|
||||
return mText;
|
||||
}
|
||||
|
||||
void LabelWidget::draw(Canvas& canvas) {
|
||||
canvas.text(mText.c_str(), getRelativeArea(), mSize, Canvas::LC, mPadding, mColor);
|
||||
}
|
||||
|
||||
|
||||
ButtonWidget::ButtonWidget() {
|
||||
mAction = []() {
|
||||
printf("Button Pressed!\n");
|
||||
};
|
||||
}
|
||||
|
||||
void ButtonWidget::setAction(const std::function<void()>& action) {
|
||||
mAction = action;
|
||||
}
|
||||
|
||||
void ButtonWidget::process(const EventHandler& eventHandler) {
|
||||
if (getRelativeArea().isInside(eventHandler.getPointer())) {
|
||||
if (eventHandler.isPressed(InputID::MOUSE1)) {
|
||||
mAction();
|
||||
}
|
||||
|
||||
mColorAnimated.setTargetColor(mColor);
|
||||
} else {
|
||||
mColorAnimated.setTargetColor(mColorHovered);
|
||||
}
|
||||
|
||||
mColorAnimated.updateCurrentRect();
|
||||
|
||||
setActive(needUpdate());
|
||||
}
|
||||
|
||||
void ButtonWidget::draw(Canvas& canvas) {
|
||||
canvas.rect(getRelativeArea(), mColorAnimated.getCurrentColor(), mRounding);
|
||||
LabelWidget::draw(canvas);
|
||||
}
|
||||
|
||||
bool ButtonWidget::needUpdate() const {
|
||||
return !mColorAnimated.checkAnimationShouldEnd();
|
||||
}
|
||||
|
||||
void ButtonWidget::finishAnimations() {
|
||||
mColorAnimated.endAnimation();
|
||||
}
|
||||
50
WidgetsNew/private/Widget.cpp
Normal file
50
WidgetsNew/private/Widget.cpp
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
#include "Widget.hpp"
|
||||
|
||||
using namespace tp;
|
||||
|
||||
Widget::Widget() {
|
||||
mArea.setTargetRect({ 10, 10, 100, 40, });
|
||||
mArea.endAnimation();
|
||||
}
|
||||
|
||||
void Widget::setArea(const RectF& area) {
|
||||
mArea.setTargetRect(area);
|
||||
}
|
||||
|
||||
void Widget::draw(Canvas& canvas) {
|
||||
canvas.rect(mArea.getCurrentRect(), RGBA(1.f), 10);
|
||||
}
|
||||
|
||||
RectF Widget::getArea() const {
|
||||
return mArea.getCurrentRect();
|
||||
}
|
||||
|
||||
RectF Widget::getRelativeArea() const {
|
||||
return { {}, mArea.getCurrentRect().size };
|
||||
}
|
||||
|
||||
void Widget::setActive(bool active) {
|
||||
mIsActive = active;
|
||||
}
|
||||
|
||||
void Widget::addChild(Widget* widget) {
|
||||
if (widget->mParent) {
|
||||
widget->mParent->removeChild(widget);
|
||||
}
|
||||
mChildWidgets.pushBack(widget);
|
||||
widget->mParent = this;
|
||||
}
|
||||
|
||||
void Widget::removeChild(Widget* widget) {
|
||||
auto node = mChildWidgets.find(widget);
|
||||
node->data->mParent = nullptr;
|
||||
mChildWidgets.removeNode(node);
|
||||
}
|
||||
|
||||
bool Widget::needUpdate() const {
|
||||
return !mArea.checkAnimationShouldEnd();
|
||||
}
|
||||
|
||||
void Widget::finishAnimations() {
|
||||
mArea.endAnimation();
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue