1
0
Fork 0
mirror of https://github.com/AquariaOSE/Aquaria.git synced 2024-11-25 09:44:02 +00:00
Aquaria/BBGE/SplineGrid.cpp
2023-08-25 20:14:30 +02:00

231 lines
5.4 KiB
C++

#include "SplineGrid.h"
#include "RenderBase.h"
#include "Core.h"
#include "RenderGrid.h"
SplineGridCtrlPoint *SplineGridCtrlPoint::movingPoint;
SplineGridCtrlPoint::SplineGridCtrlPoint()
{
setTexture("gui/open-menu");
setWidthHeight(8, 8);
}
SplineGridCtrlPoint::~SplineGridCtrlPoint()
{
}
Vector SplineGridCtrlPoint::getSplinePosition() const
{
SplineGridCtrlPoint *p = (SplineGridCtrlPoint*)getParent();
// always return alpha == 1
// points within the quad result in in -0.5 .. +0.5 on both axes
return Vector(position.x / p->width, position.y / p->height, 1.0f);
}
void SplineGridCtrlPoint::setSplinePosition(Vector pos)
{
SplineGridCtrlPoint *p = (SplineGridCtrlPoint*)getParent();
position.x = pos.x * p->width;
position.y = pos.y * p->height;
}
void SplineGridCtrlPoint::onUpdate(float dt)
{
const bool lmb = core->mouse.buttons.left;
// FIXME: selected point tracking should be done by the parent
Vector cur = core->mouse.position;
// bool wouldpick = isCoordinateInside(cur); // doesn't work
Vector wp = getWorldPosition();
const bool wouldpick = (cur - wp).isLength2DIn(10);
if(wouldpick)
color = Vector(1,0,0);
else
color = Vector(1,1,1);
if(lmb)
{
if(!movingPoint && wouldpick)
{
movingPoint = this;
}
}
else if(movingPoint)
{
movingPoint->color = Vector(1,1,1);
movingPoint = NULL;
}
if(movingPoint == this)
{
SplineGrid *p = (SplineGrid*)getParent();
const Vector parentPos = p->getWorldPosition();
const Vector invscale = Vector(1.0f / p->scale.x, 1.0f / p->scale.y);
Vector newpos = (cur - parentPos) * invscale;
if(position != newpos)
{
position = newpos;
p->recalc();
}
}
}
SplineGrid::SplineGrid()
: wasModified(false), deg(0), pointscale(1)
{
setWidthHeight(128, 128);
renderQuad = true;
renderBorder = true;
}
SplineGrid::~SplineGrid()
{
}
RenderGrid *SplineGrid::resize(size_t w, size_t h, size_t xres, size_t yres, unsigned degx, unsigned degy)
{
size_t oldcpx = bsp.ctrlX();
size_t oldcpy = bsp.ctrlY();
RenderGrid *ret = this->createGrid(xres, yres);
std::vector<SplineGridCtrlPoint*> oldp;
ctrlp.swap(oldp);
ctrlp.resize(w * h);
// move any old points over that fit within the new size
{
const size_t cw = std::min(oldcpx, w);
const size_t ch = std::min(oldcpy, h);
for(size_t y = 0; y < ch; ++y)
for(size_t x = 0; x < cw; ++x)
{
SplineGridCtrlPoint *& ref = oldp[y * oldcpx + x];
ctrlp[y * w + x] = ref;
ref = NULL;
}
}
bsp.resize(w, h, degx, degy);
// kill any excess points
for(size_t i = 0; i < oldp.size(); ++i)
if(oldp[i])
oldp[i]->safeKill();
// extend until all points are there
for(size_t y = 0; y < h; ++y)
for(size_t x = 0; x < w; ++x)
{
SplineGridCtrlPoint *& ref = ctrlp[y * w + x];
if(!ref)
ref = createControlPoint(x, y);
}
recalc();
return ret;
}
void SplineGrid::recalc()
{
exportControlPoints(&bsp.controlpoints[0]);
if(grid)
{
bsp.recalc(grid->data(), grid->width(), grid->height());
wasModified = true;
}
}
void SplineGrid::exportControlPoints(Vector* controlpoints)
{
for(size_t i = 0; i < ctrlp.size(); ++i)
controlpoints[i] = ctrlp[i]->getSplinePosition();
}
void SplineGrid::importControlPoints(const Vector* controlpoints)
{
for(size_t i = 0; i < ctrlp.size(); ++i)
ctrlp[i]->setSplinePosition(controlpoints[i]);
recalc();
}
void SplineGrid::resetControlPoints()
{
bsp.reset();
importControlPoints(&bsp.controlpoints[0]);
}
SplineGridCtrlPoint* SplineGrid::createControlPoint(size_t x, size_t y)
{
const size_t cpx = bsp.ctrlX();
const size_t cpy = bsp.ctrlY();
assert(x < cpx && y < cpy);
const Vector wh(width, height);
const Vector pos01(float(x) / float(cpx-1), float(y) / float(cpy-1));
SplineGridCtrlPoint *cp = new SplineGridCtrlPoint();
cp->position = (pos01 - Vector(0.5f, 0.5f)) * wh;
cp->scale.x = pointscale;
cp->scale.y = pointscale;
this->addChild(cp, PM_POINTER);
return cp;
}
void SplineGrid::onUpdate(float dt)
{
Quad::onUpdate(dt);
}
void SplineGrid::onRender(const RenderState& rs) const
{
Quad::onRender(rs);
glBindTexture(GL_TEXTURE_2D, 0);
const Vector wh2(width * 0.5f, height * 0.5f);
glLineWidth(2);
glColor4f(0.0f, 0.3f, 1.0f, 0.3f);
const size_t cpx = bsp.ctrlX();
const size_t cpy = bsp.ctrlY();
// X axis
for(size_t y = 0; y < cpy; ++y)
{
glBegin(GL_LINE_STRIP);
const SplineGridCtrlPoint * const *row = &ctrlp[y * cpx];
for(size_t x = 0; x < cpx; ++x)
{
const Vector p = row[x]->position;
glVertex2f(p.x, p.y);
}
glEnd();
}
// Y axis
for(size_t x = 0; x < cpx; ++x)
{
glBegin(GL_LINE_STRIP);
for(size_t y = 0; y < cpy; ++y)
{
const Vector p = ctrlp[y * cpx + x]->position;
glVertex2f(p.x, p.y);
}
glEnd();
}
}
void SplineGrid::setPointScale(const float scale)
{
pointscale = scale;
for(size_t i = 0; i < ctrlp.size(); ++i)
{
ctrlp[i]->scale.x = scale;
ctrlp[i]->scale.y = scale;
}
}