diff --git a/Aquaria/AnimationEditor.cpp b/Aquaria/AnimationEditor.cpp index 974d2db..25c18d3 100644 --- a/Aquaria/AnimationEditor.cpp +++ b/Aquaria/AnimationEditor.cpp @@ -240,6 +240,7 @@ void AnimationEditor::applyState() editingBone = 0; currentKey = 0; splinegrid = 0; + assistedSplineEdit = true; editSprite = new SkeletalSprite(); editSprite->cull = false; @@ -302,6 +303,8 @@ void AnimationEditor::applyState() addAction(MakeFunctionEvent(AnimationEditor, decrTimelineGrid), KEY_O, 0); addAction(MakeFunctionEvent(AnimationEditor, incrTimelineGrid), KEY_P, 0); + addAction(MakeFunctionEvent(AnimationEditor, toggleSplineMode), KEY_W, 0); + addAction(ACTION_SWIMLEFT, KEY_J, -1); @@ -462,6 +465,12 @@ void AnimationEditor::applyState() reverseAnim->event.set(MakeFunctionEvent(AnimationEditor, reverseAnim)); addRenderObject(reverseAnim, LR_MENU); + DebugButton *bAssist = new DebugButton(0, 0, 150); + bAssist->position = Vector(10, 510); + bAssist->event.set(MakeFunctionEvent(AnimationEditor, toggleSplineMode)); + addRenderObject(bAssist, LR_MENU); + bSplineAssist = bAssist; + OutlineRect *rect = new OutlineRect; rect->setWidthHeight(400,400); @@ -494,6 +503,7 @@ void AnimationEditor::applyState() updateTimelineGrid(); updateTimelineUnit(); + updateButtonLabels(); } void AnimationEditor::clearUndoHistory() @@ -1010,12 +1020,13 @@ void AnimationEditor::editStripKey() bk->controlpoints.resize(totalcp); assert(!splinegrid); - splinegrid = new SplineGrid; + splinegrid = new SplineGrid(); DynamicRenderGrid *rgrid = splinegrid->resize(interp->bsp.ctrlX(), interp->bsp.ctrlY(), grid->width(), grid->height(), interp->bsp.degX(), interp->bsp.degY()); rgrid->setDrawOrder(grid->getDrawOrder()); splinegrid->setTexture(editingBone->texture->name); splinegrid->setWidthHeight(editingBone->width, editingBone->height); splinegrid->position = Vector(400, 300); + splinegrid->setAssist(assistedSplineEdit); if(reset) splinegrid->resetControlPoints(); @@ -1621,6 +1632,23 @@ void AnimationEditor::decrTimelineGrid() updateTimelineGrid(); } +void AnimationEditor::toggleSplineMode() +{ + assistedSplineEdit = !assistedSplineEdit; + updateButtonLabels(); + if(splinegrid) + splinegrid->setAssist(assistedSplineEdit); +} + +void AnimationEditor::updateButtonLabels() +{ + { + std::ostringstream os; + os << "S.Assist (W)(" << (assistedSplineEdit ? "on" : "off") << ")"; + bSplineAssist->label->setText(os.str()); + } +} + void AnimationEditor::updateTimelineGrid() { std::ostringstream os; @@ -1659,3 +1687,4 @@ void AnimationEditor::applySplineGridToBone() interp->updateGridAndBone(*bk, editingBone); } } + diff --git a/Aquaria/AnimationEditor.h b/Aquaria/AnimationEditor.h index c18ad74..e69e12a 100644 --- a/Aquaria/AnimationEditor.h +++ b/Aquaria/AnimationEditor.h @@ -8,6 +8,7 @@ class DebugFont; class BitmapText; class SplineGrid; +class DebugButton; class KeyframeWidget : public Quad { @@ -133,6 +134,7 @@ public: SkeletalKeyframe buffer; bool editingStrip; + bool assistedSplineEdit; size_t selectedStripPoint; void reverseAnim(); @@ -162,6 +164,10 @@ public: SplineGrid *splinegrid; void applySplineGridToBone(); void applyBoneToSplineGrid(); + + void toggleSplineMode(); + DebugButton *bSplineAssist; + void updateButtonLabels(); }; diff --git a/BBGE/Interpolators.cpp b/BBGE/Interpolators.cpp index ad5aaa9..f954b53 100644 --- a/BBGE/Interpolators.cpp +++ b/BBGE/Interpolators.cpp @@ -165,22 +165,23 @@ void BSpline2DWithPoints::reset() BSpline2D::reset(&controlpoints[0]); } -BSpline2DControlPointGenerator::BSpline2DControlPointGenerator(size_t cx, size_t cy) +bool BSpline2DControlPointGenerator::resize(size_t cx, size_t cy) { const size_t interpStorageSizeX = tbsp__getInterpolatorStorageSize(cx, cx); const size_t interpStorageSizeY = tbsp__getInterpolatorStorageSize(cy, cy); const size_t interpStorageNeeded = interpStorageSizeX + interpStorageSizeY; floats.resize(interpStorageNeeded); - interp.x.init(&floats[0], cx, cx); - interp.y.init(&floats[interpStorageSizeX], cy, cy); cp2d.init(cx, cy); const size_t maxcp = std::max(cx, cy); vectmp.resize(maxcp); + + return interp.x.init(&floats[0], cx, cx) + && interp.y.init(&floats[interpStorageSizeX], cy, cy); } -void BSpline2DControlPointGenerator::refresh(const float* knotsx, const float* knotsy, unsigned degx, unsigned degy) +bool BSpline2DControlPointGenerator::refresh(const float* knotsx, const float* knotsy, unsigned degx, unsigned degy) { const size_t maxcp = vectmp.size(); const size_t tmpn = tbsp__getInterpolatorRefreshTempSize(maxcp, maxcp); @@ -195,8 +196,8 @@ void BSpline2DControlPointGenerator::refresh(const float* knotsx, const float* k tmp = &tmpv[0]; } - interp.x.refresh(tmp, knotsx, degx); - interp.y.refresh(tmp, knotsy, degy); + return interp.x.refresh(tmp, knotsx, degx) + && interp.y.refresh(tmp, knotsy, degy); } Vector* BSpline2DControlPointGenerator::generateControlPoints(const Vector *points2d) @@ -230,10 +231,10 @@ Vector* BSpline2DControlPointGenerator::generateControlPoints(const Vector *poin } -BSpline2DControlPointGeneratorWithPoints::BSpline2DControlPointGeneratorWithPoints(size_t cx, size_t cy) - : BSpline2DControlPointGenerator(cx, cy) - , designpoints(cx * cy) +bool BSpline2DControlPointGeneratorWithPoints::resize(size_t cx, size_t cy) { + designpoints.resize(cx * cy); + return BSpline2DControlPointGenerator::resize(cx, cy); } Vector* BSpline2DControlPointGeneratorWithPoints::generateControlPoints() diff --git a/BBGE/Interpolators.h b/BBGE/Interpolators.h index c4979b0..c098c97 100644 --- a/BBGE/Interpolators.h +++ b/BBGE/Interpolators.h @@ -75,9 +75,9 @@ public: class BSpline2DControlPointGenerator { public: - BSpline2DControlPointGenerator(size_t cx, size_t cy); + bool resize(size_t cx, size_t cy); - void refresh(const float *knotsx, const float *knotsy, unsigned degx, unsigned degy); + bool refresh(const float *knotsx, const float *knotsy, unsigned degx, unsigned degy); Vector *generateControlPoints(const Vector *points2d); @@ -94,7 +94,7 @@ private: class BSpline2DControlPointGeneratorWithPoints : public BSpline2DControlPointGenerator { public: - BSpline2DControlPointGeneratorWithPoints(size_t cx, size_t cy); + bool resize(size_t cx, size_t cy); Vector *generateControlPoints(); std::vector designpoints; }; diff --git a/BBGE/SplineGrid.cpp b/BBGE/SplineGrid.cpp index dc0c865..1de9cd2 100644 --- a/BBGE/SplineGrid.cpp +++ b/BBGE/SplineGrid.cpp @@ -79,29 +79,26 @@ void SplineGridCtrlPoint::onUpdate(float dt) } SplineGrid::SplineGrid() - : wasModified(false), deg(0), pointscale(1), cpgen(NULL) + : wasModified(false), deg(0), pointscale(1), _assistMode(true) { setWidthHeight(128, 128); renderQuad = true; renderBorder = true; + renderBorderColor = Vector(0.5f, 0.5f, 0.5f); } SplineGrid::~SplineGrid() { - delete cpgen; } DynamicRenderGrid *SplineGrid::resize(size_t w, size_t h, size_t xres, size_t yres, unsigned degx, unsigned degy) { + if(!cpgen.resize(w, h)) + return NULL; + size_t oldcpx = bsp.ctrlX(); size_t oldcpy = bsp.ctrlY(); - if(cpgen && (oldcpx != w || oldcpy != h)) - { - delete cpgen; - cpgen = NULL; - } - DynamicRenderGrid *ret = this->createGrid(xres, yres); ret->gridType = GRID_INTERP; @@ -138,7 +135,8 @@ DynamicRenderGrid *SplineGrid::resize(size_t w, size_t h, size_t xres, size_t yr ref = createControlPoint(x, y); } - _initCpgen(); + if(!cpgen.refresh(bsp.getKnotsX(), bsp.getKnotsY(), bsp.degX(), bsp.degY())) + return NULL; recalc(); @@ -147,14 +145,15 @@ DynamicRenderGrid *SplineGrid::resize(size_t w, size_t h, size_t xres, size_t yr void SplineGrid::recalc() { - if(cpgen) + if(_assistMode) { - exportGridPoints(&cpgen->designpoints[0]); + exportGridPoints(&cpgen.designpoints[0]); _generateControlPointsFromDesignPoints(); } else { exportGridPoints(&bsp.controlpoints[0]); + bsp.recalc(&cpgen.designpoints[0], bsp.ctrlX(), bsp.ctrlY()); } if(grid) @@ -183,11 +182,11 @@ void SplineGrid::importKeyframe(const BoneKeyframe* bk) bsp.controlpoints = bk->controlpoints; - if(cpgen) + if(_assistMode) { // given control points, generate spline points (which are later caculated back into control points) - bsp.recalc(&cpgen->designpoints[0], bsp.ctrlX(), bsp.ctrlY()); - importGridPoints(&cpgen->designpoints[0]); + bsp.recalc(&cpgen.designpoints[0], bsp.ctrlX(), bsp.ctrlY()); + importGridPoints(&cpgen.designpoints[0]); } else importGridPoints(&bk->controlpoints[0]); @@ -212,9 +211,9 @@ void SplineGrid::resetControlPoints() // This pushes the bspline controlpoints outwards so that all spline points line up as one would expect. // If this weren't done, the tile's texture would be pulled inwards (more with increasing dimension); // as if the tile was a piece of plastic foil that's seen too much heat. - if(cpgen) + //if(_assistMode) // ALWAYS DO THIS!! { - cpgen->designpoints = bsp.controlpoints; + cpgen.designpoints = bsp.controlpoints; _generateControlPointsFromDesignPoints(); } @@ -223,17 +222,10 @@ void SplineGrid::resetControlPoints() void SplineGrid::_generateControlPointsFromDesignPoints() { - const Vector *cp = cpgen->generateControlPoints(); + const Vector *cp = cpgen.generateControlPoints(); memcpy(&bsp.controlpoints[0], cp, bsp.controlpoints.size() * sizeof(*cp)); } -void SplineGrid::_initCpgen() -{ - assert(!cpgen); - cpgen = new BSpline2DControlPointGeneratorWithPoints(bsp.ctrlX(), bsp.ctrlY()); - cpgen->refresh(bsp.getKnotsX(), bsp.getKnotsY(), bsp.degX(), bsp.degY()); -} - SplineGridCtrlPoint* SplineGrid::createControlPoint(size_t x, size_t y) { const size_t cpx = bsp.ctrlX(); @@ -263,7 +255,10 @@ void SplineGrid::onRender(const RenderState& rs) const const Vector wh2(width * 0.5f, height * 0.5f); glLineWidth(2); - glColor4f(0.0f, 0.3f, 1.0f, 0.3f); + if(_assistMode) + glColor4f(0.0f, 0.3f, 1.0f, 0.4f); + else + glColor4f(0.0f, 0.0f, 0.0f, 0.4f); const size_t cpx = bsp.ctrlX(); const size_t cpy = bsp.ctrlY(); @@ -293,9 +288,14 @@ void SplineGrid::onRender(const RenderState& rs) const glEnd(); } - if(RenderObject::renderCollisionShape && cpgen) + const Vector *psrc = _assistMode + ? &bsp.controlpoints[0] + : &cpgen.designpoints[0]; + + if(RenderObject::renderCollisionShape) { - glColor4f(1.0f, 0.4f, 0.4f, 0.7f); + glLineWidth(1); + glColor4f(1.0f, 0.3f, 0.3f, 0.7f); glPushMatrix(); glScalef(width, height, 1); @@ -303,7 +303,7 @@ void SplineGrid::onRender(const RenderState& rs) const for(size_t y = 0; y < cpy; ++y) { glBegin(GL_LINE_STRIP); - const Vector *row = &bsp.controlpoints[y * cpx]; + const Vector *row = &psrc[y * cpx]; for(size_t x = 0; x < cpx; ++x) { const Vector p = row[x]; @@ -318,7 +318,7 @@ void SplineGrid::onRender(const RenderState& rs) const glBegin(GL_LINE_STRIP); for(size_t y = 0; y < cpy; ++y) { - const Vector p = bsp.controlpoints[y * cpx + x]; + const Vector p = psrc[y * cpx + x]; glVertex2f(p.x, p.y); } glEnd(); @@ -337,3 +337,17 @@ void SplineGrid::setPointScale(const float scale) ctrlp[i]->scale.y = scale; } } + +void SplineGrid::setAssist(bool on) +{ + if(on == _assistMode) + return; + + if(on) + importGridPoints(&cpgen.designpoints[0]); + else + importGridPoints(&bsp.controlpoints[0]); + + _assistMode = on; + recalc(); +} diff --git a/BBGE/SplineGrid.h b/BBGE/SplineGrid.h index f63bde4..eb7045a 100644 --- a/BBGE/SplineGrid.h +++ b/BBGE/SplineGrid.h @@ -47,6 +47,8 @@ public: void setPointScale(const float scale); float getPointScale() const { return pointscale; } + void setAssist(bool on); + virtual void onRender(const RenderState& rs) const OVERRIDE; virtual void onUpdate(float dt) OVERRIDE; @@ -58,7 +60,6 @@ public: private: void _generateControlPointsFromDesignPoints(); - void _initCpgen(); SplineGridCtrlPoint *createControlPoint(size_t x, size_t y); @@ -67,7 +68,8 @@ private: BSpline2DWithPoints bsp; float pointscale; - BSpline2DControlPointGeneratorWithPoints *cpgen; + BSpline2DControlPointGeneratorWithPoints cpgen; + bool _assistMode; }; diff --git a/ExternalLibs/tbsp.hh b/ExternalLibs/tbsp.hh index 1cb27c2..a94f9e0 100644 --- a/ExternalLibs/tbsp.hh +++ b/ExternalLibs/tbsp.hh @@ -835,12 +835,12 @@ T *Interpolator::init(T * TBSP_RESTRICT const mem, size_t nump, size_t numcp) // Calling this with 2 points is pointless, < 2 is mathematically impossible if(nump < 2 || numcp < 2 || !mem) - return false; + return NULL; // Can only generate less or equal control points than points TBSP_ASSERT(numcp <= nump); if(!(numcp <= nump)) - return false; + return NULL; T *p = mem;