mirror of
https://github.com/FirestormViewer/phoenix-firestorm.git
synced 2026-08-14 08:53:53 +00:00
Heavy FS AO system modifications
NEEDS TESTING. Despite my best efforts and deeming this beta-ready it may still contain some bugs. - Independent tracks per animation state - multiple of these can be played at the same time - Animation groups - again, at the same time, but only as grouped with selected animations - "Always played" quasi-state that can be used for bento ears, tails etc. - Context menus on the animations list - Tried to keep it backwards compatible Credits given where credits are due: Poked Zi Ree few times for opinions, suggestions and ideas - thanks! Signed-off-by: PanteraPolnocy <panterapolnocy@gmail.com>
This commit is contained in:
+943
-108
File diff suppressed because it is too large
Load Diff
+54
-3
@@ -32,9 +32,13 @@
|
||||
#include "lltransientdockablefloater.h"
|
||||
#include "aoset.h"
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
class LLButton;
|
||||
class LLComboBox;
|
||||
class LLCheckBoxCtrl;
|
||||
class LLContextMenu;
|
||||
class LLMenuButton;
|
||||
class LLMenuItemCallGL;
|
||||
class LLScrollListCtrl;
|
||||
@@ -50,14 +54,14 @@ class FloaterAO
|
||||
|
||||
private:
|
||||
FloaterAO(const LLSD& key);
|
||||
~FloaterAO() = default;
|
||||
~FloaterAO();
|
||||
|
||||
public:
|
||||
bool postBuild() override;
|
||||
void onOpen(const LLSD& key) override;
|
||||
void onClose(bool app_quitting) override;
|
||||
void draw() override;
|
||||
void updateList();
|
||||
void updateScrollListData();
|
||||
void updateSetParameters();
|
||||
void updateAnimationList();
|
||||
|
||||
@@ -65,7 +69,25 @@ class FloaterAO
|
||||
EAcceptance* accept, std::string& tooltip_msg) override;
|
||||
|
||||
protected:
|
||||
LLScrollListItem* addAnimation(const std::string& name);
|
||||
|
||||
struct RowInfo
|
||||
{
|
||||
std::string mKind; // "single", "group", "member", "trackmember"
|
||||
S32 mIndex{ -1 };
|
||||
S32 mMember{ -1 }; // member index within a group or track, -1 for the row itself
|
||||
};
|
||||
|
||||
LLScrollListItem* addRow(LLScrollListCtrl* list, const std::string& icon, const std::string& name, const RowInfo& info, const std::string& tooltip, bool indented, bool bold);
|
||||
bool getRowInfo(LLScrollListItem* item, RowInfo& info) const;
|
||||
static LLSD encodeRowValue(const RowInfo& info);
|
||||
|
||||
void rebuildAnimationList();
|
||||
void rebuildTrackSelector();
|
||||
|
||||
std::string expansionKey() const;
|
||||
bool isFolderExpanded(const LLUUID& folderID) const;
|
||||
void setFolderExpanded(const LLUUID& folderID, bool expanded);
|
||||
void requestListRebuild();
|
||||
|
||||
void onSelectSet();
|
||||
void onSelectSetSmall();
|
||||
@@ -96,6 +118,20 @@ class FloaterAO
|
||||
void onClickLess();
|
||||
void onDoubleClick();
|
||||
|
||||
void onClickRename();
|
||||
bool renameGroupCallback(const LLSD& notification, const LLSD& response, S32 stepIndex);
|
||||
|
||||
void onAnimationListRightClick(LLUICtrl* ctrl, S32 x, S32 y, MASK mask);
|
||||
void showContextMenu(LLScrollListCtrl* list, S32 x, S32 y);
|
||||
void onToggleRowExpand(const RowInfo& info);
|
||||
void onExtractMember(const RowInfo& info);
|
||||
void onDeleteRow(const RowInfo& info);
|
||||
void onRenameRow(const RowInfo& info);
|
||||
|
||||
void onSelectTrackTab();
|
||||
void onClickAddTrack();
|
||||
void updateCycleControlValues();
|
||||
|
||||
void onAnimationChanged(const LLUUID& animation);
|
||||
|
||||
void reloading(bool reload);
|
||||
@@ -136,12 +172,18 @@ class FloaterAO
|
||||
LLScrollListItem* mCurrentBoldItem;
|
||||
LLButton* mMoveUpButton;
|
||||
LLButton* mMoveDownButton;
|
||||
LLButton* mRenameButton;
|
||||
LLButton* mTrashButton;
|
||||
LLCheckBoxCtrl* mCycleCheckBox;
|
||||
LLCheckBoxCtrl* mRandomizeCheckBox;
|
||||
LLTextBox* mCycleTimeTextLabel;
|
||||
LLSpinCtrl* mCycleTimeSpinner;
|
||||
|
||||
LLComboBox* mTrackSelector;
|
||||
LLButton* mTrackAddButton;
|
||||
LLPanel* mDropZonePanel;
|
||||
bool mDropZoneHovered;
|
||||
|
||||
LLButton* mReloadButton;
|
||||
|
||||
LLButton* mPreviousButton;
|
||||
@@ -161,6 +203,15 @@ class FloaterAO
|
||||
bool mCanDragAndDrop;
|
||||
bool mImportRunning;
|
||||
bool mMore;
|
||||
|
||||
bool mRebuildPending;
|
||||
S32 mCurrentTrack; // 0 = main state list, N = mTracks[N-1]
|
||||
std::string mLastSelectedStateName; // "set|state" key, resets track tab on real switches
|
||||
std::string mPendingTrackSelection; // track to select after the next reload
|
||||
std::string mLastSelectedRowValue; // detects selection transitions for auto-expand
|
||||
std::map<std::string, std::set<LLUUID>> mExpandedFolders;
|
||||
LLHandle<LLContextMenu> mContextMenuHandle;
|
||||
|
||||
};
|
||||
|
||||
#endif // AO_H
|
||||
|
||||
+1547
-276
File diff suppressed because it is too large
Load Diff
@@ -33,6 +33,11 @@
|
||||
#include "llsingleton.h"
|
||||
#include "llviewerinventory.h"
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
class LLInventoryCategory;
|
||||
|
||||
class AOTimerCollection : public LLEventTimer
|
||||
{
|
||||
public:
|
||||
@@ -74,6 +79,23 @@ protected:
|
||||
|
||||
// ----------------------------------------------------
|
||||
|
||||
|
||||
// timer cycles the state's step list instead of one of its tracks - used for the continuously playing "Always" state
|
||||
constexpr S32 AO_TRACK_INDEX_STEPS = -1;
|
||||
|
||||
class AOTrackTimer : public LLEventTimer
|
||||
{
|
||||
public:
|
||||
AOTrackTimer(S32 stateEnum, S32 trackIndex, F32 period);
|
||||
~AOTrackTimer() = default;
|
||||
|
||||
bool tick() override;
|
||||
|
||||
protected:
|
||||
S32 mStateEnum;
|
||||
S32 mTrackIndex;
|
||||
};
|
||||
|
||||
class AOEngine : public LLSingleton<AOEngine>
|
||||
{
|
||||
LLSINGLETON(AOEngine);
|
||||
@@ -93,7 +115,7 @@ public:
|
||||
void tick();
|
||||
void update();
|
||||
void reload(bool fromTimer);
|
||||
void reloadStateAnimations(AOSet* set, AOSet::AOState* state);
|
||||
bool reloadStateAnimations(AOSet* set, AOSet::AOState* state);
|
||||
void clear(bool fromTimer);
|
||||
|
||||
const LLUUID& getAOFolder() const;
|
||||
@@ -103,20 +125,40 @@ public:
|
||||
bool removeSet(AOSet* set);
|
||||
|
||||
void addAnimation(const AOSet* set, AOSet::AOState* state, const LLInventoryItem* item, bool reload = true);
|
||||
bool removeAnimation(const AOSet* set, AOSet::AOState* state, S32 index);
|
||||
bool removeAnimation(const AOSet* set, AOSet::AOState* state, S32 stepIndex, S32 memberIndex = -1);
|
||||
void checkSitCancel();
|
||||
void checkBelowWater(bool check_underwater);
|
||||
|
||||
bool importNotecard(const LLInventoryItem* item);
|
||||
void processImport(bool from_timer);
|
||||
|
||||
bool swapWithPrevious(AOSet::AOState* state, S32 index);
|
||||
bool swapWithNext(AOSet::AOState* state, S32 index);
|
||||
bool swapWithPrevious(AOSet::AOState* state, S32 stepIndex, S32 memberIndex = -1);
|
||||
bool swapWithNext(AOSet::AOState* state, S32 stepIndex, S32 memberIndex = -1);
|
||||
|
||||
void cycleTimeout(const AOSet* set);
|
||||
void cycle(eCycleMode cycleMode, bool resetTimer = false);
|
||||
|
||||
void playAnimation(const LLUUID& animation);
|
||||
void addAnimationToGroup(AOSet::AOState* state, S32 stepIndex, const LLInventoryItem* item);
|
||||
void createGroupFromMerge(AOSet::AOState* state, S32 stepIndex, const LLInventoryItem* item);
|
||||
bool createGroupFromFolder(AOSet::AOState* state, const LLInventoryCategory* category);
|
||||
void extractMemberFromGroup(AOSet::AOState* state, S32 stepIndex, S32 memberIndex);
|
||||
bool renameGroup(AOSet::AOState* state, S32 stepIndex, std::string_view newName);
|
||||
|
||||
std::string createEmptyTrack(AOSet::AOState* state);
|
||||
void addAnimationToTrack(AOSet::AOState* state, S32 trackIndex, const LLInventoryItem* item);
|
||||
void removeTrack(AOSet::AOState* state, S32 trackIndex);
|
||||
void removeTrackAnimation(AOSet::AOState* state, S32 trackIndex, S32 memberIndex);
|
||||
bool swapTrackAnimationWithPrevious(AOSet::AOState* state, S32 trackIndex, S32 memberIndex);
|
||||
bool swapTrackAnimationWithNext(AOSet::AOState* state, S32 trackIndex, S32 memberIndex);
|
||||
void setTrackCycle(AOSet::AOState* state, S32 trackIndex, bool cycle);
|
||||
void setTrackRandomize(AOSet::AOState* state, S32 trackIndex, bool randomize);
|
||||
void setTrackCycleTime(AOSet::AOState* state, S32 trackIndex, F32 time);
|
||||
void playTrackAnimation(AOSet::AOState* state, S32 trackIndex, S32 memberIndex);
|
||||
void trackTimeout(S32 stateEnum, S32 trackIndex);
|
||||
|
||||
void playAlwaysAnimation(S32 stepIndex, S32 memberIndex = -1);
|
||||
|
||||
void playAnimation(S32 stepIndex, S32 memberIndex = -1);
|
||||
const AOSet* getCurrentSet() const;
|
||||
const AOSet::AOState* getCurrentState() const;
|
||||
|
||||
@@ -176,7 +218,28 @@ protected:
|
||||
std::string getSetFolderName(const AOSet* set) const;
|
||||
std::string getStateFolderName(const AOSet::AOState* state) const;
|
||||
|
||||
bool createAnimationLink(AOSet::AOState* state, const LLInventoryItem* item);
|
||||
void stopCurrentAnimations(AOSet::AOState* state, bool skipFirst = false);
|
||||
bool swapStateAnimations(AOSet::AOState* state, const uuid_vec_t& animations);
|
||||
void startStateTracks(AOSet::AOState* state);
|
||||
void stopActiveTracks();
|
||||
void startAlwaysAnimations();
|
||||
void stopAlwaysAnimations();
|
||||
void refreshAlwaysTimers();
|
||||
void cycleAlwaysStep();
|
||||
void setItemDescription(const LLUUID& itemID, const std::string& description);
|
||||
void updateMemberSortOrder(std::vector<AOSet::AOAnimation>& animations);
|
||||
void collapseGroupToSingle(AOSet::AOState* state, AOSet::AOAnimationStep& step);
|
||||
void saveGroup(const AOSet::AOAnimationStep& step);
|
||||
void saveTrack(const AOSet::AOTrack& track);
|
||||
std::string getGroupFolderName(const AOSet::AOAnimationStep& step) const;
|
||||
std::string getTrackFolderName(const AOSet::AOTrack& track) const;
|
||||
std::string sanitiseFolderName(const std::string& name, const std::string& fallback) const;
|
||||
std::string nextGroupName(const AOSet::AOState* state) const;
|
||||
std::string nextTrackName(const AOSet::AOState* state) const;
|
||||
bool readAnimationLinks(const LLUUID& categoryID, std::vector<AOSet::AOAnimation>& animations);
|
||||
void processImportState(AOSet::AOState* state);
|
||||
|
||||
bool createAnimationLink(const LLUUID& categoryID, const LLInventoryItem* item);
|
||||
bool findForeignItems(const LLUUID& uuid) const;
|
||||
void purgeFolder(const LLUUID& uuid) const;
|
||||
|
||||
@@ -220,6 +283,21 @@ protected:
|
||||
std::vector<AOSet*> mOldImportSets;
|
||||
S32 mImportRetryCount;
|
||||
|
||||
// timers of the active state's cycling tracks, and the state
|
||||
// whose tracks are currently playing. The pointer stays valid because tracks get
|
||||
// stopped in clear() before any AOSet object goes away
|
||||
std::vector<std::unique_ptr<AOTrackTimer>> mActiveTrackTimers;
|
||||
AOSet::AOState* mActiveTrackState{ nullptr };
|
||||
|
||||
// the "Always" pseudo state of the current set while it is playing, with its
|
||||
// own step cycle timer and track timers that survive motion changes
|
||||
std::vector<std::unique_ptr<AOTrackTimer>> mAlwaysTimers;
|
||||
AOSet::AOState* mActiveAlwaysState{ nullptr };
|
||||
|
||||
// pending additions while a group subfolder is created asynchronously, keyed by
|
||||
// the merge target's link UUID - prevents duplicate folders on fast multi-drop
|
||||
std::map<LLUUID, std::vector<const LLInventoryItem*>> mPendingGroupMerges;
|
||||
|
||||
boost::signals2::connection mRegionChangeConnection;
|
||||
};
|
||||
|
||||
|
||||
+98
-43
@@ -70,7 +70,8 @@ AOSet::AOSet(const LLUUID& inventoryID)
|
||||
"Floating|Swim.H",
|
||||
"Swimming Forward|Swim.N",
|
||||
"Swimming Up|Swim.U",
|
||||
"Swimming Down|Swim.D"
|
||||
"Swimming Down|Swim.D",
|
||||
"Always"
|
||||
};
|
||||
|
||||
// keep number and order in sync with the enum in the declaration
|
||||
@@ -100,7 +101,8 @@ AOSet::AOSet(const LLUUID& inventoryID)
|
||||
ANIM_AGENT_HOVER, // needs special treatment
|
||||
ANIM_AGENT_FLY, // needs special treatment
|
||||
ANIM_AGENT_HOVER_UP, // needs special treatment
|
||||
ANIM_AGENT_HOVER_DOWN // needs special treatment
|
||||
ANIM_AGENT_HOVER_DOWN, // needs special treatment
|
||||
LLUUID::null // "Always" has no motion to override
|
||||
};
|
||||
|
||||
for (S32 index = 0; index < AOSTATES_MAX; ++index)
|
||||
@@ -110,10 +112,11 @@ AOSet::AOSet(const LLUUID& inventoryID)
|
||||
|
||||
mStates[index].mName = stateNameList[0]; // for quick reference
|
||||
mStates[index].mAlternateNames = stateNameList; // to get all possible names, including mName
|
||||
mStates[index].mNum = index;
|
||||
mStates[index].mRemapID = stateUUIDs[index];
|
||||
mStates[index].mInventoryUUID = LLUUID::null;
|
||||
mStates[index].mCurrentAnimation = 0;
|
||||
mStates[index].mCurrentAnimationID = LLUUID::null;
|
||||
mStates[index].mCurrentAnimationIDs.clear();
|
||||
mStates[index].mCycle = false;
|
||||
mStates[index].mRandom = false;
|
||||
mStates[index].mCycleTime = 0;
|
||||
@@ -151,6 +154,12 @@ AOSet::AOState* AOSet::getStateByName(const std::string& name)
|
||||
|
||||
AOSet::AOState* AOSet::getStateByRemapID(const LLUUID& id)
|
||||
{
|
||||
// "Always" state has a null remap id and must never be picked up by motion mapping
|
||||
if (id.isNull())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
LLUUID remap_id = id;
|
||||
if (remap_id == ANIM_AGENT_SIT_GROUND)
|
||||
{
|
||||
@@ -167,54 +176,100 @@ AOSet::AOState* AOSet::getStateByRemapID(const LLUUID& id)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const LLUUID& AOSet::getAnimationForState(AOState* state) const
|
||||
LLUUID AOSet::resolveAssetUUID(AOAnimation& anim)
|
||||
{
|
||||
if (state)
|
||||
if (anim.mAssetUUID.isNull())
|
||||
{
|
||||
if (auto numOfAnimations = state->mAnimations.size(); numOfAnimations > 0)
|
||||
LL_DEBUGS("AOEngine") << "Asset UUID for animation " << anim.mName << " not yet known, try to find it." << LL_ENDL;
|
||||
if (LLViewerInventoryItem* item = gInventory.getItem(anim.mInventoryUUID))
|
||||
{
|
||||
if (state->mCycle)
|
||||
{
|
||||
if (state->mRandom)
|
||||
{
|
||||
state->mCurrentAnimation = (U32)(ll_frand() * numOfAnimations);
|
||||
LL_DEBUGS("AOEngine") << "randomly chosen " << state->mCurrentAnimation << " of " << numOfAnimations << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
state->mCurrentAnimation++;
|
||||
if (state->mCurrentAnimation >= state->mAnimations.size())
|
||||
{
|
||||
state->mCurrentAnimation = 0;
|
||||
}
|
||||
LL_DEBUGS("AOEngine") << "cycle " << state->mCurrentAnimation << " of " << numOfAnimations << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
AOAnimation& anim = state->mAnimations[state->mCurrentAnimation];
|
||||
|
||||
if (anim.mAssetUUID.isNull())
|
||||
{
|
||||
LL_DEBUGS("AOEngine") << "Asset UUID for chosen animation " << anim.mName << " not yet known, try to find it." << LL_ENDL;
|
||||
|
||||
if (LLViewerInventoryItem* item = gInventory.getItem(anim.mInventoryUUID))
|
||||
{
|
||||
LL_DEBUGS("AOEngine") << "Found asset UUID for chosen animation: " << item->getAssetUUID() << " - Updating AOAnimation.mAssetUUID" << LL_ENDL;
|
||||
anim.mAssetUUID = item->getAssetUUID();
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_DEBUGS("AOEngine") << "Inventory UUID " << anim.mInventoryUUID << " for chosen animation " << anim.mName << " still returns no asset." << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
return anim.mAssetUUID;
|
||||
LL_DEBUGS("AOEngine") << "Found asset UUID for animation: " << item->getAssetUUID() << " - Updating AOAnimation.mAssetUUID" << LL_ENDL;
|
||||
anim.mAssetUUID = item->getAssetUUID();
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_DEBUGS("AOEngine") << "animation state has no animations assigned" << LL_ENDL;
|
||||
LL_DEBUGS("AOEngine") << "Inventory UUID " << anim.mInventoryUUID << " for animation " << anim.mName << " still returns no asset." << LL_ENDL;
|
||||
}
|
||||
}
|
||||
return anim.mAssetUUID;
|
||||
}
|
||||
|
||||
void AOSet::getAnimationsForState(AOState* state, uuid_vec_t& animations) const
|
||||
{
|
||||
if (!state)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (auto numOfSteps = state->mSteps.size(); numOfSteps > 0)
|
||||
{
|
||||
if (state->mCycle)
|
||||
{
|
||||
if (state->mRandom)
|
||||
{
|
||||
state->mCurrentAnimation = (U32)(ll_frand() * numOfSteps);
|
||||
LL_DEBUGS("AOEngine") << "randomly chosen step " << state->mCurrentAnimation << " of " << numOfSteps << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
state->mCurrentAnimation++;
|
||||
if (state->mCurrentAnimation >= state->mSteps.size())
|
||||
{
|
||||
state->mCurrentAnimation = 0;
|
||||
}
|
||||
LL_DEBUGS("AOEngine") << "cycle step " << state->mCurrentAnimation << " of " << numOfSteps << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
// steps can shrink through editing, keep the index in range
|
||||
if (state->mCurrentAnimation >= state->mSteps.size())
|
||||
{
|
||||
state->mCurrentAnimation = 0;
|
||||
}
|
||||
|
||||
for (AOAnimation& anim : state->mSteps[state->mCurrentAnimation].mMembers)
|
||||
{
|
||||
if (LLUUID assetId = resolveAssetUUID(anim); assetId.notNull())
|
||||
{
|
||||
animations.emplace_back(assetId);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_DEBUGS("AOEngine") << "animation state has no animations assigned" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
LLUUID AOSet::getAnimationForTrack(AOTrack& track) const
|
||||
{
|
||||
if (auto numOfAnimations = track.mAnimations.size(); numOfAnimations > 0)
|
||||
{
|
||||
if (track.mCycle)
|
||||
{
|
||||
if (track.mRandom)
|
||||
{
|
||||
track.mCurrentAnimation = (U32)(ll_frand() * numOfAnimations);
|
||||
LL_DEBUGS("AOEngine") << "track " << track.mName << ": randomly chosen " << track.mCurrentAnimation << " of " << numOfAnimations << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
track.mCurrentAnimation++;
|
||||
if (track.mCurrentAnimation >= track.mAnimations.size())
|
||||
{
|
||||
track.mCurrentAnimation = 0;
|
||||
}
|
||||
LL_DEBUGS("AOEngine") << "track " << track.mName << ": cycle " << track.mCurrentAnimation << " of " << numOfAnimations << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
if (track.mCurrentAnimation >= track.mAnimations.size())
|
||||
{
|
||||
track.mCurrentAnimation = 0;
|
||||
}
|
||||
|
||||
return resolveAssetUUID(track.mAnimations[track.mCurrentAnimation]);
|
||||
}
|
||||
return LLUUID::null;
|
||||
}
|
||||
|
||||
|
||||
+29
-3
@@ -64,6 +64,7 @@ public:
|
||||
SwimmingForward,
|
||||
SwimmingUp,
|
||||
SwimmingDown,
|
||||
Always,
|
||||
AOSTATES_MAX
|
||||
};
|
||||
|
||||
@@ -76,18 +77,41 @@ public:
|
||||
S32 mSortOrder;
|
||||
};
|
||||
|
||||
struct AOAnimationStep
|
||||
{
|
||||
std::string mName;
|
||||
LLUUID mInventoryUUID;
|
||||
S32 mSortOrder{ -1 };
|
||||
bool mIsGroup{ false };
|
||||
std::vector<AOAnimation> mMembers;
|
||||
};
|
||||
|
||||
struct AOTrack
|
||||
{
|
||||
std::string mName;
|
||||
LLUUID mInventoryUUID;
|
||||
bool mCycle{ false };
|
||||
bool mRandom{ false };
|
||||
F32 mCycleTime{ 0.f };
|
||||
std::vector<AOAnimation> mAnimations;
|
||||
U32 mCurrentAnimation{ 0 };
|
||||
LLUUID mCurrentAnimationID;
|
||||
};
|
||||
|
||||
struct AOState
|
||||
{
|
||||
std::string mName;
|
||||
std::vector<std::string> mAlternateNames;
|
||||
std::vector<const LLInventoryItem*> mAddQueue;
|
||||
S32 mNum{ 0 };
|
||||
LLUUID mRemapID;
|
||||
bool mCycle;
|
||||
bool mRandom;
|
||||
F32 mCycleTime;
|
||||
std::vector<AOAnimation> mAnimations;
|
||||
std::vector<AOAnimationStep> mSteps;
|
||||
std::vector<AOTrack> mTracks;
|
||||
U32 mCurrentAnimation;
|
||||
LLUUID mCurrentAnimationID;
|
||||
uuid_vec_t mCurrentAnimationIDs;
|
||||
LLUUID mInventoryUUID;
|
||||
bool mDirty;
|
||||
};
|
||||
@@ -119,7 +143,9 @@ public:
|
||||
AOState* getState(S32 eName);
|
||||
AOState* getStateByName(const std::string& name);
|
||||
AOState* getStateByRemapID(const LLUUID& id);
|
||||
const LLUUID& getAnimationForState(AOState* state) const;
|
||||
void getAnimationsForState(AOState* state, uuid_vec_t& animations) const;
|
||||
LLUUID getAnimationForTrack(AOTrack& track) const;
|
||||
static LLUUID resolveAssetUUID(AOAnimation& anim);
|
||||
|
||||
void startTimer(F32 timeout);
|
||||
void stopTimer();
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
can_resize="true"
|
||||
can_dock="false"
|
||||
can_close="true"
|
||||
height="352"
|
||||
min_height="320"
|
||||
height="396"
|
||||
min_height="364"
|
||||
min_width="200"
|
||||
layout="topleft"
|
||||
name="animation_overrider"
|
||||
@@ -41,13 +41,70 @@ New empty set...
|
||||
Clone current set...
|
||||
</floater.string>
|
||||
|
||||
<floater.string
|
||||
name="ao_track_main">
|
||||
Main
|
||||
</floater.string>
|
||||
<floater.string
|
||||
name="ao_no_track_animations">
|
||||
Empty Track - drop an animation here
|
||||
</floater.string>
|
||||
<floater.string
|
||||
name="ao_group_tooltip">
|
||||
Animation group - these play together:
|
||||
</floater.string>
|
||||
<floater.string
|
||||
name="ao_member_tooltip">
|
||||
Animation group entry - plays together with the rest of its group. Double-click to preview it alone.
|
||||
</floater.string>
|
||||
<floater.string
|
||||
name="ao_cm_expand">
|
||||
Expand
|
||||
</floater.string>
|
||||
<floater.string
|
||||
name="ao_cm_collapse">
|
||||
Collapse
|
||||
</floater.string>
|
||||
<floater.string
|
||||
name="ao_cm_rename_group">
|
||||
Rename group...
|
||||
</floater.string>
|
||||
<floater.string
|
||||
name="ao_cm_move_out">
|
||||
Move out of group
|
||||
</floater.string>
|
||||
<floater.string
|
||||
name="ao_cm_delete">
|
||||
Delete
|
||||
</floater.string>
|
||||
<floater.string
|
||||
name="ao_dnd_merge">
|
||||
Drop to group with this animation
|
||||
</floater.string>
|
||||
<floater.string
|
||||
name="ao_dnd_add_to_group">
|
||||
Drop to add to this group
|
||||
</floater.string>
|
||||
<floater.string
|
||||
name="ao_dnd_add_to_track">
|
||||
Drop to add to this track
|
||||
</floater.string>
|
||||
<floater.string
|
||||
name="ao_dnd_folder_group">
|
||||
Drop folder to create an animation group
|
||||
</floater.string>
|
||||
<floater.string
|
||||
name="ao_dnd_folder_pour">
|
||||
Drop folder to add its animations to this track
|
||||
</floater.string>
|
||||
|
||||
<panel
|
||||
name="animation_overrider_outer_panel"
|
||||
filename="panel_ao.xml"
|
||||
left="0"
|
||||
top="16"
|
||||
width="200"
|
||||
height="334"
|
||||
height="378"
|
||||
follows="all"
|
||||
layout="topleft">
|
||||
</panel>
|
||||
|
||||
@@ -11137,6 +11137,49 @@ The name may only contain ASCII characters, excluding ":" and "|".
|
||||
yestext="OK"/>
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
name="RenameAOGroup"
|
||||
type="alertmodal">
|
||||
Specify a new name for this animation group:
|
||||
(The name may contain any ASCII character, except for ":" or "|")
|
||||
<form name="form">
|
||||
<input name="message" type="text" default="true">
|
||||
[AO_GROUP_NAME]
|
||||
</input>
|
||||
<button
|
||||
default="true"
|
||||
index="0"
|
||||
name="OK"
|
||||
text="OK"/>
|
||||
<button
|
||||
index="1"
|
||||
name="Cancel"
|
||||
text="Cancel"/>
|
||||
</form>
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
name="RenameAOEntryMustBeASCII"
|
||||
type="alertmodal">
|
||||
Could not rename to "[AO_SET_NAME]".
|
||||
The name may only contain ASCII characters, excluding ":" and "|".
|
||||
<usetemplate
|
||||
name="okbutton"
|
||||
yestext="OK"/>
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
name="AOFolderDropNoAnimations"
|
||||
type="alertmodal">
|
||||
The folder "[NAME]" does not contain any animations to add.
|
||||
<usetemplate
|
||||
name="okbutton"
|
||||
yestext="OK"/>
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
name="NewAONameCantExist"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
left="0"
|
||||
top="0"
|
||||
width="200"
|
||||
height="314"
|
||||
height="338"
|
||||
follows="all"
|
||||
visible="true"
|
||||
layout="topleft">
|
||||
@@ -16,7 +16,7 @@
|
||||
left="10"
|
||||
top="4"
|
||||
width="180"
|
||||
height="306"
|
||||
height="330"
|
||||
follows="all"
|
||||
visible="true"
|
||||
layout="topleft">
|
||||
@@ -154,25 +154,36 @@
|
||||
|
||||
<button
|
||||
name="ao_move_up"
|
||||
tool_tip="Move the selected animation up in the list."
|
||||
tool_tip="Move the selected animation or animation group up in the list."
|
||||
left="0"
|
||||
top="0"
|
||||
width="20"
|
||||
height="32"
|
||||
height="24"
|
||||
image_overlay="Arrow_Up"
|
||||
follows="left|top"
|
||||
layout="topleft" />
|
||||
|
||||
<button
|
||||
name="ao_move_down"
|
||||
tool_tip="Move the selected animation down in the list."
|
||||
tool_tip="Move the selected animation or animation group down in the list."
|
||||
top_pad="4"
|
||||
width="20"
|
||||
height="32"
|
||||
height="24"
|
||||
image_overlay="Arrow_Down"
|
||||
follows="left|top"
|
||||
layout="topleft" />
|
||||
|
||||
<button
|
||||
name="ao_rename"
|
||||
tool_tip="Rename the selected animation group."
|
||||
left_delta="0"
|
||||
bottom="-25"
|
||||
width="20"
|
||||
height="20"
|
||||
image_overlay="Edit_Wrench"
|
||||
follows="left|bottom"
|
||||
layout="topleft" />
|
||||
|
||||
<button
|
||||
name="ao_trash"
|
||||
tool_tip="Remove the selected animation from the list."
|
||||
@@ -185,6 +196,26 @@
|
||||
layout="topleft" />
|
||||
</panel>
|
||||
|
||||
<combo_box
|
||||
name="ao_track_selection_combo"
|
||||
tool_tip="Select which animation track of this state to show. The main list plays as usual, additional tracks play and cycle independently alongside it, for example a tail wag next to all walking animations."
|
||||
left="0"
|
||||
top_pad="4"
|
||||
right="-24"
|
||||
height="20"
|
||||
follows="left|right|bottom"
|
||||
layout="topleft" />
|
||||
|
||||
<button
|
||||
name="ao_track_add"
|
||||
tool_tip="Add a new independent animation track to this state."
|
||||
left_pad="4"
|
||||
width="20"
|
||||
height="20"
|
||||
image_overlay="AddItem_Press"
|
||||
follows="right|bottom"
|
||||
layout="topleft" />
|
||||
|
||||
<check_box
|
||||
name="ao_cycle"
|
||||
label="Cycle"
|
||||
@@ -303,6 +334,55 @@
|
||||
follows="right|bottom"
|
||||
layout="topleft" />
|
||||
|
||||
<panel
|
||||
name="ao_drop_zone_panel"
|
||||
left="0"
|
||||
top="68"
|
||||
right="-1"
|
||||
height="44"
|
||||
follows="left|right|top"
|
||||
visible="false"
|
||||
bg_alpha_color="Black_50"
|
||||
bg_opaque_color="Black_50"
|
||||
background_visible="true"
|
||||
background_opaque="true"
|
||||
mouse_opaque="false"
|
||||
layout="topleft">
|
||||
|
||||
<view_border
|
||||
name="ao_drop_zone_border"
|
||||
left="0"
|
||||
top="0"
|
||||
right="-1"
|
||||
bottom="-1"
|
||||
follows="all" />
|
||||
|
||||
<text
|
||||
name="ao_drop_zone_add_label"
|
||||
left="2"
|
||||
top="6"
|
||||
right="-2"
|
||||
height="16"
|
||||
halign="center"
|
||||
font.style="BOLD"
|
||||
follows="left|right|top"
|
||||
layout="topleft">
|
||||
Drop here to add
|
||||
</text>
|
||||
|
||||
<text
|
||||
name="ao_drop_zone_group_label"
|
||||
left="2"
|
||||
top_pad="2"
|
||||
right="-2"
|
||||
height="16"
|
||||
halign="center"
|
||||
follows="left|right|top"
|
||||
layout="topleft">
|
||||
Drop on existing to group
|
||||
</text>
|
||||
</panel>
|
||||
|
||||
</panel>
|
||||
|
||||
<!-- Reload Cover Panel -->
|
||||
@@ -312,7 +392,7 @@
|
||||
left="0"
|
||||
top="0"
|
||||
width="200"
|
||||
height="315"
|
||||
height="339"
|
||||
follows="all"
|
||||
visible="false"
|
||||
bg_alpha_color="Black_50"
|
||||
|
||||
@@ -5,4 +5,18 @@
|
||||
<floater.string name="ao_dnd_only_on_full_interface">Możesz przeciągać notkę z zestawami animacji tylko na pełne okno interfejsu Animatora. Kliknij na ikonce klucza francuskiego, aby je otworzyć.</floater.string>
|
||||
<floater.string name="ao_add_blank_label">Nowy pusty zestaw...</floater.string>
|
||||
<floater.string name="ao_add_clone_label">Sklonuj obecny zestaw...</floater.string>
|
||||
<floater.string name="ao_track_main">Główna</floater.string>
|
||||
<floater.string name="ao_no_track_animations">Pusta ścieżka - upuść tutaj animację</floater.string>
|
||||
<floater.string name="ao_group_tooltip">Grupa animacji - te animacje są odtwarzane razem:</floater.string>
|
||||
<floater.string name="ao_member_tooltip">Element grupy animacji - odtwarza się razem z resztą swojej grupy. Kliknij dwukrotnie, aby wyświetlić podgląd samodzielnie.</floater.string>
|
||||
<floater.string name="ao_cm_expand">Rozwiń</floater.string>
|
||||
<floater.string name="ao_cm_collapse">Zwiń</floater.string>
|
||||
<floater.string name="ao_cm_rename_group">Zmień nazwę grupy...</floater.string>
|
||||
<floater.string name="ao_cm_move_out">Przenieś poza grupę</floater.string>
|
||||
<floater.string name="ao_cm_delete">Usuń</floater.string>
|
||||
<floater.string name="ao_dnd_merge">Upuść, aby zgrupować z tą animacją</floater.string>
|
||||
<floater.string name="ao_dnd_add_to_group">Upuść, aby dodać do tej grupy</floater.string>
|
||||
<floater.string name="ao_dnd_add_to_track">Upuść, aby dodać do tej ścieżki</floater.string>
|
||||
<floater.string name="ao_dnd_folder_group">Upuść folder, aby utworzyć grupę animacji</floater.string>
|
||||
<floater.string name="ao_dnd_folder_pour">Upuść folder, aby dodać jego animacje do tej ścieżki</floater.string>
|
||||
</floater>
|
||||
|
||||
@@ -4149,6 +4149,23 @@ Nazwa może zawierać tylko znaki ASCII, za wyjątkiem ":" oraz "|".
|
||||
Nie można zmienić nazwy zestawu AO "[AO_SET_NAME]".
|
||||
Nazwa może zawierać tylko znaki ASCII, za wyjątkiem ":" oraz "|".
|
||||
</notification>
|
||||
<notification name="RenameAOGroup">
|
||||
Wpisz nazwę nowej grupy animacji:
|
||||
(Nazwa może zawierać każdy znak ASCII, za wyjątkiem ":" oraz "|")
|
||||
<form name="form">
|
||||
<input name="message">
|
||||
[AO_GROUP_NAME]
|
||||
</input>
|
||||
<button name="Cancel" text="Anuluj"/>
|
||||
</form>
|
||||
</notification>
|
||||
<notification name="RenameAOEntryMustBeASCII">
|
||||
Nie można zmienić nazwy na "[AO_SET_NAME]".
|
||||
Nazwa może zawierać tylko znaki ASCII, za wyjątkiem ":" oraz "|".
|
||||
</notification>
|
||||
<notification name="AOFolderDropNoAnimations">
|
||||
Folder "[NAME]" nie zawiera żadnych animacji do dodania.
|
||||
</notification>
|
||||
<notification name="NewAONameCantExist">
|
||||
Zestaw animacji o tej nazwie już istnieje.
|
||||
</notification>
|
||||
|
||||
@@ -11,10 +11,13 @@
|
||||
<check_box name="ao_disable_stands_in_mouselook" label="Wyłącz w trybie 1 osoby" tool_tip="Jeśli chcesz zachować własną animację stania w miejscu, będąc w trybie pierwszoosobowym (mouselook), to zaznacz tą opcję." />
|
||||
<combo_box name="ao_state_selection_combo" tool_tip="Wybierz stan animacji do edycji." />
|
||||
<panel name="ao_animation_move_trash_panel">
|
||||
<button name="ao_move_up" tool_tip="Przenieś zaznaczoną animację do góry na liście." />
|
||||
<button name="ao_move_down" tool_tip="Przenieś zaznaczoną animację w dół na liście." />
|
||||
<button name="ao_move_up" tool_tip="Przenieś zaznaczoną animację lub grupę animacji do góry na liście." />
|
||||
<button name="ao_move_down" tool_tip="Przenieś zaznaczoną animację lub grupę animacji w dół na liście." />
|
||||
<button name="ao_rename" tool_tip="Zmień nazwę wybranej grupy animacji." />
|
||||
<button name="ao_trash" tool_tip="Usuń zaznaczoną animację z listy." />
|
||||
</panel>
|
||||
<combo_box name="ao_track_selection_combo" tool_tip="Wybierz, która ścieżka animacji tego stanu ma być wyświetlana. Lista główna jest odtwarzana jak zwykle, natomiast dodatkowe ścieżki są odtwarzane i zapętlane niezależnie obok niej, na przykład machanie ogonem działa podczas wszystkich animacji chodzenia." />
|
||||
<button name="ao_track_add" tool_tip="Dodaj nową niezależną ścieżkę animacji do tego stanu." />
|
||||
<check_box name="ao_cycle" label="Cykl" tool_tip="Odtwarzaj inną animację z listy za każdym razem, gdy dany stan jest wywoływany." />
|
||||
<check_box name="ao_randomize" label="Losowy porządek" tool_tip="Losuj porządek odtwarzania animacji w cyklu." />
|
||||
<text name="ao_cycle_time_seconds_label" value="Czas cyklu (sekundy):" />
|
||||
@@ -29,6 +32,14 @@
|
||||
</layout_panel>
|
||||
</layout_stack>
|
||||
<button name="ao_less" tool_tip="Pokazuj mniejszy interfejs Animatora." />
|
||||
<panel name="ao_drop_zone_panel">
|
||||
<text name="ao_drop_zone_add_label">
|
||||
Upuść tutaj, by dodać
|
||||
</text>
|
||||
<text name="ao_drop_zone_group_label">
|
||||
Upuść na istniejącą, by zgrupować
|
||||
</text>
|
||||
</panel>
|
||||
</panel>
|
||||
<panel name="ao_reload_cover">
|
||||
<panel name="ao_reload_text_panel">
|
||||
|
||||
Reference in New Issue
Block a user