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:
parent
8cb19e528f
commit
0e1283a4d7
4 changed files with 128 additions and 126 deletions
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Add table
Reference in a new issue