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; editMode = AE_SELECT;
editingBone = 0; editingBone = 0;
editingBoneSprite = 0; editingBoneSprite = 0;
editingBonePage = -1;
editingBoneIdx = -1;
currentKey = 0; currentKey = 0;
splinegrid = 0; splinegrid = 0;
assistedSplineEdit = true; assistedSplineEdit = true;
@ -874,10 +876,9 @@ void AnimationEditor::toggleMouseSelection()
{ {
if (dsq->isNested()) return; if (dsq->isNested()) return;
if (mouseSelection) if (editingBone)
{ {
for(size_t i = 0; i < NumPages; ++i) editingBone->color = Vector(1,1,1);
getPageSprite(i)->updateSelectedBoneColor();
} }
mouseSelection = !mouseSelection; 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) void AnimationEditor::update(float dt)
{ {
StateObject::update(dt); StateObject::update(dt);
@ -1199,17 +1180,17 @@ void AnimationEditor::nextKey()
{ {
if (dsq->isNested()) return; if (dsq->isNested()) return;
SkeletalSprite *editSprite = getCurrentPageSprite();
if (editMode == AE_STRIP) if (editMode == AE_STRIP)
{ {
selectedStripPoint++; selectedStripPoint++;
if (selectedStripPoint >= editingBoneSprite->getSelectedBone(false)->changeStrip.size() if (selectedStripPoint >= editingBone->changeStrip.size()
&& selectedStripPoint > 0) && selectedStripPoint > 0)
selectedStripPoint --; selectedStripPoint --;
} }
else else
{ {
SkeletalSprite *editSprite = getCurrentPageSprite();
if (core->getCtrlState()) if (core->getCtrlState())
{ {
const std::vector<KeyframeWidget*>& keyframeWidgets = pages[curPage].timeline->getKeyframes(); const std::vector<KeyframeWidget*>& keyframeWidgets = pages[curPage].timeline->getKeyframes();
@ -1236,8 +1217,6 @@ void AnimationEditor::prevKey()
{ {
if (dsq->isNested()) return; if (dsq->isNested()) return;
SkeletalSprite *editSprite = getCurrentPageSprite();
if (editMode == AE_STRIP) if (editMode == AE_STRIP)
{ {
if(selectedStripPoint > 0) if(selectedStripPoint > 0)
@ -1245,6 +1224,8 @@ void AnimationEditor::prevKey()
} }
else else
{ {
SkeletalSprite *editSprite = getCurrentPageSprite();
if (core->getCtrlState()) if (core->getCtrlState())
{ {
const std::vector<KeyframeWidget*>& keyframeWidgets = pages[curPage].timeline->getKeyframes(); const std::vector<KeyframeWidget*>& keyframeWidgets = pages[curPage].timeline->getKeyframes();
@ -1743,6 +1724,7 @@ void AnimationEditor::loadFile(size_t pg, const char* fn)
{ {
SkeletalSprite::clearCache(); SkeletalSprite::clearCache();
editingBone = 0; editingBone = 0;
editingBoneIdx = -1;
pages[pg].clearUndoHistory(); pages[pg].clearUndoHistory();
//editSprite->position = Vector(0,0); //editSprite->position = Vector(0,0);
pages[pg].load(fn); pages[pg].load(fn);
@ -1958,9 +1940,14 @@ void AnimationEditor::updateEditingBone()
if(!mouseSelection) if(!mouseSelection)
{ {
editingBoneSprite = getCurrentPageSprite(); if(!editingBoneSprite)
editingBone = editingBoneSprite->getSelectedBone(false); editingBoneSprite = getCurrentPageSprite();
editingBonePage = curPage; 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; return;
} }
@ -1968,30 +1955,34 @@ void AnimationEditor::updateEditingBone()
float mind; float mind;
Bone *nearest = NULL; Bone *nearest = NULL;
SkeletalSprite *nearestSpr = NULL; SkeletalSprite *nearestSpr = NULL;
const Vector p = core->mouse.position; const Vector& p = core->mouse.position;
int page = -1; int page = -1, idx = -1;
for(size_t i = 0; i < NumPages; ++i) for(size_t i = 0; i < NumPages; ++i)
{ {
SkeletalSprite& spr = pages[i].editSprite; SkeletalSprite& spr = pages[i].editSprite;
if(spr.isLoaded()) 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) if(!nearest || d < mind)
{ {
mind = d; mind = d;
nearest = b; nearest = b;
nearestSpr = &spr; nearestSpr = &spr;
page = i; page = i;
idx = k;
} }
} }
} }
} }
editingBone = nearest;
editingBoneSprite = nearestSpr; editingBoneSprite = nearestSpr;
editingBonePage = page; editingBonePage = page;
editingBoneIdx = idx;
_selectBone(nearest);
} }
void AnimationEditor::showAllBones() void AnimationEditor::showAllBones()
@ -2065,6 +2056,8 @@ void AnimationEditor::updateButtonLabels()
void AnimationEditor::toggleGradient() void AnimationEditor::toggleGradient()
{ {
if (dsq->isNested()) return;
bgGrad->alpha.x = float(bgGrad->alpha.x <= 0); bgGrad->alpha.x = float(bgGrad->alpha.x <= 0);
} }
@ -2137,6 +2130,12 @@ void AnimationEditor::selectPage(unsigned page)
if(editMode != AE_SELECT) if(editMode != AE_SELECT)
return; return;
if(!mouseSelection)
{
editingBoneSprite = &pages[page].editSprite;
updateEditingBone();
}
curPage = page; 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 Bone *editingBone; // only changed when editMode == AE_SELECT
SkeletalSprite *editingBoneSprite; // updated together with editingBone SkeletalSprite *editingBoneSprite; // updated together with editingBone
int editingBonePage; int editingBonePage;
int editingBoneIdx; // editingBoneSprite->bones[editingBoneIdx] == editingBone
EditMode editMode; EditMode editMode;
DebugFont *text, *text2, *toptext, *btmtext; DebugFont *text, *text2, *toptext, *btmtext;
@ -195,6 +196,8 @@ private:
void reloadAll(); void reloadAll();
bool savePage(size_t pg); bool savePage(size_t pg);
void reloadPage(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); animLayers.resize(10);
for (size_t i = 0; i < animLayers.size(); i++) for (size_t i = 0; i < animLayers.size(); i++)
animLayers[i].setSkeletalSprite(this); animLayers[i].setSkeletalSprite(this);
selectedBone = -1;
} }
SkeletalSprite::~SkeletalSprite() SkeletalSprite::~SkeletalSprite()
@ -2113,94 +2112,28 @@ void SkeletalSprite::setTimeMultiplier(float t, int layer)
animLayers[layer].timeMultiplier = t; animLayers[layer].timeMultiplier = t;
} }
Bone* SkeletalSprite::getSelectedBone(bool mouseBased) int SkeletalSprite::findSelectableBoneIdxClosestTo(const Vector& pos, bool mustBeInBox) const
{ {
if (!loaded) return 0; float closestDist = HUGE_VALF;
if (mouseBased) int idx = -1;
{
float closestDist = HUGE_VALF;
Bone *b = 0;
Vector p = core->mouse.position;
for (size_t i = 0; i < bones.size(); i++)
{
if (bones[i]->renderQuad || core->getShiftState())
{
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();
if (dist <= closestDist)
{
closestDist = dist;
b = bones[i];
selectedBone = i;
}
}
}
}
if (b)
{
b->color = Vector(1,0,0);
}
return b;
}
// else
if (!bones.empty() && selectedBone < bones.size())
return bones[selectedBone];
return 0;
}
void SkeletalSprite::updateSelectedBoneColor()
{
if(!bones.size())
return;
for (size_t i = 0; i < bones.size(); i++) for (size_t i = 0; i < bones.size(); i++)
{ {
bones[i]->color = Vector(1,1,1); Bone *b = bones[i];
if (b->selectable && b->renderQuad && (!mustBeInBox || b->isCoordinateInsideWorld(pos)))
{
float dist = (b->getWorldPosition() - pos).getSquaredLength2D();
if (dist <= closestDist)
{
closestDist = dist;
idx = (int)i;
}
}
} }
Bone *b = bones[selectedBone]; return idx;
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) void BoneGridInterpolator::updateGridOnly(BoneKeyframe& bk, const Bone *bone)
{ {

View file

@ -274,7 +274,7 @@ public:
void setTimeMultiplier(float t, int layer=0); 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 *getCurrentAnimation(size_t layer=0);
Animation *getCurrentAnimationOrNull(size_t layer=0); Animation *getCurrentAnimationOrNull(size_t layer=0);
@ -284,23 +284,15 @@ public:
void lastAnimation(); void lastAnimation();
void firstAnimation(); void firstAnimation();
bool selectAnimation(const char *name); bool selectAnimation(const char *name);
void updateSelectedBoneColor();
void setFreeze(bool f); void setFreeze(bool f);
Animation *getAnimation(const std::string& anim); Animation *getAnimation(const std::string& anim);
std::vector<Animation> animations; std::vector<Animation> animations;
std::vector<Bone*> bones; std::vector<Bone*> bones;
inline size_t getSelectedBoneIdx(void) { return selectedBone; }
void setSelectedBone(int b);
void selectPrevBone();
void selectNextBone();
bool isLoaded(); bool isLoaded();
size_t getNumAnimLayers() const { return animLayers.size(); } size_t getNumAnimLayers() const { return animLayers.size(); }
@ -319,7 +311,6 @@ protected:
bool frozen; bool frozen;
RenderObject *animKeyNotify; RenderObject *animKeyNotify;
bool loaded; bool loaded;
size_t selectedBone;
friend class AnimationLayer; friend class AnimationLayer;
std::vector<AnimationLayer> animLayers; 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); Bone* initBone(int idx, std::string gfx, int pidx, bool rbp=false, std::string name="", float cr=0, bool fh=false, bool fv=false);