parent
1d86da332c
commit
ae2e5dad31
|
|
@ -75,7 +75,7 @@ namespace easy2d
|
||||||
}
|
}
|
||||||
|
|
||||||
Canvas::Canvas(Size const & size)
|
Canvas::Canvas(Size const & size)
|
||||||
: Canvas(size.width, size.height)
|
: Canvas(size.x, size.y)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -158,7 +158,7 @@ namespace easy2d
|
||||||
return stroke_width_;
|
return stroke_width_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::SetBrushTransform(math::Matrix const & transform)
|
void Canvas::SetBrushTransform(Matrix const & transform)
|
||||||
{
|
{
|
||||||
render_target_->SetTransform(transform);
|
render_target_->SetTransform(transform);
|
||||||
}
|
}
|
||||||
|
|
@ -217,8 +217,8 @@ namespace easy2d
|
||||||
D2D1::RectF(
|
D2D1::RectF(
|
||||||
rect.origin.x,
|
rect.origin.x,
|
||||||
rect.origin.y,
|
rect.origin.y,
|
||||||
rect.origin.x + rect.size.width,
|
rect.origin.x + rect.size.x,
|
||||||
rect.origin.y + rect.size.height
|
rect.origin.y + rect.size.y
|
||||||
),
|
),
|
||||||
stroke_brush_.Get(),
|
stroke_brush_.Get(),
|
||||||
stroke_width_,
|
stroke_width_,
|
||||||
|
|
@ -234,8 +234,8 @@ namespace easy2d
|
||||||
D2D1::RectF(
|
D2D1::RectF(
|
||||||
rect.origin.x,
|
rect.origin.x,
|
||||||
rect.origin.y,
|
rect.origin.y,
|
||||||
rect.origin.x + rect.size.width,
|
rect.origin.x + rect.size.x,
|
||||||
rect.origin.y + rect.size.height
|
rect.origin.y + rect.size.y
|
||||||
),
|
),
|
||||||
radius_x,
|
radius_x,
|
||||||
radius_y
|
radius_y
|
||||||
|
|
@ -345,8 +345,8 @@ namespace easy2d
|
||||||
D2D1::RectF(
|
D2D1::RectF(
|
||||||
rect.origin.x,
|
rect.origin.x,
|
||||||
rect.origin.y,
|
rect.origin.y,
|
||||||
rect.origin.x + rect.size.width,
|
rect.origin.x + rect.size.x,
|
||||||
rect.origin.y + rect.size.height
|
rect.origin.y + rect.size.y
|
||||||
),
|
),
|
||||||
fill_brush_.Get()
|
fill_brush_.Get()
|
||||||
);
|
);
|
||||||
|
|
@ -360,8 +360,8 @@ namespace easy2d
|
||||||
D2D1::RectF(
|
D2D1::RectF(
|
||||||
rect.origin.x,
|
rect.origin.x,
|
||||||
rect.origin.y,
|
rect.origin.y,
|
||||||
rect.origin.x + rect.size.width,
|
rect.origin.x + rect.size.x,
|
||||||
rect.origin.y + rect.size.height
|
rect.origin.y + rect.size.y
|
||||||
),
|
),
|
||||||
radius_x,
|
radius_x,
|
||||||
radius_y
|
radius_y
|
||||||
|
|
|
||||||
|
|
@ -212,7 +212,7 @@ namespace easy2d
|
||||||
|
|
||||||
// 变换画笔
|
// 变换画笔
|
||||||
void SetBrushTransform(
|
void SetBrushTransform(
|
||||||
math::Matrix const& transform
|
Matrix const& transform
|
||||||
);
|
);
|
||||||
|
|
||||||
// 导出为图片
|
// 导出为图片
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@ namespace easy2d
|
||||||
{
|
{
|
||||||
auto graphics = Graphics::Instance();
|
auto graphics = Graphics::Instance();
|
||||||
|
|
||||||
graphics->SetTransform(math::Matrix{});
|
graphics->SetTransform(Matrix{});
|
||||||
|
|
||||||
graphics->GetSolidBrush()->SetColor(Color(0.0f, 0.0f, 0.0f, 0.5f));
|
graphics->GetSolidBrush()->SetColor(Color(0.0f, 0.0f, 0.0f, 0.5f));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -351,7 +351,7 @@ namespace easy2d
|
||||||
|
|
||||||
HRESULT FactoryImpl::CreateTransformedGeometry(
|
HRESULT FactoryImpl::CreateTransformedGeometry(
|
||||||
cpTransformedGeometry& transformed,
|
cpTransformedGeometry& transformed,
|
||||||
math::Matrix const& matrix,
|
Matrix const& matrix,
|
||||||
cpGeometry const& geo
|
cpGeometry const& geo
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ namespace easy2d
|
||||||
|
|
||||||
HRESULT CreateTransformedGeometry(
|
HRESULT CreateTransformedGeometry(
|
||||||
cpTransformedGeometry& transformed,
|
cpTransformedGeometry& transformed,
|
||||||
math::Matrix const& matrix,
|
Matrix const& matrix,
|
||||||
cpGeometry const& geo
|
cpGeometry const& geo
|
||||||
) const;
|
) const;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -113,19 +113,19 @@ namespace easy2d
|
||||||
auto bitmap_size = bitmap_->GetSize();
|
auto bitmap_size = bitmap_->GetSize();
|
||||||
crop_rect_.origin.x = std::min(std::max(crop_rect.origin.x, 0.f), bitmap_size.width);
|
crop_rect_.origin.x = std::min(std::max(crop_rect.origin.x, 0.f), bitmap_size.width);
|
||||||
crop_rect_.origin.y = std::min(std::max(crop_rect.origin.y, 0.f), bitmap_size.height);
|
crop_rect_.origin.y = std::min(std::max(crop_rect.origin.y, 0.f), bitmap_size.height);
|
||||||
crop_rect_.size.width = std::min(std::max(crop_rect.size.width, 0.f), bitmap_size.width - crop_rect.origin.x);
|
crop_rect_.size.x = std::min(std::max(crop_rect.size.x, 0.f), bitmap_size.width - crop_rect.origin.x);
|
||||||
crop_rect_.size.height = std::min(std::max(crop_rect.size.height, 0.f), bitmap_size.height - crop_rect.origin.y);
|
crop_rect_.size.y = std::min(std::max(crop_rect.size.y, 0.f), bitmap_size.height - crop_rect.origin.y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float Image::GetWidth() const
|
float Image::GetWidth() const
|
||||||
{
|
{
|
||||||
return crop_rect_.size.width;
|
return crop_rect_.size.x;
|
||||||
}
|
}
|
||||||
|
|
||||||
float Image::GetHeight() const
|
float Image::GetHeight() const
|
||||||
{
|
{
|
||||||
return crop_rect_.size.height;
|
return crop_rect_.size.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
Size Image::GetSize() const
|
Size Image::GetSize() const
|
||||||
|
|
@ -139,10 +139,7 @@ namespace easy2d
|
||||||
{
|
{
|
||||||
return bitmap_->GetSize().width;
|
return bitmap_->GetSize().width;
|
||||||
}
|
}
|
||||||
else
|
return 0;
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float Image::GetSourceHeight() const
|
float Image::GetSourceHeight() const
|
||||||
|
|
@ -151,10 +148,7 @@ namespace easy2d
|
||||||
{
|
{
|
||||||
return bitmap_->GetSize().height;
|
return bitmap_->GetSize().height;
|
||||||
}
|
}
|
||||||
else
|
return 0;
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Size Image::GetSourceSize() const
|
Size Image::GetSourceSize() const
|
||||||
|
|
@ -198,8 +192,8 @@ namespace easy2d
|
||||||
{
|
{
|
||||||
bitmap_ = bitmap;
|
bitmap_ = bitmap;
|
||||||
crop_rect_.origin.x = crop_rect_.origin.y = 0;
|
crop_rect_.origin.x = crop_rect_.origin.y = 0;
|
||||||
crop_rect_.size.width = bitmap_->GetSize().width;
|
crop_rect_.size.x = bitmap_->GetSize().width;
|
||||||
crop_rect_.size.height = bitmap_->GetSize().height;
|
crop_rect_.size.y = bitmap_->GetSize().height;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "Event.hpp"
|
#include "Event.hpp"
|
||||||
|
#include "helper.hpp"
|
||||||
|
|
||||||
namespace easy2d
|
namespace easy2d
|
||||||
{
|
{
|
||||||
|
|
@ -36,15 +37,18 @@ namespace easy2d
|
||||||
Up, // 抬起
|
Up, // 抬起
|
||||||
Wheel, // 滚轮滚动
|
Wheel, // 滚轮滚动
|
||||||
|
|
||||||
|
Hover, // 報炎卞秘
|
||||||
|
Out, // 報炎卞竃
|
||||||
|
Click, // 報炎泣似
|
||||||
|
|
||||||
Last // 结束标志
|
Last // 结束标志
|
||||||
};
|
};
|
||||||
|
|
||||||
MouseEvent(EventType type, float x, float y, float wheel_delta) : Event(type), x(x), y(y), wheel_delta(wheel_delta), button_down(false) {}
|
MouseEvent(EventType type, float x, float y, float wheel_delta) : Event(type), position(x, y), wheel_delta(wheel_delta), button_down(false) {}
|
||||||
|
|
||||||
static bool Check(Event* e) { return e->type > Type::First && e->type < Type::Last; }
|
static bool Check(Event* e) { return e->type > Type::First && e->type < Type::Last; }
|
||||||
|
|
||||||
float x;
|
Point position;
|
||||||
float y;
|
|
||||||
float wheel_delta;
|
float wheel_delta;
|
||||||
bool button_down;
|
bool button_down;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -19,10 +19,11 @@
|
||||||
// THE SOFTWARE.
|
// THE SOFTWARE.
|
||||||
|
|
||||||
#include "Node.h"
|
#include "Node.h"
|
||||||
|
#include "Action.hpp"
|
||||||
#include "Factory.h"
|
#include "Factory.h"
|
||||||
#include "Scene.h"
|
#include "Scene.h"
|
||||||
#include "Task.h"
|
#include "Task.h"
|
||||||
#include "Action.hpp"
|
#include "MouseEvent.hpp"
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
#include "logs.h"
|
#include "logs.h"
|
||||||
|
|
||||||
|
|
@ -43,6 +44,7 @@ namespace easy2d
|
||||||
Node::Node()
|
Node::Node()
|
||||||
: visible_(true)
|
: visible_(true)
|
||||||
, dirty_transform_(false)
|
, dirty_transform_(false)
|
||||||
|
, dirty_transform_inverse_(false)
|
||||||
, parent_(nullptr)
|
, parent_(nullptr)
|
||||||
, hash_name_(0)
|
, hash_name_(0)
|
||||||
, z_order_(0)
|
, z_order_(0)
|
||||||
|
|
@ -116,30 +118,78 @@ namespace easy2d
|
||||||
if (!visible_)
|
if (!visible_)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this->HandleEvent(e);
|
|
||||||
|
|
||||||
if (!e->has_target)
|
|
||||||
{
|
|
||||||
EventDispatcher::DispatchEvent(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Node::HandleEvent(Event * e)
|
|
||||||
{
|
|
||||||
spNode prev;
|
spNode prev;
|
||||||
for (auto child = children_.Last(); child; child = prev)
|
for (auto child = children_.Last(); child; child = prev)
|
||||||
{
|
{
|
||||||
prev = child->PrevItem();
|
prev = child->PrevItem();
|
||||||
child->HandleEvent(e);
|
child->DispatchEvent(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (MouseEvent::Check(e))
|
||||||
|
{
|
||||||
|
MouseEvent* me = static_cast<MouseEvent*>(e);
|
||||||
|
|
||||||
|
if (me->type == MouseEvent::Move)
|
||||||
|
{
|
||||||
|
if (!me->has_target && ContainsPoint(me->position))
|
||||||
|
{
|
||||||
|
me->has_target = true;
|
||||||
|
|
||||||
|
if (!hover_)
|
||||||
|
{
|
||||||
|
hover_ = true;
|
||||||
|
|
||||||
|
MouseEvent hover = *me;
|
||||||
|
hover.type = MouseEvent::Hover;
|
||||||
|
DispatchEvent(&hover);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (hover_)
|
||||||
|
{
|
||||||
|
hover_ = false;
|
||||||
|
pressed_ = false;
|
||||||
|
|
||||||
|
MouseEvent hover = *me;
|
||||||
|
hover.type = MouseEvent::Out;
|
||||||
|
DispatchEvent(&hover);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (me->type == MouseEvent::Down && hover_)
|
||||||
|
{
|
||||||
|
pressed_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (me->type == MouseEvent::Up && pressed_)
|
||||||
|
{
|
||||||
|
pressed_ = false;
|
||||||
|
|
||||||
|
MouseEvent click = *me;
|
||||||
|
click.type = MouseEvent::Click;
|
||||||
|
DispatchEvent(&click);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EventDispatcher::DispatchEvent(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
math::Matrix const & Node::GetTransformMatrix()
|
Matrix const & Node::GetTransformMatrix() const
|
||||||
{
|
{
|
||||||
UpdateTransform();
|
UpdateTransform();
|
||||||
return transform_matrix_;
|
return transform_matrix_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Matrix const & Node::GetTransformInverseMatrix() const
|
||||||
|
{
|
||||||
|
UpdateTransform();
|
||||||
|
if (dirty_transform_inverse_)
|
||||||
|
{
|
||||||
|
transform_matrix_inverse_ = Matrix::Invert(transform_matrix_);
|
||||||
|
dirty_transform_inverse_ = false;
|
||||||
|
}
|
||||||
|
return transform_matrix_inverse_;
|
||||||
|
}
|
||||||
|
|
||||||
spNode Node::GetParent() const
|
spNode Node::GetParent() const
|
||||||
{
|
{
|
||||||
return parent_;
|
return parent_;
|
||||||
|
|
@ -150,20 +200,21 @@ namespace easy2d
|
||||||
return scene_;
|
return scene_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Node::UpdateTransform()
|
void Node::UpdateTransform() const
|
||||||
{
|
{
|
||||||
if (!dirty_transform_)
|
if (!dirty_transform_)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
dirty_transform_ = false;
|
dirty_transform_ = false;
|
||||||
|
dirty_transform_inverse_ = true;
|
||||||
|
|
||||||
// matrix multiplication is optimized by expression template
|
// matrix multiplication is optimized by expression template
|
||||||
transform_matrix_ = math::Matrix::Scaling(transform_.scale)
|
transform_matrix_ = Matrix::Scaling(transform_.scale)
|
||||||
* math::Matrix::Skewing(transform_.skew.x, transform_.skew.y)
|
* Matrix::Skewing(transform_.skew.x, transform_.skew.y)
|
||||||
* math::Matrix::Rotation(transform_.rotation)
|
* Matrix::Rotation(transform_.rotation)
|
||||||
* math::Matrix::Translation(transform_.position);
|
* Matrix::Translation(transform_.position);
|
||||||
|
|
||||||
Point offset{ -size_.width * pivot_.x, -size_.height * pivot_.y };
|
Point offset{ -size_.x * pivot_.x, -size_.y * pivot_.y };
|
||||||
transform_matrix_.Translate(offset);
|
transform_matrix_.Translate(offset);
|
||||||
|
|
||||||
if (parent_)
|
if (parent_)
|
||||||
|
|
@ -261,26 +312,26 @@ namespace easy2d
|
||||||
|
|
||||||
void Node::SetWidth(float width)
|
void Node::SetWidth(float width)
|
||||||
{
|
{
|
||||||
this->SetSize(width, size_.height);
|
this->SetSize(width, size_.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Node::SetHeight(float height)
|
void Node::SetHeight(float height)
|
||||||
{
|
{
|
||||||
this->SetSize(size_.width, height);
|
this->SetSize(size_.x, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Node::SetSize(const Size& size)
|
void Node::SetSize(const Size& size)
|
||||||
{
|
{
|
||||||
this->SetSize(size.width, size.height);
|
this->SetSize(size.x, size.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Node::SetSize(float width, float height)
|
void Node::SetSize(float width, float height)
|
||||||
{
|
{
|
||||||
if (size_.width == width && size_.height == height)
|
if (size_.x == width && size_.y == height)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
size_.width = width;
|
size_.x = width;
|
||||||
size_.height = height;
|
size_.y = height;
|
||||||
dirty_transform_ = true;
|
dirty_transform_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -427,7 +478,7 @@ namespace easy2d
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Rect Node::GetBounds()
|
Rect Node::GetBounds() const
|
||||||
{
|
{
|
||||||
return Rect(Point{}, size_);
|
return Rect(Point{}, size_);
|
||||||
}
|
}
|
||||||
|
|
@ -522,25 +573,12 @@ namespace easy2d
|
||||||
children_.Clear();
|
children_.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Node::ContainsPoint(const Point& point)
|
bool Node::ContainsPoint(const Point& point) const
|
||||||
{
|
{
|
||||||
if (size_.width == 0.f || size_.height == 0.f)
|
if (size_.x == 0.f || size_.y == 0.f)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
UpdateTransform();
|
math::Vector2 local = GetTransformInverseMatrix().Transform(point);
|
||||||
|
return GetBounds().ContainsPoint(local);
|
||||||
cpRectangleGeometry border;
|
|
||||||
|
|
||||||
ThrowIfFailed(
|
|
||||||
Factory::Instance()->CreateRectangleGeometry(
|
|
||||||
border,
|
|
||||||
Rect(Point{}, size_)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
BOOL ret = 0;
|
|
||||||
// no matter it failed or not
|
|
||||||
border->FillContainsPoint(point, transform_matrix_, &ret);
|
|
||||||
return !!ret;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -56,9 +56,6 @@ namespace easy2d
|
||||||
// 渲染节点
|
// 渲染节点
|
||||||
virtual void OnRender() {}
|
virtual void OnRender() {}
|
||||||
|
|
||||||
// ´¦Àíʼþ
|
|
||||||
virtual void HandleEvent(Event* e);
|
|
||||||
|
|
||||||
// 获取显示状态
|
// 获取显示状态
|
||||||
bool IsVisible() const { return visible_; }
|
bool IsVisible() const { return visible_; }
|
||||||
|
|
||||||
|
|
@ -96,19 +93,19 @@ namespace easy2d
|
||||||
float GetRotation() const { return transform_.rotation; }
|
float GetRotation() const { return transform_.rotation; }
|
||||||
|
|
||||||
// 获取宽度
|
// 获取宽度
|
||||||
float GetWidth() const { return size_.width; }
|
float GetWidth() const { return size_.x; }
|
||||||
|
|
||||||
// 获取高度
|
// 获取高度
|
||||||
float GetHeight() const { return size_.height; }
|
float GetHeight() const { return size_.y; }
|
||||||
|
|
||||||
// 获取大小
|
// 获取大小
|
||||||
Size const& GetSize() const { return size_; }
|
Size const& GetSize() const { return size_; }
|
||||||
|
|
||||||
// 获取缩放后的宽度
|
// 获取缩放后的宽度
|
||||||
float GetScaledWidth() const { return size_.width * transform_.scale.x; }
|
float GetScaledWidth() const { return size_.x * transform_.scale.x; }
|
||||||
|
|
||||||
// 获取缩放后的高度
|
// 获取缩放后的高度
|
||||||
float GetScaledHeight() const { return size_.height * transform_.scale.y; }
|
float GetScaledHeight() const { return size_.y * transform_.scale.y; }
|
||||||
|
|
||||||
// 获取缩放后的大小
|
// 获取缩放后的大小
|
||||||
Size GetScaledSize() const { return Size{ GetScaledWidth(), GetScaledHeight() }; }
|
Size GetScaledSize() const { return Size{ GetScaledWidth(), GetScaledHeight() }; }
|
||||||
|
|
@ -126,10 +123,13 @@ namespace easy2d
|
||||||
Transform const& GetTransform() const { return transform_; }
|
Transform const& GetTransform() const { return transform_; }
|
||||||
|
|
||||||
// 获取包围盒
|
// 获取包围盒
|
||||||
virtual Rect GetBounds();
|
Rect GetBounds() const;
|
||||||
|
|
||||||
// 获取二维变换矩阵
|
// 获取二维变换矩阵
|
||||||
math::Matrix const& GetTransformMatrix();
|
Matrix const& GetTransformMatrix() const;
|
||||||
|
|
||||||
|
// »ñÈ¡¶þά±ä»»µÄÄæ¾ØÕó
|
||||||
|
Matrix const& GetTransformInverseMatrix() const;
|
||||||
|
|
||||||
// 获取父节点
|
// 获取父节点
|
||||||
spNode GetParent() const;
|
spNode GetParent() const;
|
||||||
|
|
@ -243,7 +243,7 @@ namespace easy2d
|
||||||
|
|
||||||
// 设置支点位置
|
// 设置支点位置
|
||||||
// 默认为 (0, 0), 范围 [0, 1]
|
// 默认为 (0, 0), 范围 [0, 1]
|
||||||
virtual void SetPivot(
|
void SetPivot(
|
||||||
float pivot_x,
|
float pivot_x,
|
||||||
float pivot_y
|
float pivot_y
|
||||||
);
|
);
|
||||||
|
|
@ -288,7 +288,7 @@ namespace easy2d
|
||||||
// 判断点是否在节点内
|
// 判断点是否在节点内
|
||||||
bool ContainsPoint(
|
bool ContainsPoint(
|
||||||
const Point& point
|
const Point& point
|
||||||
);
|
) const;
|
||||||
|
|
||||||
// 添加子节点
|
// 添加子节点
|
||||||
void AddChild(
|
void AddChild(
|
||||||
|
|
@ -347,7 +347,7 @@ namespace easy2d
|
||||||
|
|
||||||
void Render();
|
void Render();
|
||||||
|
|
||||||
void UpdateTransform();
|
void UpdateTransform() const;
|
||||||
|
|
||||||
void UpdateOpacity();
|
void UpdateOpacity();
|
||||||
|
|
||||||
|
|
@ -355,18 +355,23 @@ namespace easy2d
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool visible_;
|
bool visible_;
|
||||||
bool dirty_transform_;
|
bool hover_;
|
||||||
|
bool pressed_;
|
||||||
int z_order_;
|
int z_order_;
|
||||||
float opacity_;
|
float opacity_;
|
||||||
float display_opacity_;
|
float display_opacity_;
|
||||||
std::wstring name_;
|
std::wstring name_;
|
||||||
size_t hash_name_;
|
size_t hash_name_;
|
||||||
Transform transform_;
|
Transform transform_;
|
||||||
math::Matrix transform_matrix_;
|
|
||||||
Point pivot_;
|
Point pivot_;
|
||||||
Size size_;
|
Size size_;
|
||||||
Node* parent_;
|
Node* parent_;
|
||||||
Scene* scene_;
|
Scene* scene_;
|
||||||
Children children_;
|
Children children_;
|
||||||
|
|
||||||
|
mutable bool dirty_transform_;
|
||||||
|
mutable bool dirty_transform_inverse_;
|
||||||
|
mutable Matrix transform_matrix_;
|
||||||
|
mutable Matrix transform_matrix_inverse_;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,89 +0,0 @@
|
||||||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
// THE SOFTWARE.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include "../math/vector.hpp"
|
|
||||||
#include <d2d1.h>
|
|
||||||
|
|
||||||
namespace easy2d
|
|
||||||
{
|
|
||||||
// 坐标
|
|
||||||
//
|
|
||||||
// Usage:
|
|
||||||
// 表示一个二维空间的坐标: Point origin(0, 0);
|
|
||||||
// 计算两点间距离: float distance = p1.Distance(p2);
|
|
||||||
// 坐标可以相加减: Point p = Point(10, 10) + Point(20, 20); // p 的坐标是 (30, 30)
|
|
||||||
//
|
|
||||||
class Point
|
|
||||||
: public math::Vector2
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Point() {}
|
|
||||||
|
|
||||||
Point(float x, float y) : math::Vector2(x, y) {}
|
|
||||||
|
|
||||||
Point(Point const& other) : math::Vector2(other.x, other.y) {}
|
|
||||||
|
|
||||||
inline float Distance(Point const& v)
|
|
||||||
{
|
|
||||||
return Point(x - v.x, y - v.y).Length();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const Point operator + (const Point & other) const
|
|
||||||
{
|
|
||||||
return Point(x + other.x, y + other.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const Point operator - (const Point & other) const
|
|
||||||
{
|
|
||||||
return Point(x - other.x, y - other.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const Point operator * (float val) const
|
|
||||||
{
|
|
||||||
return Point(x * val, y * val);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const Point operator / (float val) const
|
|
||||||
{
|
|
||||||
return Point(x / val, y / val);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const Point operator - () const
|
|
||||||
{
|
|
||||||
return Point(-x, -y);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator == (const Point& other) const
|
|
||||||
{
|
|
||||||
return (x == other.x) && (y == other.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline operator D2D1_POINT_2F const& () const
|
|
||||||
{
|
|
||||||
return reinterpret_cast<D2D1_POINT_2F const&>(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline operator D2D1_POINT_2F& ()
|
|
||||||
{
|
|
||||||
return reinterpret_cast<D2D1_POINT_2F&>(*this);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,128 +0,0 @@
|
||||||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
// THE SOFTWARE.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include "Point.hpp"
|
|
||||||
#include "Size.hpp"
|
|
||||||
#include <d2d1.h>
|
|
||||||
|
|
||||||
namespace easy2d
|
|
||||||
{
|
|
||||||
// 矩形
|
|
||||||
//
|
|
||||||
// Usage:
|
|
||||||
// 表示一个二维矩形: Rect rect = Rect(10, 20, 30, 40); // 左上角坐标为 (10, 20), 宽为 30, 高为 40
|
|
||||||
// 矩形可以通过 Point + Size 定义, Point 表示矩形左上角坐标, Size 表示矩形宽高
|
|
||||||
// 判断一个点是否在矩形内: bool contains = rect.ContainsPoint(p);
|
|
||||||
// 判断两矩形是否相交: bool intersects = rect1.Intersects(rect2);
|
|
||||||
//
|
|
||||||
class Rect
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Point origin; // 左上角坐标
|
|
||||||
Size size; // 宽度和高度
|
|
||||||
|
|
||||||
public:
|
|
||||||
Rect() {}
|
|
||||||
|
|
||||||
Rect(
|
|
||||||
float x,
|
|
||||||
float y,
|
|
||||||
float width,
|
|
||||||
float height
|
|
||||||
)
|
|
||||||
: origin(x, y)
|
|
||||||
, size(width, height)
|
|
||||||
{}
|
|
||||||
|
|
||||||
Rect(
|
|
||||||
const Point& pos,
|
|
||||||
const Size& size
|
|
||||||
)
|
|
||||||
: origin(pos.x, pos.y)
|
|
||||||
, size(size.width, size.height)
|
|
||||||
{}
|
|
||||||
|
|
||||||
Rect(
|
|
||||||
const Rect& other
|
|
||||||
)
|
|
||||||
: origin(other.origin.x, other.origin.y)
|
|
||||||
, size(other.size.width, other.size.height)
|
|
||||||
{}
|
|
||||||
|
|
||||||
Rect(
|
|
||||||
const D2D1_RECT_F& other
|
|
||||||
)
|
|
||||||
: origin(other.left, other.top)
|
|
||||||
, size(other.right - other.left, other.bottom - other.top)
|
|
||||||
{}
|
|
||||||
|
|
||||||
Rect& operator= (const Rect& other)
|
|
||||||
{
|
|
||||||
origin = other.origin;
|
|
||||||
size = other.size;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator== (const Rect& rect) const
|
|
||||||
{
|
|
||||||
return (origin == rect.origin) && (size == rect.size);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Point GetCenter() const { return Point{ origin.x + size.width / 2, origin.y + size.height / 2 }; }
|
|
||||||
|
|
||||||
inline Point GetLeftTop() const { return origin; }
|
|
||||||
|
|
||||||
inline Point GetRightBottom() const { return Point{ GetRight(), GetBottom() }; }
|
|
||||||
|
|
||||||
inline Point GetRightTop() const { return Point{ GetRight(), GetTop() }; }
|
|
||||||
|
|
||||||
inline Point GetLeftBottom() const { return Point{ GetLeft(), GetBottom() }; }
|
|
||||||
|
|
||||||
inline float GetLeft() const { return origin.x; }
|
|
||||||
|
|
||||||
inline float GetTop() const { return origin.y; }
|
|
||||||
|
|
||||||
inline float GetRight() const { return origin.x + size.width; }
|
|
||||||
|
|
||||||
inline float GetBottom() const { return origin.y + size.height; }
|
|
||||||
|
|
||||||
// 判断点是否在矩形内
|
|
||||||
inline bool ContainsPoint(const Point& point) const
|
|
||||||
{
|
|
||||||
return point.x >= origin.x && point.x <= (origin.y + size.height) &&
|
|
||||||
point.y >= origin.y && point.y <= (origin.y + size.height);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 判断两矩形是否相交
|
|
||||||
inline bool Intersects(const Rect& rect) const
|
|
||||||
{
|
|
||||||
return !((origin.x + size.width) < rect.origin.x ||
|
|
||||||
(rect.origin.x + rect.size.width) < origin.x ||
|
|
||||||
(origin.y + size.height) < rect.origin.y ||
|
|
||||||
(rect.origin.y + rect.size.height) < origin.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline operator D2D1_RECT_F () const
|
|
||||||
{
|
|
||||||
return D2D1_RECT_F{ origin.x, origin.y, origin.x + size.width, origin.y + size.height };
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,109 +0,0 @@
|
||||||
// Copyright (c) 2016-2018 Easy2D - Nomango
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
// THE SOFTWARE.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include "Point.hpp"
|
|
||||||
#include <d2d1.h>
|
|
||||||
|
|
||||||
namespace easy2d
|
|
||||||
{
|
|
||||||
// 大小
|
|
||||||
//
|
|
||||||
// Usage:
|
|
||||||
// 表示一个二维矩形区域的大小: Size s(10, 5); // 宽为 10, 高为 5
|
|
||||||
// 大小可以相加减: Size s = Size(10, 10) + Size(20, 20); // s 的大小是宽高均为 30
|
|
||||||
//
|
|
||||||
class Size
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
float width; // 宽度
|
|
||||||
float height; // 高度
|
|
||||||
|
|
||||||
public:
|
|
||||||
Size()
|
|
||||||
{
|
|
||||||
width = 0;
|
|
||||||
height = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Size(float width, float height)
|
|
||||||
{
|
|
||||||
this->width = width;
|
|
||||||
this->height = height;
|
|
||||||
}
|
|
||||||
|
|
||||||
Size(const Size & other)
|
|
||||||
{
|
|
||||||
width = other.width;
|
|
||||||
height = other.height;
|
|
||||||
}
|
|
||||||
|
|
||||||
Size(const Point & p)
|
|
||||||
{
|
|
||||||
width = p.x;
|
|
||||||
height = p.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const Size operator+(const Size & other) const
|
|
||||||
{
|
|
||||||
return Size(width + other.width, height + other.height);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const Size operator-(const Size & other) const
|
|
||||||
{
|
|
||||||
return Size(width - other.width, height - other.height);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const Size operator*(float val) const
|
|
||||||
{
|
|
||||||
return Size(width * val, height * val);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const Size operator/(float val) const
|
|
||||||
{
|
|
||||||
return Size(width / val, height / val);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const Size operator-() const
|
|
||||||
{
|
|
||||||
return Size(-width, -height);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator==(const Size & other) const
|
|
||||||
{
|
|
||||||
return (width == other.width) && (height == other.height);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline operator Point () const
|
|
||||||
{
|
|
||||||
return Point{ width, height };
|
|
||||||
}
|
|
||||||
|
|
||||||
inline operator D2D1_SIZE_F const& () const
|
|
||||||
{
|
|
||||||
return reinterpret_cast<D2D1_SIZE_F const&>(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline operator D2D1_SIZE_F& ()
|
|
||||||
{
|
|
||||||
return reinterpret_cast<D2D1_SIZE_F&>(*this);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -117,8 +117,8 @@ namespace easy2d
|
||||||
{
|
{
|
||||||
image_->Crop(crop_rect);
|
image_->Crop(crop_rect);
|
||||||
Node::SetSize(
|
Node::SetSize(
|
||||||
std::min(std::max(crop_rect.size.width, 0.f), image_->GetSourceWidth() - image_->GetCropX()),
|
std::min(std::max(crop_rect.size.x, 0.f), image_->GetSourceWidth() - image_->GetCropX()),
|
||||||
std::min(std::max(crop_rect.size.height, 0.f), image_->GetSourceHeight() - image_->GetCropY())
|
std::min(std::max(crop_rect.size.y, 0.f), image_->GetSourceHeight() - image_->GetCropY())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,10 +19,7 @@
|
||||||
// THE SOFTWARE.
|
// THE SOFTWARE.
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "Size.hpp"
|
#include "helper.hpp"
|
||||||
#include "Point.hpp"
|
|
||||||
#include "../math/Matrix.hpp"
|
|
||||||
#include <d2d1.h>
|
|
||||||
|
|
||||||
namespace easy2d
|
namespace easy2d
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -161,10 +161,10 @@ namespace easy2d
|
||||||
if (process_ < .5f)
|
if (process_ < .5f)
|
||||||
{
|
{
|
||||||
out_layer_prop_.area = Rect(
|
out_layer_prop_.area = Rect(
|
||||||
window_size_.width * process_,
|
window_size_.x * process_,
|
||||||
window_size_.height * process_,
|
window_size_.y * process_,
|
||||||
window_size_.width * (1 - process_ * 2),
|
window_size_.x * (1 - process_ * 2),
|
||||||
window_size_.height * (1 - process_ * 2)
|
window_size_.y * (1 - process_ * 2)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -172,10 +172,10 @@ namespace easy2d
|
||||||
out_layer_prop_.opacity = 0;
|
out_layer_prop_.opacity = 0;
|
||||||
in_layer_prop_.opacity = 1;
|
in_layer_prop_.opacity = 1;
|
||||||
in_layer_prop_.area = Rect(
|
in_layer_prop_.area = Rect(
|
||||||
window_size_.width * (1 - process_),
|
window_size_.x * (1 - process_),
|
||||||
window_size_.height * (1 - process_),
|
window_size_.y * (1 - process_),
|
||||||
window_size_.width * (2 * process_ - 1),
|
window_size_.x * (2 * process_ - 1),
|
||||||
window_size_.height * (2 * process_ - 1)
|
window_size_.y * (2 * process_ - 1)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -255,20 +255,20 @@ namespace easy2d
|
||||||
switch (direction_)
|
switch (direction_)
|
||||||
{
|
{
|
||||||
case Direction::Up:
|
case Direction::Up:
|
||||||
pos_delta_ = Point(0, -window_size_.height);
|
pos_delta_ = Point(0, -window_size_.y);
|
||||||
start_pos_ = Point(0, window_size_.height);
|
start_pos_ = Point(0, window_size_.y);
|
||||||
break;
|
break;
|
||||||
case Direction::Down:
|
case Direction::Down:
|
||||||
pos_delta_ = Point(0, window_size_.height);
|
pos_delta_ = Point(0, window_size_.y);
|
||||||
start_pos_ = Point(0, -window_size_.height);
|
start_pos_ = Point(0, -window_size_.y);
|
||||||
break;
|
break;
|
||||||
case Direction::Left:
|
case Direction::Left:
|
||||||
pos_delta_ = Point(-window_size_.width, 0);
|
pos_delta_ = Point(-window_size_.x, 0);
|
||||||
start_pos_ = Point(window_size_.width, 0);
|
start_pos_ = Point(window_size_.x, 0);
|
||||||
break;
|
break;
|
||||||
case Direction::Right:
|
case Direction::Right:
|
||||||
pos_delta_ = Point(window_size_.width, 0);
|
pos_delta_ = Point(window_size_.x, 0);
|
||||||
start_pos_ = Point(-window_size_.width, 0);
|
start_pos_ = Point(-window_size_.x, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -332,7 +332,7 @@ namespace easy2d
|
||||||
Transition::Init(prev, next);
|
Transition::Init(prev, next);
|
||||||
|
|
||||||
auto transform = Transform{};
|
auto transform = Transform{};
|
||||||
transform.position = Point{ window_size_.width / 2, window_size_.height / 2 };
|
transform.position = Point{ window_size_.x / 2, window_size_.y / 2 };
|
||||||
|
|
||||||
if (out_scene_)
|
if (out_scene_)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "RefCounter.hpp"
|
#include "RefCounter.hpp"
|
||||||
#include "intrusive/SmartPointer.hpp"
|
#include "intrusive/SmartPointer.hpp"
|
||||||
|
#include "../math/vector.hpp"
|
||||||
|
#include "../math/Rect.hpp"
|
||||||
|
#include "../math/Matrix.hpp"
|
||||||
|
|
||||||
#ifndef E2D_DECLARE_SMART_PTR
|
#ifndef E2D_DECLARE_SMART_PTR
|
||||||
#define E2D_DECLARE_SMART_PTR(class_name)\
|
#define E2D_DECLARE_SMART_PTR(class_name)\
|
||||||
|
|
@ -89,6 +92,11 @@ namespace easy2d
|
||||||
E2D_DECLARE_NS_SMART_PTR(ui, Button);
|
E2D_DECLARE_NS_SMART_PTR(ui, Button);
|
||||||
E2D_DECLARE_NS_SMART_PTR(ui, Menu);
|
E2D_DECLARE_NS_SMART_PTR(ui, Menu);
|
||||||
|
|
||||||
|
using Vector2 = math::Vector2;
|
||||||
|
using Point = math::Vector2;
|
||||||
|
using Size = math::Vector2;
|
||||||
|
using Rect = math::Rect;
|
||||||
|
using Matrix = math::Matrix;
|
||||||
|
|
||||||
template <typename Dest, typename Src>
|
template <typename Dest, typename Src>
|
||||||
inline Dest SafeCast(Src ptr)
|
inline Dest SafeCast(Src ptr)
|
||||||
|
|
|
||||||
|
|
@ -20,9 +20,6 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "macros.h"
|
#include "macros.h"
|
||||||
#include "Point.hpp"
|
|
||||||
#include "Size.hpp"
|
|
||||||
#include "Rect.hpp"
|
|
||||||
#include "Color.h"
|
#include "Color.h"
|
||||||
#include "Object.h"
|
#include "Object.h"
|
||||||
#include "helper.hpp"
|
#include "helper.hpp"
|
||||||
|
|
|
||||||
|
|
@ -249,7 +249,7 @@ namespace easy2d
|
||||||
return text_layout->Draw(nullptr, text_renderer_.Get(), 0, 0);
|
return text_layout->Draw(nullptr, text_renderer_.Get(), 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT GraphicsDevice::PushClip(const math::Matrix & clip_matrix, const Size & clip_size)
|
HRESULT GraphicsDevice::PushClip(const Matrix & clip_matrix, const Size & clip_size)
|
||||||
{
|
{
|
||||||
if (!render_target_)
|
if (!render_target_)
|
||||||
return E_UNEXPECTED;
|
return E_UNEXPECTED;
|
||||||
|
|
@ -259,7 +259,7 @@ namespace easy2d
|
||||||
|
|
||||||
render_target_->SetTransform(clip_matrix);
|
render_target_->SetTransform(clip_matrix);
|
||||||
render_target_->PushAxisAlignedClip(
|
render_target_->PushAxisAlignedClip(
|
||||||
D2D1::RectF(0, 0, clip_size.width, clip_size.height),
|
D2D1::RectF(0, 0, clip_size.x, clip_size.y),
|
||||||
D2D1_ANTIALIAS_MODE_PER_PRIMITIVE
|
D2D1_ANTIALIAS_MODE_PER_PRIMITIVE
|
||||||
);
|
);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
|
@ -319,8 +319,8 @@ namespace easy2d
|
||||||
return E_UNEXPECTED;
|
return E_UNEXPECTED;
|
||||||
|
|
||||||
auto rtsize = render_target_->GetSize();
|
auto rtsize = render_target_->GetSize();
|
||||||
size.width = rtsize.width;
|
size.x = rtsize.width;
|
||||||
size.height = rtsize.height;
|
size.y = rtsize.height;
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -399,7 +399,7 @@ namespace easy2d
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT GraphicsDevice::SetTransform(const math::Matrix & matrix)
|
HRESULT GraphicsDevice::SetTransform(const Matrix & matrix)
|
||||||
{
|
{
|
||||||
if (!render_target_)
|
if (!render_target_)
|
||||||
return E_UNEXPECTED;
|
return E_UNEXPECTED;
|
||||||
|
|
|
||||||
|
|
@ -97,7 +97,7 @@ namespace easy2d
|
||||||
);
|
);
|
||||||
|
|
||||||
HRESULT SetTransform(
|
HRESULT SetTransform(
|
||||||
const math::Matrix& matrix
|
const Matrix& matrix
|
||||||
);
|
);
|
||||||
|
|
||||||
HRESULT SetOpacity(
|
HRESULT SetOpacity(
|
||||||
|
|
@ -137,7 +137,7 @@ namespace easy2d
|
||||||
);
|
);
|
||||||
|
|
||||||
HRESULT PushClip(
|
HRESULT PushClip(
|
||||||
const math::Matrix& clip_matrix,
|
const Matrix& clip_matrix,
|
||||||
const Size& clip_size
|
const Size& clip_size
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -89,8 +89,8 @@ namespace easy2d
|
||||||
WINDOW_STYLE,
|
WINDOW_STYLE,
|
||||||
static_cast<int>(client_rect.origin.x),
|
static_cast<int>(client_rect.origin.x),
|
||||||
static_cast<int>(client_rect.origin.y),
|
static_cast<int>(client_rect.origin.y),
|
||||||
static_cast<int>(client_rect.size.width),
|
static_cast<int>(client_rect.size.x),
|
||||||
static_cast<int>(client_rect.size.height),
|
static_cast<int>(client_rect.size.y),
|
||||||
nullptr,
|
nullptr,
|
||||||
nullptr,
|
nullptr,
|
||||||
hinstance,
|
hinstance,
|
||||||
|
|
@ -138,12 +138,12 @@ namespace easy2d
|
||||||
|
|
||||||
float WindowImpl::GetWidth() const
|
float WindowImpl::GetWidth() const
|
||||||
{
|
{
|
||||||
return GetSize().width;
|
return GetSize().x;
|
||||||
}
|
}
|
||||||
|
|
||||||
float WindowImpl::GetHeight() const
|
float WindowImpl::GetHeight() const
|
||||||
{
|
{
|
||||||
return GetSize().height;
|
return GetSize().y;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowImpl::SetSize(int width, int height)
|
void WindowImpl::SetSize(int width, int height)
|
||||||
|
|
@ -155,8 +155,8 @@ namespace easy2d
|
||||||
handle,
|
handle,
|
||||||
static_cast<int>(rect.origin.x),
|
static_cast<int>(rect.origin.x),
|
||||||
static_cast<int>(rect.origin.y),
|
static_cast<int>(rect.origin.y),
|
||||||
static_cast<int>(rect.size.width),
|
static_cast<int>(rect.size.x),
|
||||||
static_cast<int>(rect.size.height),
|
static_cast<int>(rect.size.y),
|
||||||
TRUE
|
TRUE
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,9 +39,6 @@
|
||||||
#include "base/time.h"
|
#include "base/time.h"
|
||||||
#include "base/logs.h"
|
#include "base/logs.h"
|
||||||
|
|
||||||
#include "base/Point.hpp"
|
|
||||||
#include "base/Size.hpp"
|
|
||||||
#include "base/Rect.hpp"
|
|
||||||
#include "base/Font.hpp"
|
#include "base/Font.hpp"
|
||||||
#include "base/Color.h"
|
#include "base/Color.h"
|
||||||
#include "base/Resource.h"
|
#include "base/Resource.h"
|
||||||
|
|
|
||||||
|
|
@ -123,6 +123,11 @@ namespace easy2d
|
||||||
_31 == 0.f && _32 == 0.f;
|
_31 == 0.f && _32 == 0.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool IsInvertible() const
|
||||||
|
{
|
||||||
|
return 0 != Determinant();
|
||||||
|
}
|
||||||
|
|
||||||
Vector2 Transform(const Vector2& v) const
|
Vector2 Transform(const Vector2& v) const
|
||||||
{
|
{
|
||||||
return Vector2(
|
return Vector2(
|
||||||
|
|
@ -210,6 +215,20 @@ namespace easy2d
|
||||||
center.y * tx, center.x * ty
|
center.y * tx, center.x * ty
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Matrix Invert(Matrix const& matrix)
|
||||||
|
{
|
||||||
|
float det = 1.f / matrix.Determinant();
|
||||||
|
|
||||||
|
return Matrix(
|
||||||
|
det * matrix._22,
|
||||||
|
-det * matrix._12,
|
||||||
|
-det * matrix._21,
|
||||||
|
det * matrix._11,
|
||||||
|
det * (matrix._21 * matrix._32 - matrix._22 * matrix._31),
|
||||||
|
det * (matrix._12 * matrix._31 - matrix._11 * matrix._32)
|
||||||
|
);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,130 @@
|
||||||
|
// Copyright (c) 2016-2018 Easy2D - Nomango
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "vector.hpp"
|
||||||
|
#include <d2d1.h>
|
||||||
|
|
||||||
|
namespace easy2d
|
||||||
|
{
|
||||||
|
namespace math
|
||||||
|
{
|
||||||
|
// 矩形
|
||||||
|
//
|
||||||
|
// Usage:
|
||||||
|
// 表示一个二维矩形: Rect rect = Rect(10, 20, 30, 40); // 左上角坐标为 (10, 20), 宽为 30, 高为 40
|
||||||
|
// 矩形可以通过 Vector2 + Vector2 定义, Vector2 表示矩形左上角坐标, Vector2 表示矩形宽高
|
||||||
|
// 判断一个点是否在矩形内: bool contains = rect.ContainsPoint(p);
|
||||||
|
// 判断两矩形是否相交: bool intersects = rect1.Intersects(rect2);
|
||||||
|
//
|
||||||
|
class Rect
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Vector2 origin; // 左上角坐标
|
||||||
|
Vector2 size; // 宽度和高度
|
||||||
|
|
||||||
|
public:
|
||||||
|
Rect() {}
|
||||||
|
|
||||||
|
Rect(
|
||||||
|
float x,
|
||||||
|
float y,
|
||||||
|
float width,
|
||||||
|
float height
|
||||||
|
)
|
||||||
|
: origin(x, y)
|
||||||
|
, size(width, height)
|
||||||
|
{}
|
||||||
|
|
||||||
|
Rect(
|
||||||
|
const Vector2& pos,
|
||||||
|
const Vector2& size
|
||||||
|
)
|
||||||
|
: origin(pos.x, pos.y)
|
||||||
|
, size(size.x, size.y)
|
||||||
|
{}
|
||||||
|
|
||||||
|
Rect(
|
||||||
|
const Rect& other
|
||||||
|
)
|
||||||
|
: origin(other.origin.x, other.origin.y)
|
||||||
|
, size(other.size.x, other.size.y)
|
||||||
|
{}
|
||||||
|
|
||||||
|
Rect(
|
||||||
|
const D2D1_RECT_F& other
|
||||||
|
)
|
||||||
|
: origin(other.left, other.top)
|
||||||
|
, size(other.right - other.left, other.bottom - other.top)
|
||||||
|
{}
|
||||||
|
|
||||||
|
Rect& operator= (const Rect& other)
|
||||||
|
{
|
||||||
|
origin = other.origin;
|
||||||
|
size = other.size;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator== (const Rect& rect) const
|
||||||
|
{
|
||||||
|
return (origin == rect.origin) && (size == rect.size);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Vector2 GetCenter() const { return Vector2{ origin.x + size.x / 2, origin.y + size.y / 2 }; }
|
||||||
|
|
||||||
|
inline Vector2 GetLeftTop() const { return origin; }
|
||||||
|
|
||||||
|
inline Vector2 GetRightBottom() const { return Vector2{ GetRight(), GetBottom() }; }
|
||||||
|
|
||||||
|
inline Vector2 GetRightTop() const { return Vector2{ GetRight(), GetTop() }; }
|
||||||
|
|
||||||
|
inline Vector2 GetLeftBottom() const { return Vector2{ GetLeft(), GetBottom() }; }
|
||||||
|
|
||||||
|
inline float GetLeft() const { return origin.x; }
|
||||||
|
|
||||||
|
inline float GetTop() const { return origin.y; }
|
||||||
|
|
||||||
|
inline float GetRight() const { return origin.x + size.x; }
|
||||||
|
|
||||||
|
inline float GetBottom() const { return origin.y + size.y; }
|
||||||
|
|
||||||
|
// 判断点是否在矩形内
|
||||||
|
inline bool ContainsPoint(const Vector2& point) const
|
||||||
|
{
|
||||||
|
return point.x >= origin.x && point.x <= (origin.y + size.y) &&
|
||||||
|
point.y >= origin.y && point.y <= (origin.y + size.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断两矩形是否相交
|
||||||
|
inline bool Intersects(const Rect& rect) const
|
||||||
|
{
|
||||||
|
return !((origin.x + size.x) < rect.origin.x ||
|
||||||
|
(rect.origin.x + rect.size.x) < origin.x ||
|
||||||
|
(origin.y + size.y) < rect.origin.y ||
|
||||||
|
(rect.origin.y + rect.size.y) < origin.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline operator D2D1_RECT_F () const
|
||||||
|
{
|
||||||
|
return D2D1_RECT_F{ origin.x, origin.y, origin.x + size.x, origin.y + size.y };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "scalar.hpp"
|
#include "scalar.hpp"
|
||||||
|
#include <d2d1.h>
|
||||||
|
|
||||||
namespace easy2d
|
namespace easy2d
|
||||||
{
|
{
|
||||||
|
|
@ -34,20 +35,9 @@ namespace easy2d
|
||||||
public:
|
public:
|
||||||
Vector2() : x(0.f), y(0.f) {}
|
Vector2() : x(0.f), y(0.f) {}
|
||||||
|
|
||||||
Vector2(
|
Vector2(float x, float y) : x(x), y(y) {}
|
||||||
float x,
|
|
||||||
float y
|
|
||||||
)
|
|
||||||
: x(x)
|
|
||||||
, y(y)
|
|
||||||
{}
|
|
||||||
|
|
||||||
Vector2(
|
Vector2(const Vector2& other) : x(other.x), y(other.y) {}
|
||||||
const Vector2& other
|
|
||||||
)
|
|
||||||
: x(other.x)
|
|
||||||
, y(other.y)
|
|
||||||
{}
|
|
||||||
|
|
||||||
inline float Length() const
|
inline float Length() const
|
||||||
{
|
{
|
||||||
|
|
@ -83,6 +73,16 @@ namespace easy2d
|
||||||
{
|
{
|
||||||
return (x == other.x) && (y == other.y);
|
return (x == other.x) && (y == other.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline operator D2D1_POINT_2F const& () const
|
||||||
|
{
|
||||||
|
return reinterpret_cast<D2D1_POINT_2F const&>(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline operator D2D1_POINT_2F& ()
|
||||||
|
{
|
||||||
|
return reinterpret_cast<D2D1_POINT_2F&>(*this);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -21,98 +21,26 @@
|
||||||
#include "Button.h"
|
#include "Button.h"
|
||||||
#include "../base/MouseEvent.hpp"
|
#include "../base/MouseEvent.hpp"
|
||||||
|
|
||||||
#define SAFE_SET(pointer, func, ...) if (pointer) { pointer->##func(__VA_ARGS__); }
|
|
||||||
|
|
||||||
#define SET_BUTTON_NODE(Old, New) \
|
|
||||||
if (New != Old) \
|
|
||||||
{ \
|
|
||||||
if (Old) this->RemoveChild(Old); \
|
|
||||||
if (New) \
|
|
||||||
{ \
|
|
||||||
New->SetPivot(GetPivotX(), GetPivotY()); \
|
|
||||||
this->AddChild(New); \
|
|
||||||
} \
|
|
||||||
Old = New; \
|
|
||||||
UpdateVisible(); \
|
|
||||||
} \
|
|
||||||
|
|
||||||
|
|
||||||
namespace easy2d
|
namespace easy2d
|
||||||
{
|
{
|
||||||
namespace ui
|
namespace ui
|
||||||
{
|
{
|
||||||
Button::Button()
|
Button::Button()
|
||||||
: callback_(nullptr)
|
: enabled_(true)
|
||||||
, status_(Status::Normal)
|
|
||||||
, enabled_(true)
|
|
||||||
, is_selected_(false)
|
, is_selected_(false)
|
||||||
, normal_(nullptr)
|
, callback_(nullptr)
|
||||||
, mouseover_(nullptr)
|
, status_(Status::Normal)
|
||||||
, selected_(nullptr)
|
|
||||||
, disabled_(nullptr)
|
|
||||||
{
|
{
|
||||||
|
AddListener(MouseEvent::Hover, std::bind(&Button::UpdateStatus, this, std::placeholders::_1));
|
||||||
|
AddListener(MouseEvent::Out, std::bind(&Button::UpdateStatus, this, std::placeholders::_1));
|
||||||
|
AddListener(MouseEvent::Down, std::bind(&Button::UpdateStatus, this, std::placeholders::_1));
|
||||||
|
AddListener(MouseEvent::Up, std::bind(&Button::UpdateStatus, this, std::placeholders::_1));
|
||||||
}
|
}
|
||||||
|
|
||||||
Button::Button(spNode const& normal, const Callback& func)
|
Button::Button(const Callback& func)
|
||||||
: callback_(nullptr)
|
: Button()
|
||||||
, status_(Status::Normal)
|
|
||||||
, enabled_(true)
|
|
||||||
, is_selected_(false)
|
|
||||||
, normal_(nullptr)
|
|
||||||
, mouseover_(nullptr)
|
|
||||||
, selected_(nullptr)
|
|
||||||
, disabled_(nullptr)
|
|
||||||
{
|
{
|
||||||
this->SetNormal(normal);
|
this->SetClickCallback(func);
|
||||||
this->SetCallbackOnClick(func);
|
|
||||||
}
|
|
||||||
|
|
||||||
Button::Button(spNode const& normal, spNode const& selected, const Callback& func)
|
|
||||||
: callback_(nullptr)
|
|
||||||
, status_(Status::Normal)
|
|
||||||
, enabled_(true)
|
|
||||||
, is_selected_(false)
|
|
||||||
, normal_(nullptr)
|
|
||||||
, mouseover_(nullptr)
|
|
||||||
, selected_(nullptr)
|
|
||||||
, disabled_(nullptr)
|
|
||||||
{
|
|
||||||
this->SetNormal(normal);
|
|
||||||
this->SetSelected(selected);
|
|
||||||
this->SetCallbackOnClick(func);
|
|
||||||
}
|
|
||||||
|
|
||||||
Button::Button(spNode const& normal, spNode const& mouseover, spNode const& selected, const Callback& func)
|
|
||||||
: callback_(nullptr)
|
|
||||||
, status_(Status::Normal)
|
|
||||||
, enabled_(true)
|
|
||||||
, is_selected_(false)
|
|
||||||
, normal_(nullptr)
|
|
||||||
, mouseover_(nullptr)
|
|
||||||
, selected_(nullptr)
|
|
||||||
, disabled_(nullptr)
|
|
||||||
{
|
|
||||||
this->SetNormal(normal);
|
|
||||||
this->SetMouseOver(mouseover);
|
|
||||||
this->SetSelected(selected);
|
|
||||||
this->SetCallbackOnClick(func);
|
|
||||||
}
|
|
||||||
|
|
||||||
Button::Button(spNode const& normal, spNode const& mouseover, spNode const& selected, spNode const& disabled, const Callback& func)
|
|
||||||
: callback_(nullptr)
|
|
||||||
, status_(Status::Normal)
|
|
||||||
, enabled_(true)
|
|
||||||
, is_selected_(false)
|
|
||||||
, normal_(nullptr)
|
|
||||||
, mouseover_(nullptr)
|
|
||||||
, selected_(nullptr)
|
|
||||||
, disabled_(nullptr)
|
|
||||||
{
|
|
||||||
this->SetNormal(normal);
|
|
||||||
this->SetMouseOver(mouseover);
|
|
||||||
this->SetSelected(selected);
|
|
||||||
this->SetDisabled(disabled);
|
|
||||||
this->SetCallbackOnClick(func);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Button::~Button()
|
Button::~Button()
|
||||||
|
|
@ -124,146 +52,55 @@ namespace easy2d
|
||||||
return enabled_;
|
return enabled_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Button::SetNormal(spNode const& normal)
|
|
||||||
{
|
|
||||||
SET_BUTTON_NODE(normal_, normal);
|
|
||||||
if (normal)
|
|
||||||
{
|
|
||||||
this->SetSize(normal->GetWidth(), normal->GetHeight());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Button::SetMouseOver(spNode const& mouseover)
|
|
||||||
{
|
|
||||||
SET_BUTTON_NODE(mouseover_, mouseover);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Button::SetSelected(spNode const& selected)
|
|
||||||
{
|
|
||||||
SET_BUTTON_NODE(selected_, selected);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Button::SetDisabled(spNode const& disabled)
|
|
||||||
{
|
|
||||||
SET_BUTTON_NODE(disabled_, disabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Button::SetEnabled(bool enabled)
|
void Button::SetEnabled(bool enabled)
|
||||||
{
|
{
|
||||||
if (enabled_ != enabled)
|
if (enabled_ != enabled)
|
||||||
{
|
{
|
||||||
enabled_ = enabled;
|
enabled_ = enabled;
|
||||||
UpdateVisible();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Button::SetCallbackOnClick(const Callback& func)
|
void Button::SetClickCallback(const Callback& func)
|
||||||
{
|
{
|
||||||
callback_ = func;
|
callback_ = func;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Button::SetPivot(float pivot_x, float pivot_y)
|
|
||||||
{
|
|
||||||
Node::SetPivot(pivot_x, pivot_y);
|
|
||||||
SAFE_SET(normal_, SetPivot, pivot_x, pivot_y);
|
|
||||||
SAFE_SET(mouseover_, SetPivot, pivot_x, pivot_y);
|
|
||||||
SAFE_SET(selected_, SetPivot, pivot_x, pivot_y);
|
|
||||||
SAFE_SET(disabled_, SetPivot, pivot_x, pivot_y);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Button::HandleEvent(Event* e)
|
|
||||||
{
|
|
||||||
if (e && MouseEvent::Check(e) && !e->has_target)
|
|
||||||
{
|
|
||||||
MouseEvent* me = static_cast<MouseEvent*>(e);
|
|
||||||
if (enabled_ && IsVisible() && normal_)
|
|
||||||
{
|
|
||||||
bool contains = normal_->ContainsPoint(Point{ me->x, me->y });
|
|
||||||
if (me->type == MouseEvent::Up && is_selected_ && contains)
|
|
||||||
{
|
|
||||||
if (callback_)
|
|
||||||
{
|
|
||||||
callback_();
|
|
||||||
}
|
|
||||||
is_selected_ = false;
|
|
||||||
SetStatus(Status::Normal);
|
|
||||||
me->has_target = true;
|
|
||||||
}
|
|
||||||
else if (me->type == MouseEvent::Down)
|
|
||||||
{
|
|
||||||
is_selected_ = contains;
|
|
||||||
SetStatus(contains ? Status::Selected : Status::Normal);
|
|
||||||
|
|
||||||
me->has_target = contains;
|
|
||||||
}
|
|
||||||
else if (me->type == MouseEvent::Up)
|
|
||||||
{
|
|
||||||
is_selected_ = false;
|
|
||||||
}
|
|
||||||
else if (me->type == MouseEvent::Move && is_selected_ && contains)
|
|
||||||
{
|
|
||||||
SetStatus(Status::Selected);
|
|
||||||
me->has_target = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!me->button_down && is_selected_)
|
|
||||||
{
|
|
||||||
is_selected_ = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
SetStatus(contains ? Status::Mouseover : Status::Normal);
|
|
||||||
|
|
||||||
me->has_target = contains;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Node::HandleEvent(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Button::SetStatus(Status status)
|
void Button::SetStatus(Status status)
|
||||||
{
|
{
|
||||||
if (status_ != status)
|
if (status_ != status)
|
||||||
{
|
{
|
||||||
status_ = status;
|
status_ = status;
|
||||||
UpdateVisible();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Button::UpdateVisible()
|
void Button::UpdateStatus(Event * e)
|
||||||
{
|
{
|
||||||
SAFE_SET(normal_, SetVisible, false);
|
E2D_ASSERT(MouseEvent::Check(e));
|
||||||
SAFE_SET(mouseover_, SetVisible, false);
|
|
||||||
SAFE_SET(selected_, SetVisible, false);
|
|
||||||
SAFE_SET(disabled_, SetVisible, false);
|
|
||||||
|
|
||||||
|
MouseEvent* me = static_cast<MouseEvent*>(e);
|
||||||
if (enabled_)
|
if (enabled_)
|
||||||
{
|
{
|
||||||
if (status_ == Status::Selected && selected_)
|
if (me->type == MouseEvent::Hover)
|
||||||
{
|
{
|
||||||
selected_->SetVisible(true);
|
SetStatus(Status::Hover);
|
||||||
}
|
}
|
||||||
else if (status_ == Status::Mouseover && mouseover_)
|
else if (me->type == MouseEvent::Out)
|
||||||
{
|
{
|
||||||
mouseover_->SetVisible(true);
|
SetStatus(Status::Normal);
|
||||||
}
|
}
|
||||||
else
|
else if (me->type == MouseEvent::Down && status_ == Status::Hover)
|
||||||
{
|
{
|
||||||
if (normal_) normal_->SetVisible(true);
|
SetStatus(Status::Selected);
|
||||||
}
|
}
|
||||||
}
|
else if (me->type == MouseEvent::Up && status_ == Status::Selected)
|
||||||
else
|
|
||||||
{
|
|
||||||
if (disabled_)
|
|
||||||
{
|
{
|
||||||
disabled_->SetVisible(true);
|
SetStatus(Status::Hover);
|
||||||
}
|
|
||||||
else
|
if (callback_)
|
||||||
{
|
callback_();
|
||||||
if (normal_) normal_->SetVisible(true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
// THE SOFTWARE.
|
// THE SOFTWARE.
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "../base/Node.h"
|
#include "../base/Sprite.h"
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
namespace easy2d
|
namespace easy2d
|
||||||
|
|
@ -27,7 +27,7 @@ namespace easy2d
|
||||||
namespace ui
|
namespace ui
|
||||||
{
|
{
|
||||||
class Button
|
class Button
|
||||||
: public Node
|
: public Sprite
|
||||||
{
|
{
|
||||||
using Callback = std::function<void()>;
|
using Callback = std::function<void()>;
|
||||||
|
|
||||||
|
|
@ -35,29 +35,7 @@ namespace easy2d
|
||||||
Button();
|
Button();
|
||||||
|
|
||||||
explicit Button(
|
explicit Button(
|
||||||
spNode const& normal, /* 普通状态 */
|
Callback const& func /* 按钮回调函数 */
|
||||||
const Callback& func = nullptr /* 按钮点击后的回调函数 */
|
|
||||||
);
|
|
||||||
|
|
||||||
explicit Button(
|
|
||||||
spNode const& normal, /* 普通状态 */
|
|
||||||
spNode const& selected, /* 鼠标按下状态 */
|
|
||||||
const Callback& func = nullptr /* 按钮点击后的回调函数 */
|
|
||||||
);
|
|
||||||
|
|
||||||
explicit Button(
|
|
||||||
spNode const& normal, /* 普通状态 */
|
|
||||||
spNode const& mouseover, /* 鼠标移入状态 */
|
|
||||||
spNode const& selected, /* 鼠标按下状态 */
|
|
||||||
const Callback& func = nullptr /* 按钮点击后的回调函数 */
|
|
||||||
);
|
|
||||||
|
|
||||||
explicit Button(
|
|
||||||
spNode const& normal, /* 普通状态 */
|
|
||||||
spNode const& mouseover, /* 鼠标移入状态 */
|
|
||||||
spNode const& selected, /* 鼠标移入状态 */
|
|
||||||
spNode const& disabled, /* 按钮禁用状态 */
|
|
||||||
const Callback& func = nullptr /* 按钮点击后的回调函数 */
|
|
||||||
);
|
);
|
||||||
|
|
||||||
virtual ~Button();
|
virtual ~Button();
|
||||||
|
|
@ -70,57 +48,21 @@ namespace easy2d
|
||||||
bool enabled
|
bool enabled
|
||||||
);
|
);
|
||||||
|
|
||||||
// 设置一般情况下显示的按钮
|
|
||||||
void SetNormal(
|
|
||||||
spNode const& normal
|
|
||||||
);
|
|
||||||
|
|
||||||
// 设置鼠标移入按钮时显示的按钮
|
|
||||||
void SetMouseOver(
|
|
||||||
spNode const& mouseover
|
|
||||||
);
|
|
||||||
|
|
||||||
// 设置鼠标按下按钮时显示的按钮
|
|
||||||
void SetSelected(
|
|
||||||
spNode const& selected
|
|
||||||
);
|
|
||||||
|
|
||||||
// 设置按钮被禁用时显示的按钮
|
|
||||||
void SetDisabled(
|
|
||||||
spNode const& disabled
|
|
||||||
);
|
|
||||||
|
|
||||||
// 设置按钮点击后的回调函数
|
// 设置按钮点击后的回调函数
|
||||||
void SetCallbackOnClick(
|
void SetClickCallback(
|
||||||
const Callback& func
|
const Callback& func
|
||||||
);
|
);
|
||||||
|
|
||||||
// 设置支点位置
|
|
||||||
// 默认为 (0, 0), 范围 [0, 1]
|
|
||||||
virtual void SetPivot(
|
|
||||||
float pivot_x,
|
|
||||||
float pivot_y
|
|
||||||
) override;
|
|
||||||
|
|
||||||
virtual void HandleEvent(Event* e) override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// 按钮状态枚举
|
enum class Status { Normal, Hover, Selected };
|
||||||
enum class Status { Normal, Mouseover, Selected };
|
|
||||||
|
|
||||||
// 设置按钮状态
|
void SetStatus(
|
||||||
virtual void SetStatus(
|
|
||||||
Status status
|
Status status
|
||||||
);
|
);
|
||||||
|
|
||||||
// 刷新按钮显示
|
void UpdateStatus(Event* e);
|
||||||
virtual void UpdateVisible();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
spNode normal_;
|
|
||||||
spNode mouseover_;
|
|
||||||
spNode selected_;
|
|
||||||
spNode disabled_;
|
|
||||||
bool enabled_;
|
bool enabled_;
|
||||||
bool is_selected_;
|
bool is_selected_;
|
||||||
Status status_;
|
Status status_;
|
||||||
|
|
|
||||||
|
|
@ -55,14 +55,11 @@
|
||||||
<ClInclude Include="..\..\core\base\Node.h" />
|
<ClInclude Include="..\..\core\base\Node.h" />
|
||||||
<ClInclude Include="..\..\core\base\noncopyable.hpp" />
|
<ClInclude Include="..\..\core\base\noncopyable.hpp" />
|
||||||
<ClInclude Include="..\..\core\base\Object.h" />
|
<ClInclude Include="..\..\core\base\Object.h" />
|
||||||
<ClInclude Include="..\..\core\base\Point.hpp" />
|
|
||||||
<ClInclude Include="..\..\core\base\Rect.hpp" />
|
|
||||||
<ClInclude Include="..\..\core\base\RefCounter.hpp" />
|
<ClInclude Include="..\..\core\base\RefCounter.hpp" />
|
||||||
<ClInclude Include="..\..\core\base\render.h" />
|
<ClInclude Include="..\..\core\base\render.h" />
|
||||||
<ClInclude Include="..\..\core\base\Resource.h" />
|
<ClInclude Include="..\..\core\base\Resource.h" />
|
||||||
<ClInclude Include="..\..\core\base\Scene.h" />
|
<ClInclude Include="..\..\core\base\Scene.h" />
|
||||||
<ClInclude Include="..\..\core\base\Singleton.hpp" />
|
<ClInclude Include="..\..\core\base\Singleton.hpp" />
|
||||||
<ClInclude Include="..\..\core\base\Size.hpp" />
|
|
||||||
<ClInclude Include="..\..\core\base\Sprite.h" />
|
<ClInclude Include="..\..\core\base\Sprite.h" />
|
||||||
<ClInclude Include="..\..\core\base\Task.h" />
|
<ClInclude Include="..\..\core\base\Task.h" />
|
||||||
<ClInclude Include="..\..\core\base\TaskManager.h" />
|
<ClInclude Include="..\..\core\base\TaskManager.h" />
|
||||||
|
|
@ -78,6 +75,7 @@
|
||||||
<ClInclude Include="..\..\core\math\ease.hpp" />
|
<ClInclude Include="..\..\core\math\ease.hpp" />
|
||||||
<ClInclude Include="..\..\core\math\Matrix.hpp" />
|
<ClInclude Include="..\..\core\math\Matrix.hpp" />
|
||||||
<ClInclude Include="..\..\core\math\rand.h" />
|
<ClInclude Include="..\..\core\math\rand.h" />
|
||||||
|
<ClInclude Include="..\..\core\math\Rect.hpp" />
|
||||||
<ClInclude Include="..\..\core\math\scalar.hpp" />
|
<ClInclude Include="..\..\core\math\scalar.hpp" />
|
||||||
<ClInclude Include="..\..\core\math\vector.hpp" />
|
<ClInclude Include="..\..\core\math\vector.hpp" />
|
||||||
<ClInclude Include="..\..\core\ui\Button.h" />
|
<ClInclude Include="..\..\core\ui\Button.h" />
|
||||||
|
|
|
||||||
|
|
@ -38,9 +38,6 @@
|
||||||
<ClInclude Include="..\..\core\base\Node.h">
|
<ClInclude Include="..\..\core\base\Node.h">
|
||||||
<Filter>base</Filter>
|
<Filter>base</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\core\base\Rect.hpp">
|
|
||||||
<Filter>base</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\..\core\base\render.h">
|
<ClInclude Include="..\..\core\base\render.h">
|
||||||
<Filter>base</Filter>
|
<Filter>base</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
|
@ -137,12 +134,6 @@
|
||||||
<ClInclude Include="..\..\core\base\Transform.hpp">
|
<ClInclude Include="..\..\core\base\Transform.hpp">
|
||||||
<Filter>base</Filter>
|
<Filter>base</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\core\base\Point.hpp">
|
|
||||||
<Filter>base</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\..\core\base\Size.hpp">
|
|
||||||
<Filter>base</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\..\core\base\noncopyable.hpp">
|
<ClInclude Include="..\..\core\base\noncopyable.hpp">
|
||||||
<Filter>base</Filter>
|
<Filter>base</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
|
@ -206,6 +197,9 @@
|
||||||
<ClInclude Include="..\..\core\base\DebugNode.h">
|
<ClInclude Include="..\..\core\base\DebugNode.h">
|
||||||
<Filter>base</Filter>
|
<Filter>base</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\core\math\Rect.hpp">
|
||||||
|
<Filter>math</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Filter Include="base">
|
<Filter Include="base">
|
||||||
|
|
|
||||||
|
|
@ -55,14 +55,11 @@
|
||||||
<ClInclude Include="..\..\core\base\Node.h" />
|
<ClInclude Include="..\..\core\base\Node.h" />
|
||||||
<ClInclude Include="..\..\core\base\noncopyable.hpp" />
|
<ClInclude Include="..\..\core\base\noncopyable.hpp" />
|
||||||
<ClInclude Include="..\..\core\base\Object.h" />
|
<ClInclude Include="..\..\core\base\Object.h" />
|
||||||
<ClInclude Include="..\..\core\base\Point.hpp" />
|
|
||||||
<ClInclude Include="..\..\core\base\Rect.hpp" />
|
|
||||||
<ClInclude Include="..\..\core\base\RefCounter.hpp" />
|
<ClInclude Include="..\..\core\base\RefCounter.hpp" />
|
||||||
<ClInclude Include="..\..\core\base\render.h" />
|
<ClInclude Include="..\..\core\base\render.h" />
|
||||||
<ClInclude Include="..\..\core\base\Resource.h" />
|
<ClInclude Include="..\..\core\base\Resource.h" />
|
||||||
<ClInclude Include="..\..\core\base\Scene.h" />
|
<ClInclude Include="..\..\core\base\Scene.h" />
|
||||||
<ClInclude Include="..\..\core\base\Singleton.hpp" />
|
<ClInclude Include="..\..\core\base\Singleton.hpp" />
|
||||||
<ClInclude Include="..\..\core\base\Size.hpp" />
|
|
||||||
<ClInclude Include="..\..\core\base\Sprite.h" />
|
<ClInclude Include="..\..\core\base\Sprite.h" />
|
||||||
<ClInclude Include="..\..\core\base\Task.h" />
|
<ClInclude Include="..\..\core\base\Task.h" />
|
||||||
<ClInclude Include="..\..\core\base\TaskManager.h" />
|
<ClInclude Include="..\..\core\base\TaskManager.h" />
|
||||||
|
|
@ -78,6 +75,7 @@
|
||||||
<ClInclude Include="..\..\core\math\ease.hpp" />
|
<ClInclude Include="..\..\core\math\ease.hpp" />
|
||||||
<ClInclude Include="..\..\core\math\Matrix.hpp" />
|
<ClInclude Include="..\..\core\math\Matrix.hpp" />
|
||||||
<ClInclude Include="..\..\core\math\rand.h" />
|
<ClInclude Include="..\..\core\math\rand.h" />
|
||||||
|
<ClInclude Include="..\..\core\math\Rect.hpp" />
|
||||||
<ClInclude Include="..\..\core\math\scalar.hpp" />
|
<ClInclude Include="..\..\core\math\scalar.hpp" />
|
||||||
<ClInclude Include="..\..\core\math\vector.hpp" />
|
<ClInclude Include="..\..\core\math\vector.hpp" />
|
||||||
<ClInclude Include="..\..\core\ui\Button.h" />
|
<ClInclude Include="..\..\core\ui\Button.h" />
|
||||||
|
|
|
||||||
|
|
@ -38,9 +38,6 @@
|
||||||
<ClInclude Include="..\..\core\base\Node.h">
|
<ClInclude Include="..\..\core\base\Node.h">
|
||||||
<Filter>base</Filter>
|
<Filter>base</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\core\base\Rect.hpp">
|
|
||||||
<Filter>base</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\..\core\base\render.h">
|
<ClInclude Include="..\..\core\base\render.h">
|
||||||
<Filter>base</Filter>
|
<Filter>base</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
|
@ -137,12 +134,6 @@
|
||||||
<ClInclude Include="..\..\core\base\Transform.hpp">
|
<ClInclude Include="..\..\core\base\Transform.hpp">
|
||||||
<Filter>base</Filter>
|
<Filter>base</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\core\base\Point.hpp">
|
|
||||||
<Filter>base</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\..\core\base\Size.hpp">
|
|
||||||
<Filter>base</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\..\core\base\noncopyable.hpp">
|
<ClInclude Include="..\..\core\base\noncopyable.hpp">
|
||||||
<Filter>base</Filter>
|
<Filter>base</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
|
@ -206,6 +197,9 @@
|
||||||
<ClInclude Include="..\..\core\base\DebugNode.h">
|
<ClInclude Include="..\..\core\base\DebugNode.h">
|
||||||
<Filter>base</Filter>
|
<Filter>base</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\core\math\Rect.hpp">
|
||||||
|
<Filter>math</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Filter Include="base">
|
<Filter Include="base">
|
||||||
|
|
|
||||||
|
|
@ -55,14 +55,11 @@
|
||||||
<ClInclude Include="..\..\core\base\Node.h" />
|
<ClInclude Include="..\..\core\base\Node.h" />
|
||||||
<ClInclude Include="..\..\core\base\noncopyable.hpp" />
|
<ClInclude Include="..\..\core\base\noncopyable.hpp" />
|
||||||
<ClInclude Include="..\..\core\base\Object.h" />
|
<ClInclude Include="..\..\core\base\Object.h" />
|
||||||
<ClInclude Include="..\..\core\base\Point.hpp" />
|
|
||||||
<ClInclude Include="..\..\core\base\Rect.hpp" />
|
|
||||||
<ClInclude Include="..\..\core\base\RefCounter.hpp" />
|
<ClInclude Include="..\..\core\base\RefCounter.hpp" />
|
||||||
<ClInclude Include="..\..\core\base\render.h" />
|
<ClInclude Include="..\..\core\base\render.h" />
|
||||||
<ClInclude Include="..\..\core\base\Resource.h" />
|
<ClInclude Include="..\..\core\base\Resource.h" />
|
||||||
<ClInclude Include="..\..\core\base\Scene.h" />
|
<ClInclude Include="..\..\core\base\Scene.h" />
|
||||||
<ClInclude Include="..\..\core\base\Singleton.hpp" />
|
<ClInclude Include="..\..\core\base\Singleton.hpp" />
|
||||||
<ClInclude Include="..\..\core\base\Size.hpp" />
|
|
||||||
<ClInclude Include="..\..\core\base\Sprite.h" />
|
<ClInclude Include="..\..\core\base\Sprite.h" />
|
||||||
<ClInclude Include="..\..\core\base\Task.h" />
|
<ClInclude Include="..\..\core\base\Task.h" />
|
||||||
<ClInclude Include="..\..\core\base\TaskManager.h" />
|
<ClInclude Include="..\..\core\base\TaskManager.h" />
|
||||||
|
|
@ -78,6 +75,7 @@
|
||||||
<ClInclude Include="..\..\core\math\ease.hpp" />
|
<ClInclude Include="..\..\core\math\ease.hpp" />
|
||||||
<ClInclude Include="..\..\core\math\Matrix.hpp" />
|
<ClInclude Include="..\..\core\math\Matrix.hpp" />
|
||||||
<ClInclude Include="..\..\core\math\rand.h" />
|
<ClInclude Include="..\..\core\math\rand.h" />
|
||||||
|
<ClInclude Include="..\..\core\math\Rect.hpp" />
|
||||||
<ClInclude Include="..\..\core\math\scalar.hpp" />
|
<ClInclude Include="..\..\core\math\scalar.hpp" />
|
||||||
<ClInclude Include="..\..\core\math\vector.hpp" />
|
<ClInclude Include="..\..\core\math\vector.hpp" />
|
||||||
<ClInclude Include="..\..\core\ui\Button.h" />
|
<ClInclude Include="..\..\core\ui\Button.h" />
|
||||||
|
|
|
||||||
|
|
@ -38,9 +38,6 @@
|
||||||
<ClInclude Include="..\..\core\base\Node.h">
|
<ClInclude Include="..\..\core\base\Node.h">
|
||||||
<Filter>base</Filter>
|
<Filter>base</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\core\base\Rect.hpp">
|
|
||||||
<Filter>base</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\..\core\base\render.h">
|
<ClInclude Include="..\..\core\base\render.h">
|
||||||
<Filter>base</Filter>
|
<Filter>base</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
|
@ -137,12 +134,6 @@
|
||||||
<ClInclude Include="..\..\core\base\Transform.hpp">
|
<ClInclude Include="..\..\core\base\Transform.hpp">
|
||||||
<Filter>base</Filter>
|
<Filter>base</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\core\base\Point.hpp">
|
|
||||||
<Filter>base</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\..\core\base\Size.hpp">
|
|
||||||
<Filter>base</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\..\core\base\noncopyable.hpp">
|
<ClInclude Include="..\..\core\base\noncopyable.hpp">
|
||||||
<Filter>base</Filter>
|
<Filter>base</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
|
@ -206,6 +197,9 @@
|
||||||
<ClInclude Include="..\..\core\base\DebugNode.h">
|
<ClInclude Include="..\..\core\base\DebugNode.h">
|
||||||
<Filter>base</Filter>
|
<Filter>base</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\core\math\Rect.hpp">
|
||||||
|
<Filter>math</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Filter Include="base">
|
<Filter Include="base">
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue