1
0
Fork 0
mirror of https://github.com/AquariaOSE/Aquaria.git synced 2025-02-27 16:44:00 +00:00

Rework bone selection logic

A skeleton no longer has a "selectedBone".
It's all in the anim editor now.
This commit is contained in:
fgenesis 2025-01-13 02:53:33 +01:00
parent 8cb19e528f
commit 0e1283a4d7
4 changed files with 128 additions and 126 deletions

View file

@ -436,6 +436,8 @@ void AnimationEditor::applyState()
editMode = AE_SELECT;
editingBone = 0;
editingBoneSprite = 0;
editingBonePage = -1;
editingBoneIdx = -1;
currentKey = 0;
splinegrid = 0;
assistedSplineEdit = true;
@ -874,10 +876,9 @@ void AnimationEditor::toggleMouseSelection()
{
if (dsq->isNested()) return;
if (mouseSelection)
if (editingBone)
{
for(size_t i = 0; i < NumPages; ++i)
getPageSprite(i)->updateSelectedBoneColor();
editingBone->color = Vector(1,1,1);
}
mouseSelection = !mouseSelection;
@ -908,26 +909,6 @@ void AnimationEditor::moveBoneStripPoint(const Vector &mov)
}
}
void AnimationEditor::selectPrevBone()
{
if (dsq->isNested()) return;
if (editMode == AE_SELECT)
{
getCurrentPageSprite()->selectPrevBone();
}
}
void AnimationEditor::selectNextBone()
{
if (dsq->isNested()) return;
if (editMode == AE_SELECT)
{
getCurrentPageSprite()->selectNextBone();
}
}
void AnimationEditor::update(float dt)
{
StateObject::update(dt);
@ -1199,17 +1180,17 @@ void AnimationEditor::nextKey()
{
if (dsq->isNested()) return;
SkeletalSprite *editSprite = getCurrentPageSprite();
if (editMode == AE_STRIP)
{
selectedStripPoint++;
if (selectedStripPoint >= editingBoneSprite->getSelectedBone(false)->changeStrip.size()
if (selectedStripPoint >= editingBone->changeStrip.size()
&& selectedStripPoint > 0)
selectedStripPoint --;
}
else
{
SkeletalSprite *editSprite = getCurrentPageSprite();
if (core->getCtrlState())
{
const std::vector<KeyframeWidget*>& keyframeWidgets = pages[curPage].timeline->getKeyframes();
@ -1236,8 +1217,6 @@ void AnimationEditor::prevKey()
{
if (dsq->isNested()) return;
SkeletalSprite *editSprite = getCurrentPageSprite();
if (editMode == AE_STRIP)
{
if(selectedStripPoint > 0)
@ -1245,6 +1224,8 @@ void AnimationEditor::prevKey()
}
else
{
SkeletalSprite *editSprite = getCurrentPageSprite();
if (core->getCtrlState())
{
const std::vector<KeyframeWidget*>& keyframeWidgets = pages[curPage].timeline->getKeyframes();
@ -1743,6 +1724,7 @@ void AnimationEditor::loadFile(size_t pg, const char* fn)
{
SkeletalSprite::clearCache();
editingBone = 0;
editingBoneIdx = -1;
pages[pg].clearUndoHistory();
//editSprite->position = Vector(0,0);
pages[pg].load(fn);
@ -1958,9 +1940,14 @@ void AnimationEditor::updateEditingBone()
if(!mouseSelection)
{
if(!editingBoneSprite)
editingBoneSprite = getCurrentPageSprite();
editingBone = editingBoneSprite->getSelectedBone(false);
editingBonePage = curPage;
Bone *b = (size_t)editingBoneIdx < editingBoneSprite->bones.size() ? editingBoneSprite->bones[editingBoneIdx] : NULL; // this uses underflow at -1
if(b && b->selectable)
_selectBone(b);
else
selectNextBone();
return;
}
@ -1968,30 +1955,34 @@ void AnimationEditor::updateEditingBone()
float mind;
Bone *nearest = NULL;
SkeletalSprite *nearestSpr = NULL;
const Vector p = core->mouse.position;
int page = -1;
const Vector& p = core->mouse.position;
int page = -1, idx = -1;
for(size_t i = 0; i < NumPages; ++i)
{
SkeletalSprite& spr = pages[i].editSprite;
if(spr.isLoaded())
{
if(Bone *b = spr.getSelectedBone(true))
int k = spr.findSelectableBoneIdxClosestTo(p, true);
if(k >= 0)
{
const float d = (b->position - p).getSquaredLength2D();
Bone *b = spr.bones[k];
const float d = (b->getWorldPosition() - p).getSquaredLength2D();
if(!nearest || d < mind)
{
mind = d;
nearest = b;
nearestSpr = &spr;
page = i;
idx = k;
}
}
}
}
editingBone = nearest;
editingBoneSprite = nearestSpr;
editingBonePage = page;
editingBoneIdx = idx;
_selectBone(nearest);
}
void AnimationEditor::showAllBones()
@ -2065,6 +2056,8 @@ void AnimationEditor::updateButtonLabels()
void AnimationEditor::toggleGradient()
{
if (dsq->isNested()) return;
bgGrad->alpha.x = float(bgGrad->alpha.x <= 0);
}
@ -2137,6 +2130,12 @@ void AnimationEditor::selectPage(unsigned page)
if(editMode != AE_SELECT)
return;
if(!mouseSelection)
{
editingBoneSprite = &pages[page].editSprite;
updateEditingBone();
}
curPage = page;
}
@ -2179,3 +2178,79 @@ void AnimationEditor::applySplineGridToBone()
}
}
void AnimationEditor::_selectBone(Bone *b)
{
if(editingBone)
editingBone->color = Vector(1,1,1);
if (b)
b->color = mouseSelection ? Vector(1,0,0) : Vector(0.5,0.5,1);
else
{
editingBonePage = -1;
editingBoneSprite = NULL;
editingBoneIdx = -1;
}
editingBone = b;
}
void AnimationEditor::selectPrevBone()
{
if (dsq->isNested() || mouseSelection || editMode != AE_SELECT)
return;
SkeletalSprite *spr = editingBoneSprite ? editingBoneSprite : getCurrentPageSprite();
if(spr->bones.empty())
return;
size_t idx = editingBoneIdx;
Bone *b = NULL;
do
{
idx++;
if(idx == editingBoneIdx)
{
idx = -1;
break;
}
if (idx >= spr->bones.size())
idx = 0;
b = spr->bones[idx];
}
while (!b->selectable);
editingBoneIdx = idx;
editingBonePage = curPage;
editingBoneSprite = spr;
_selectBone(b);
}
void AnimationEditor::selectNextBone()
{
if (dsq->isNested() || mouseSelection || editMode != AE_SELECT)
return;
SkeletalSprite *spr = editingBoneSprite ? editingBoneSprite : getCurrentPageSprite();
if(spr->bones.empty())
return;
size_t idx = editingBoneIdx;
Bone *b = NULL;
do
{
idx--;
if(idx == editingBoneIdx)
{
idx = -1;
break;
}
if (idx >= spr->bones.size())
idx = spr->bones.size()-1;
b = spr->bones[idx];
}
while (!b->selectable);
editingBoneIdx = idx;
editingBonePage = curPage;
editingBoneSprite = spr;
_selectBone(b);
}

View file

@ -100,6 +100,7 @@ public:
Bone *editingBone; // only changed when editMode == AE_SELECT
SkeletalSprite *editingBoneSprite; // updated together with editingBone
int editingBonePage;
int editingBoneIdx; // editingBoneSprite->bones[editingBoneIdx] == editingBone
EditMode editMode;
DebugFont *text, *text2, *toptext, *btmtext;
@ -195,6 +196,8 @@ private:
void reloadAll();
bool savePage(size_t pg);
void reloadPage(size_t pg);
void _selectBone(Bone *b); // NULL to unselect
};

View file

@ -775,7 +775,6 @@ SkeletalSprite::SkeletalSprite() : RenderObject()
animLayers.resize(10);
for (size_t i = 0; i < animLayers.size(); i++)
animLayers[i].setSkeletalSprite(this);
selectedBone = -1;
}
SkeletalSprite::~SkeletalSprite()
@ -2113,94 +2112,28 @@ void SkeletalSprite::setTimeMultiplier(float t, int layer)
animLayers[layer].timeMultiplier = t;
}
Bone* SkeletalSprite::getSelectedBone(bool mouseBased)
int SkeletalSprite::findSelectableBoneIdxClosestTo(const Vector& pos, bool mustBeInBox) const
{
if (!loaded) return 0;
if (mouseBased)
{
float closestDist = HUGE_VALF;
Bone *b = 0;
Vector p = core->mouse.position;
int idx = -1;
for (size_t i = 0; i < bones.size(); i++)
{
if (bones[i]->renderQuad || core->getShiftState())
Bone *b = bones[i];
if (b->selectable && b->renderQuad && (!mustBeInBox || b->isCoordinateInsideWorld(pos)))
{
bones[i]->color = Vector(1,1,1);
if (bones[i]->selectable && bones[i]->renderQuad && bones[i]->isCoordinateInsideWorld(p))
{
float dist = (bones[i]->getWorldPosition() - p).getSquaredLength2D();
float dist = (b->getWorldPosition() - pos).getSquaredLength2D();
if (dist <= closestDist)
{
closestDist = dist;
b = bones[i];
selectedBone = i;
idx = (int)i;
}
}
}
}
if (b)
{
b->color = Vector(1,0,0);
}
return b;
}
// else
if (!bones.empty() && selectedBone < bones.size())
return bones[selectedBone];
return 0;
return idx;
}
void SkeletalSprite::updateSelectedBoneColor()
{
if(!bones.size())
return;
for (size_t i = 0; i < bones.size(); i++)
{
bones[i]->color = Vector(1,1,1);
}
Bone *b = bones[selectedBone];
if (b)
b->color = Vector(0.5,0.5,1);
}
void SkeletalSprite::setSelectedBone(int b)
{
selectedBone = b;
updateSelectedBoneColor();
}
void SkeletalSprite::selectPrevBone()
{
const size_t oldsel = selectedBone;
do
{
selectedBone++;
if(selectedBone == oldsel)
break;
if (selectedBone >= bones.size())
selectedBone = 0;
}
while (!bones[selectedBone]->selectable);
updateSelectedBoneColor();
}
void SkeletalSprite::selectNextBone()
{
const size_t oldsel = selectedBone;
do
{
selectedBone--;
if(selectedBone == oldsel)
break;
if (selectedBone >= bones.size())
selectedBone = bones.size()-1;
}
while (!bones[selectedBone]->selectable);
updateSelectedBoneColor();
}
void BoneGridInterpolator::updateGridOnly(BoneKeyframe& bk, const Bone *bone)
{

View file

@ -274,7 +274,7 @@ public:
void setTimeMultiplier(float t, int layer=0);
Bone* getSelectedBone(bool mouseBased = true);
int findSelectableBoneIdxClosestTo(const Vector& pos, bool mustBeInBox = true) const; // -1 if none found, otherwise bones[idx] to get the bone
Animation *getCurrentAnimation(size_t layer=0);
Animation *getCurrentAnimationOrNull(size_t layer=0);
@ -284,23 +284,15 @@ public:
void lastAnimation();
void firstAnimation();
bool selectAnimation(const char *name);
void updateSelectedBoneColor();
void setFreeze(bool f);
Animation *getAnimation(const std::string& anim);
std::vector<Animation> animations;
std::vector<Bone*> bones;
inline size_t getSelectedBoneIdx(void) { return selectedBone; }
void setSelectedBone(int b);
void selectPrevBone();
void selectNextBone();
bool isLoaded();
size_t getNumAnimLayers() const { return animLayers.size(); }
@ -319,7 +311,6 @@ protected:
bool frozen;
RenderObject *animKeyNotify;
bool loaded;
size_t selectedBone;
friend class AnimationLayer;
std::vector<AnimationLayer> animLayers;
Bone* initBone(int idx, std::string gfx, int pidx, bool rbp=false, std::string name="", float cr=0, bool fh=false, bool fv=false);