151 lines
3.8 KiB
C++
151 lines
3.8 KiB
C++
#include "DirectionSelector.h"
|
|
|
|
namespace ui {
|
|
|
|
DirectionSelector::DirectionSelector(ui::Point position, float radius):
|
|
ui::Component(position, ui::Point(radius * 2, radius * 2)),
|
|
radius(radius),
|
|
maxRadius(radius - (radius / 4)),
|
|
useSnapPoints(false),
|
|
snapPointRadius(0),
|
|
snapPoints(std::vector<ui::Point>()),
|
|
autoReturn(false),
|
|
backgroundColor(ui::Colour(0, 0, 0, 63)),
|
|
foregroundColor(ui::Colour(63, 63, 63, 127)),
|
|
borderColor(ui::Colour(255, 255, 255)),
|
|
snapPointColor(ui::Colour(63, 63, 63, 127)),
|
|
updateCallback(nullptr),
|
|
changeCallback(nullptr),
|
|
mouseDown(false),
|
|
mouseHover(false),
|
|
altDown(false),
|
|
offset(ui::Point(0, 0))
|
|
{
|
|
|
|
}
|
|
|
|
void DirectionSelector::CheckHovering(int x, int y)
|
|
{
|
|
mouseHover = std::hypot((offset.X + radius) - x, (offset.Y + radius) - y) < radius / 4;
|
|
}
|
|
|
|
void DirectionSelector::SetSnapPoints(int newRadius, int points)
|
|
{
|
|
snapPointRadius = newRadius;
|
|
snapPoints.clear();
|
|
snapPoints.push_back(ui::Point(0, 0));
|
|
for (int i = 1; i < points; i++)
|
|
{
|
|
int dist = ((float)i / (float)(points - 1)) * maxRadius;
|
|
snapPoints.push_back(ui::Point(0, dist));
|
|
snapPoints.push_back(ui::Point(0, -1 * dist));
|
|
snapPoints.push_back(ui::Point(-1 * dist, 0));
|
|
snapPoints.push_back(ui::Point(dist, 0));
|
|
}
|
|
useSnapPoints = true;
|
|
}
|
|
|
|
void DirectionSelector::ClearSnapPoints()
|
|
{
|
|
useSnapPoints = false;
|
|
snapPoints.clear();
|
|
}
|
|
|
|
float DirectionSelector::GetXValue()
|
|
{
|
|
return offset.X / maxRadius;
|
|
}
|
|
|
|
float DirectionSelector::GetYValue()
|
|
{
|
|
return offset.Y / maxRadius;
|
|
}
|
|
|
|
float DirectionSelector::GetTotalValue()
|
|
{
|
|
return std::hypot(offset.X, offset.Y) / maxRadius;
|
|
}
|
|
|
|
void DirectionSelector::SetPositionAbs(float absx, float absy)
|
|
{
|
|
SetPosition(absx - radius, absy - radius);
|
|
}
|
|
|
|
void DirectionSelector::SetPosition(float x, float y)
|
|
{
|
|
if (std::hypot(x, y) > maxRadius)
|
|
{
|
|
offset.X = (maxRadius * x) / std::hypot(x, y);
|
|
offset.Y = (maxRadius * y) / std::hypot(x, y);
|
|
}
|
|
else
|
|
{
|
|
offset.X = x;
|
|
offset.Y = y;
|
|
}
|
|
|
|
if (useSnapPoints && !altDown)
|
|
{
|
|
for (const ui::Point& i : snapPoints)
|
|
if (std::hypot(i.X - offset.X, i.Y - offset.Y) <= snapPointRadius)
|
|
{
|
|
offset.X = i.X;
|
|
offset.Y = i.Y;
|
|
}
|
|
}
|
|
if (updateCallback)
|
|
updateCallback(GetXValue(), GetYValue());
|
|
}
|
|
|
|
void DirectionSelector::SetValues(float x, float y)
|
|
{
|
|
SetPosition(x * maxRadius, y * maxRadius);
|
|
}
|
|
|
|
void DirectionSelector::Draw(const ui::Point& screenPos)
|
|
{
|
|
Graphics * g = GetGraphics();
|
|
ui::Point center = screenPos + radius;
|
|
|
|
g->fillcircle(center.X, center.Y, radius, radius, backgroundColor.Red, backgroundColor.Green, backgroundColor.Blue, backgroundColor.Alpha);
|
|
g->drawcircle(center.X, center.Y, radius, radius, borderColor.Red, borderColor.Green, borderColor.Blue, borderColor.Alpha);
|
|
|
|
for (const ui::Point& i : snapPoints)
|
|
g->fillrect(
|
|
(center.X + i.X) - (radius / 30),
|
|
(center.Y + i.Y) - (radius / 30),
|
|
radius / 10, radius / 10,
|
|
snapPointColor.Red, snapPointColor.Green, snapPointColor.Blue, altDown ? (int)(snapPointColor.Alpha / 2) : snapPointColor.Alpha
|
|
);
|
|
|
|
g->fillcircle(center.X + offset.X, center.Y + offset.Y, radius / 4, radius / 4, foregroundColor.Red, foregroundColor.Green, foregroundColor.Blue, mouseHover ? std::min((int)(foregroundColor.Alpha * 1.5f), 255) : foregroundColor.Alpha);
|
|
g->drawcircle(center.X + offset.X, center.Y + offset.Y, radius / 4, radius / 4, borderColor.Red, borderColor.Green, borderColor.Blue, borderColor.Alpha);
|
|
}
|
|
|
|
void DirectionSelector::OnMouseMoved(int x, int y, int dx, int dy)
|
|
{
|
|
if (mouseDown)
|
|
SetPositionAbs(x, y);
|
|
CheckHovering(x, y);
|
|
}
|
|
|
|
void DirectionSelector::OnMouseClick(int x, int y, unsigned button)
|
|
{
|
|
mouseDown = true;
|
|
SetPositionAbs(x, y);
|
|
CheckHovering(x, y);
|
|
}
|
|
|
|
void DirectionSelector::OnMouseUp(int x, int y, unsigned button)
|
|
{
|
|
mouseDown = false;
|
|
if (autoReturn)
|
|
SetPosition(0, 0);
|
|
CheckHovering(x - Position.X, y - Position.Y);
|
|
|
|
if (changeCallback)
|
|
changeCallback(GetXValue(), GetYValue());
|
|
}
|
|
|
|
}
|