Added Animation Explorer. FIRE-10622
parent
afd49c5e59
commit
152d331992
|
|
@ -113,6 +113,7 @@ include_directories(SYSTEM
|
|||
|
||||
set(viewer_SOURCE_FILES
|
||||
# <Add FS includes below this line>
|
||||
animationexplorer.cpp
|
||||
ao.cpp
|
||||
aoengine.cpp
|
||||
aoset.cpp
|
||||
|
|
@ -808,6 +809,7 @@ set(viewer_HEADER_FILES
|
|||
ViewerInstall.cmake
|
||||
|
||||
# <Add FS includes below this line>
|
||||
animationexplorer.h
|
||||
ao.h
|
||||
aoengine.h
|
||||
aoset.h
|
||||
|
|
|
|||
|
|
@ -0,0 +1,551 @@
|
|||
/**
|
||||
* @file animationexplorer.cpp
|
||||
* @brief Animation Explorer floater implementation
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
* Copyright (C) 2013, Zi Ree @ Second Life
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "animationexplorer.h"
|
||||
|
||||
#include "indra_constants.h" // for MASK_ALT etc.
|
||||
#include "message.h" // for gMessageSystem
|
||||
#include "stdenums.h" // for ADD_TOP
|
||||
#include "llagent.h" // for gAgent
|
||||
#include "llanimationstates.h"
|
||||
#include "llbutton.h"
|
||||
#include "llcachename.h" // for gCacheName
|
||||
#include "llcheckboxctrl.h"
|
||||
#include "llfloater.h"
|
||||
#include "llfloaterreg.h"
|
||||
#include "llgl.h"
|
||||
#include "llkeyframefallmotion.h"
|
||||
#include "llrect.h"
|
||||
#include "llscrolllistctrl.h"
|
||||
#include "lltimer.h"
|
||||
#include "lltoolmgr.h" // for MASK_ORBIT etc.
|
||||
#include "lltrans.h"
|
||||
#include "lluuid.h"
|
||||
#include "llview.h"
|
||||
#include "llviewerobjectlist.h"
|
||||
#include "llviewerregion.h"
|
||||
#include "llviewerwindow.h" // for gViewerWindow
|
||||
#include "llvoavatar.h"
|
||||
#include "llvoavatarself.h" // for gAgentAvatarp
|
||||
#include </storage/eisfuchs/SecondLife/source/phoenix-firestorm-lgpl-animation-explorer/indra/#[bin_dir]/packages/include/boost/container/detail/tree.hpp>
|
||||
|
||||
const S32 MAX_ANIMATIONS=100;
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
RecentAnimationList::RecentAnimationList()
|
||||
: LLSingleton<RecentAnimationList>()
|
||||
{
|
||||
}
|
||||
|
||||
RecentAnimationList::~RecentAnimationList()
|
||||
{
|
||||
}
|
||||
|
||||
void RecentAnimationList::addAnimation(const LLUUID& id, const LLUUID& playedBy)
|
||||
{
|
||||
AnimationEntry entry;
|
||||
|
||||
entry.animationID=id;
|
||||
entry.playedBy=playedBy;
|
||||
entry.time=LLTimer::getElapsedSeconds();
|
||||
|
||||
AnimationExplorer* explorer=LLFloaterReg::findTypedInstance<AnimationExplorer>("animation_explorer");
|
||||
|
||||
// only remember animation when it wasn't played by ourselves or the explorer window is open,
|
||||
// so the list doesn't get polluted
|
||||
if(playedBy!=gAgentAvatarp->getID() || explorer!=NULL)
|
||||
{
|
||||
mAnimationList.push_back(entry);
|
||||
|
||||
// only keep a certain number of entries
|
||||
if(mAnimationList.size()>MAX_ANIMATIONS)
|
||||
{
|
||||
mAnimationList.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
// if the animation explorer floater is open, send this animation over immediately
|
||||
if(explorer)
|
||||
{
|
||||
explorer->addAnimation(id,playedBy,LLTimer::getElapsedSeconds());
|
||||
}
|
||||
}
|
||||
|
||||
void RecentAnimationList::requestList(AnimationExplorer* explorer)
|
||||
{
|
||||
if(explorer)
|
||||
{
|
||||
// send the list of recent animations to the given animation explorer floater
|
||||
for(std::deque<AnimationEntry>::iterator iter=mAnimationList.begin();
|
||||
iter!=mAnimationList.end();
|
||||
++iter)
|
||||
{
|
||||
AnimationEntry entry=*iter;
|
||||
explorer->addAnimation(entry.animationID,entry.playedBy,entry.time);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
AnimationExplorer::AnimationExplorer(const LLSD& key)
|
||||
: LLFloater(key),
|
||||
mPreviewCtrl(NULL),
|
||||
mLastMouseX(0),
|
||||
mLastMouseY(0)
|
||||
{
|
||||
}
|
||||
|
||||
AnimationExplorer::~AnimationExplorer()
|
||||
{
|
||||
mAnimationPreview=NULL;
|
||||
}
|
||||
|
||||
void AnimationExplorer::startMotion(const LLUUID& motionID)
|
||||
{
|
||||
if(!mAnimationPreview)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LLVOAvatar* avatarp=mAnimationPreview->getDummyAvatar();
|
||||
|
||||
avatarp->deactivateAllMotions();
|
||||
avatarp->startMotion(ANIM_AGENT_STAND,0.0f);
|
||||
|
||||
if(motionID.notNull())
|
||||
{
|
||||
avatarp->startMotion(motionID,0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL AnimationExplorer::postBuild()
|
||||
{
|
||||
mAnimationScrollList=getChild<LLScrollListCtrl>("animation_list");
|
||||
mStopButton=getChild<LLButton>("stop_btn");
|
||||
mRevokeButton=getChild<LLButton>("revoke_btn");
|
||||
mStopAndRevokeButton=getChild<LLButton>("stop_and_revoke_btn");
|
||||
mNoOwnedAnimationsCheckBox=getChild<LLCheckBoxCtrl>("no_owned_animations_check");
|
||||
|
||||
mAnimationScrollList->setCommitCallback(boost::bind(&AnimationExplorer::onSelectAnimation,this));
|
||||
mStopButton->setCommitCallback(boost::bind(&AnimationExplorer::onStopPressed,this));
|
||||
mRevokeButton->setCommitCallback(boost::bind(&AnimationExplorer::onRevokePressed,this));
|
||||
mStopAndRevokeButton->setCommitCallback(boost::bind(&AnimationExplorer::onStopAndRevokePressed,this));
|
||||
mNoOwnedAnimationsCheckBox->setCommitCallback(boost::bind(&AnimationExplorer::onOwnedCheckToggled,this));
|
||||
|
||||
mPreviewCtrl=findChild<LLView>("animation_preview");
|
||||
if(mPreviewCtrl)
|
||||
{
|
||||
mAnimationPreview=new LLPreviewAnimation(
|
||||
mPreviewCtrl->getRect().getWidth(),mPreviewCtrl->getRect().getHeight()
|
||||
);
|
||||
mAnimationPreview->setZoom(2.0f);
|
||||
startMotion(LLUUID::null);
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("AnimationExplorer") << "Could not find animation preview control to place animation texture" << LL_ENDL;
|
||||
}
|
||||
|
||||
// request list of recent animations
|
||||
update();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void AnimationExplorer::onSelectAnimation()
|
||||
{
|
||||
LLScrollListItem* item=mAnimationScrollList->getFirstSelected();
|
||||
if(!item)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
S32 column=mAnimationScrollList->getColumn("animation_id")->mIndex;
|
||||
mCurrentAnimationID=item->getColumn(column)->getValue().asUUID();
|
||||
|
||||
column=mAnimationScrollList->getColumn("played_by")->mIndex;
|
||||
mCurrentObject=item->getColumn(column)->getValue().asUUID();
|
||||
|
||||
startMotion(mCurrentAnimationID);
|
||||
}
|
||||
|
||||
void AnimationExplorer::onStopPressed()
|
||||
{
|
||||
if(mCurrentAnimationID.notNull())
|
||||
{
|
||||
gAgentAvatarp->stopMotion(mCurrentAnimationID);
|
||||
gAgent.sendAnimationRequest(mCurrentAnimationID,ANIM_REQUEST_STOP);
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationExplorer::onRevokePressed()
|
||||
{
|
||||
if(mCurrentObject.notNull())
|
||||
{
|
||||
LLViewerObject* vo=gObjectList.findObject(mCurrentObject);
|
||||
|
||||
if(vo)
|
||||
{
|
||||
gAgentAvatarp->revokePermissionsOnObject(vo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationExplorer::onStopAndRevokePressed()
|
||||
{
|
||||
onStopPressed();
|
||||
onRevokePressed();
|
||||
}
|
||||
|
||||
void AnimationExplorer::onOwnedCheckToggled()
|
||||
{
|
||||
update();
|
||||
updateList(LLTimer::getElapsedSeconds());
|
||||
}
|
||||
|
||||
void AnimationExplorer::draw()
|
||||
{
|
||||
LLFloater::draw();
|
||||
LLRect r=mPreviewCtrl->getRect();
|
||||
|
||||
if(mAnimationPreview)
|
||||
{
|
||||
mAnimationPreview->requestUpdate();
|
||||
|
||||
gGL.color3f(1.0f,1.0f,1.0f);
|
||||
gGL.getTexUnit(0)->bind(mAnimationPreview);
|
||||
gGL.begin(LLRender::QUADS);
|
||||
{
|
||||
gGL.texCoord2f(0.0f,1.0f);
|
||||
gGL.vertex2i(r.mLeft,r.mTop);
|
||||
gGL.texCoord2f(0.0f,0.0f);
|
||||
gGL.vertex2i(r.mLeft,r.mBottom);
|
||||
gGL.texCoord2f(1.0f,0.0f);
|
||||
gGL.vertex2i(r.mRight,r.mBottom);
|
||||
gGL.texCoord2f(1.0f,1.0f);
|
||||
gGL.vertex2i(r.mRight,r.mTop);
|
||||
}
|
||||
gGL.end();
|
||||
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
|
||||
}
|
||||
|
||||
// update tiems and "Still playing" status in the list once every few seconds
|
||||
static F64 last_update=0.0f;
|
||||
F64 time=LLTimer::getElapsedSeconds();
|
||||
if(time-last_update>5.0f)
|
||||
{
|
||||
last_update=time;
|
||||
updateList(time);
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationExplorer::update()
|
||||
{
|
||||
// stop playing preview animations when reloading the list
|
||||
startMotion(LLUUID::null);
|
||||
|
||||
mAnimationScrollList->deleteAllItems();
|
||||
RecentAnimationList::instance().requestList(this);
|
||||
}
|
||||
|
||||
void AnimationExplorer::updateList(F64 current_timestamp)
|
||||
{
|
||||
S32 played_column=mAnimationScrollList->getColumn("played")->mIndex;
|
||||
S32 timestamp_column=mAnimationScrollList->getColumn("timestamp")->mIndex;
|
||||
S32 object_id_column=mAnimationScrollList->getColumn("object_id")->mIndex;
|
||||
S32 anim_id_column=mAnimationScrollList->getColumn("animation_id")->mIndex;
|
||||
|
||||
// go through the full animation scroll list
|
||||
std::vector<LLScrollListItem*> items=mAnimationScrollList->getAllData();
|
||||
for (std::vector<LLScrollListItem*>::iterator list_iter=items.begin();list_iter!=items.end();++list_iter)
|
||||
{
|
||||
LLScrollListItem* item=*list_iter;
|
||||
|
||||
// get a pointer to the "Played" column text
|
||||
LLScrollListText* played_text=(LLScrollListText*) item->getColumn(played_column);
|
||||
|
||||
// get the object ID from the list
|
||||
LLUUID object_id=item->getColumn(object_id_column)->getValue().asUUID();
|
||||
|
||||
// assume this animation is not running first
|
||||
bool is_running=false;
|
||||
|
||||
// go through the list of playing animations to find out if this animation played by
|
||||
// this object is still running
|
||||
for(LLVOAvatar::AnimSourceIterator anim_iter=gAgentAvatarp->mAnimationSources.begin();
|
||||
anim_iter!=gAgentAvatarp->mAnimationSources.end();anim_iter++)
|
||||
{
|
||||
// object found
|
||||
if(anim_iter->first==object_id)
|
||||
{
|
||||
LLUUID anim_id=item->getColumn(anim_id_column)->getValue().asUUID();
|
||||
|
||||
// animation found
|
||||
if(anim_iter->second==anim_id)
|
||||
{
|
||||
// set text to "Still playing" and break out of this loop
|
||||
played_text->setText(LLTrans::getString("animation_explorer_still_playing"));
|
||||
is_running=true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// animation was not found to be running
|
||||
if(!is_running)
|
||||
{
|
||||
// get timestamp when this animation was started
|
||||
F64 timestamp=item->getColumn(timestamp_column)->getValue().asReal();
|
||||
|
||||
// update text to show the number of seconds ago when this animation was started
|
||||
LLStringUtil::format_map_t args;
|
||||
args["SECONDS"]=llformat("%d",(S32) (current_timestamp-timestamp));
|
||||
|
||||
played_text->setText(LLTrans::getString("animation_explorer_seconds_ago",args));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationExplorer::addAnimation(const LLUUID& id, const LLUUID& played_by, F64 time)
|
||||
{
|
||||
// don't add animations that are played by ourselves when the filter box is checked
|
||||
if(played_by==gAgentAvatarp->getID())
|
||||
{
|
||||
if(mNoOwnedAnimationsCheckBox->getValue().asBoolean())
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// set object name to UUID at first
|
||||
std::string playedByName=played_by.asString();
|
||||
|
||||
// find out if the object is still in reach
|
||||
LLViewerObject* vo=gObjectList.findObject(played_by);
|
||||
if(vo)
|
||||
{
|
||||
// if it was an avatar, get the name here
|
||||
if(vo->isAvatar())
|
||||
{
|
||||
playedByName=std::string(vo->getNVPair("FirstName")->getString())+" "+
|
||||
std::string(vo->getNVPair("LastName")->getString());
|
||||
}
|
||||
// not an avatar, do a lookup by UUID
|
||||
else
|
||||
{
|
||||
// find out if we know the name to this UUID already
|
||||
std::map<LLUUID,std::string>::iterator iter=mKnownIDs.find(played_by);
|
||||
// if we don't know it yet, start a lookup
|
||||
if(iter==mKnownIDs.end())
|
||||
{
|
||||
// if we are not already looking up this object's name, send a request out
|
||||
if(std::find(mRequestedIDs.begin(),mRequestedIDs.end(),played_by)==mRequestedIDs.end())
|
||||
{
|
||||
// remember which object names we already requested
|
||||
mRequestedIDs.push_back(played_by);
|
||||
|
||||
LLMessageSystem* msg = gMessageSystem;
|
||||
|
||||
msg->newMessageFast(_PREHASH_ObjectSelect);
|
||||
msg->nextBlockFast(_PREHASH_AgentData);
|
||||
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
|
||||
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
|
||||
msg->nextBlockFast(_PREHASH_ObjectData);
|
||||
msg->addU32Fast(_PREHASH_ObjectLocalID,vo->getLocalID());
|
||||
msg->sendReliable(gAgentAvatarp->getRegion()->getHost());
|
||||
|
||||
msg->newMessageFast(_PREHASH_ObjectDeselect);
|
||||
msg->nextBlockFast(_PREHASH_AgentData);
|
||||
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
|
||||
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
|
||||
msg->nextBlockFast(_PREHASH_ObjectData);
|
||||
msg->addU32Fast(_PREHASH_ObjectLocalID,vo->getLocalID());
|
||||
msg->sendReliable(gAgentAvatarp->getRegion()->getHost());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// we know the name already
|
||||
playedByName=mKnownIDs[played_by];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// insert the item into the scroll list
|
||||
LLSD item;
|
||||
item["columns"][0]["column"]="played_by";
|
||||
item["columns"][0]["value"]=playedByName;
|
||||
item["columns"][1]["column"]="played";
|
||||
item["columns"][1]["value"]=LLTrans::getString("animation_explorer_still_playing");
|
||||
item["columns"][2]["column"]="timestamp";
|
||||
item["columns"][2]["value"]=time;
|
||||
item["columns"][3]["column"]="animation_id";
|
||||
item["columns"][3]["value"]=id;
|
||||
item["columns"][4]["column"]="object_id";
|
||||
item["columns"][4]["value"]=played_by;
|
||||
|
||||
mAnimationScrollList->addElement(item,ADD_TOP);
|
||||
}
|
||||
|
||||
void AnimationExplorer::requestNameCallback(LLMessageSystem* msg)
|
||||
{
|
||||
// if we weren't looking for any IDs, ignore this callback
|
||||
if(mRequestedIDs.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// we might have received more than one answer in one block
|
||||
S32 num=msg->getNumberOfBlocksFast(_PREHASH_ObjectData);
|
||||
for (S32 index=0;index<num;index++)
|
||||
{
|
||||
LLUUID object_id;
|
||||
msg->getUUIDFast(_PREHASH_ObjectData,_PREHASH_ObjectID,object_id,index);
|
||||
|
||||
std::vector<LLUUID>::iterator iter;
|
||||
iter=std::find(mRequestedIDs.begin(),mRequestedIDs.end(),object_id);
|
||||
// if this is one of the objects we were looking for, process the data
|
||||
if(iter!=mRequestedIDs.end())
|
||||
{
|
||||
// get the name of the object
|
||||
std::string object_name;
|
||||
msg->getStringFast(_PREHASH_ObjectData,_PREHASH_Name,object_name,index);
|
||||
|
||||
// remove the object from the lookup list and add it to the known names list
|
||||
mRequestedIDs.erase(iter);
|
||||
mKnownIDs[object_id]=object_name;
|
||||
|
||||
S32 object_id_column=mAnimationScrollList->getColumn("object_id")->mIndex;
|
||||
S32 played_by_column=mAnimationScrollList->getColumn("played_by")->mIndex;
|
||||
|
||||
// find all scroll list entries with this object UUID and update the names there
|
||||
std::vector<LLScrollListItem*> items=mAnimationScrollList->getAllData();
|
||||
for (std::vector<LLScrollListItem*>::iterator list_iter=items.begin();list_iter!=items.end();++list_iter)
|
||||
{
|
||||
LLScrollListItem* item=*list_iter;
|
||||
LLUUID list_object_id=item->getColumn(object_id_column)->getValue().asUUID();
|
||||
|
||||
if(object_id==list_object_id)
|
||||
{
|
||||
LLScrollListText* played_by_text=(LLScrollListText*) item->getColumn(played_by_column);
|
||||
played_by_text->setText(object_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Copied from llfloaterbvhpreview.cpp
|
||||
BOOL AnimationExplorer::handleMouseDown(S32 x, S32 y, MASK mask)
|
||||
{
|
||||
if (mPreviewCtrl && mPreviewCtrl->getRect().pointInRect(x, y))
|
||||
{
|
||||
bringToFront( x, y );
|
||||
gFocusMgr.setMouseCapture(this);
|
||||
gViewerWindow->hideCursor();
|
||||
mLastMouseX = x;
|
||||
mLastMouseY = y;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return LLFloater::handleMouseDown(x, y, mask);
|
||||
}
|
||||
|
||||
// Copied from llfloaterbvhpreview.cpp
|
||||
BOOL AnimationExplorer::handleMouseUp(S32 x, S32 y, MASK mask)
|
||||
{
|
||||
gFocusMgr.setMouseCapture(FALSE);
|
||||
gViewerWindow->showCursor();
|
||||
return LLFloater::handleMouseUp(x, y, mask);
|
||||
}
|
||||
|
||||
// (Almost) Copied from llfloaterbvhpreview.cpp
|
||||
BOOL AnimationExplorer::handleHover(S32 x, S32 y, MASK mask)
|
||||
{
|
||||
if (!mPreviewCtrl || !mAnimationPreview || !mPreviewCtrl->getRect().pointInRect(x, y))
|
||||
{
|
||||
return LLFloater::handleHover(x, y, mask);
|
||||
}
|
||||
|
||||
MASK local_mask = mask & ~MASK_ALT;
|
||||
if (mAnimationPreview && hasMouseCapture())
|
||||
{
|
||||
if (local_mask == MASK_PAN)
|
||||
{
|
||||
// pan here
|
||||
mAnimationPreview->pan((F32)(x - mLastMouseX) * -0.005f, (F32)(y - mLastMouseY) * -0.005f);
|
||||
}
|
||||
else if (local_mask == MASK_ORBIT)
|
||||
{
|
||||
F32 yaw_radians = (F32)(x - mLastMouseX) * -0.01f;
|
||||
F32 pitch_radians = (F32)(y - mLastMouseY) * 0.02f;
|
||||
mAnimationPreview->rotate(yaw_radians, pitch_radians);
|
||||
}
|
||||
else
|
||||
{
|
||||
F32 yaw_radians = (F32)(x - mLastMouseX) * -0.01f;
|
||||
F32 zoom_amt = (F32)(y - mLastMouseY) * 0.02f;
|
||||
mAnimationPreview->rotate(yaw_radians, 0.f);
|
||||
mAnimationPreview->zoom(zoom_amt);
|
||||
}
|
||||
mAnimationPreview->requestUpdate();
|
||||
LLUI::setMousePositionLocal(this, mLastMouseX, mLastMouseY);
|
||||
}
|
||||
else if (local_mask == MASK_ORBIT)
|
||||
{
|
||||
gViewerWindow->setCursor(UI_CURSOR_TOOLCAMERA);
|
||||
}
|
||||
else if (local_mask == MASK_PAN)
|
||||
{
|
||||
gViewerWindow->setCursor(UI_CURSOR_TOOLPAN);
|
||||
}
|
||||
else
|
||||
{
|
||||
gViewerWindow->setCursor(UI_CURSOR_TOOLZOOMIN);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// (Almost) Copied from llfloaterbvhpreview.cpp
|
||||
BOOL AnimationExplorer::handleScrollWheel(S32 x, S32 y, S32 clicks)
|
||||
{
|
||||
if (mPreviewCtrl && mPreviewCtrl->getRect().pointInRect(x, y))
|
||||
{
|
||||
mAnimationPreview->zoom((F32)clicks * -0.2f);
|
||||
mAnimationPreview->requestUpdate();
|
||||
return TRUE;
|
||||
}
|
||||
return LLFloater::handleScrollWheel(x, y, clicks);
|
||||
}
|
||||
|
||||
// Copied from llfloaterbvhpreview.cpp
|
||||
void AnimationExplorer::onMouseCaptureLost()
|
||||
{
|
||||
gViewerWindow->showCursor();
|
||||
}
|
||||
|
|
@ -0,0 +1,133 @@
|
|||
/**
|
||||
* @file ao.h
|
||||
* @brief Animation Explorer floater declaration
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
* Copyright (C) 2013, Zi Ree @ Second Life
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef ANIMATIONEXPLORER_H
|
||||
#define ANIMATIONEXPLORER_H
|
||||
|
||||
#include <deque>
|
||||
|
||||
#include "llfloater.h"
|
||||
#include "llfloaterbvhpreview.h" // for LLPreviewAnimation
|
||||
#include "llscrolllistitem.h"
|
||||
#include "llsingleton.h"
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// RecentAnimationList: holds a list of recently placed animations to query
|
||||
// by the animation explorer, so we don't have to keep the full floater
|
||||
// loaded all the time.
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
class AnimationExplorer;
|
||||
|
||||
class RecentAnimationList
|
||||
: public LLSingleton<RecentAnimationList>
|
||||
{
|
||||
friend class LLSingleton<RecentAnimationList>;
|
||||
|
||||
private:
|
||||
RecentAnimationList();
|
||||
~RecentAnimationList();
|
||||
|
||||
public:
|
||||
struct AnimationEntry
|
||||
{
|
||||
LLUUID animationID; // asset ID of the animation
|
||||
LLUUID playedBy; // object/agent who played this animation
|
||||
F64 time; // time in seconds since viewer start when the animation started
|
||||
};
|
||||
|
||||
std::deque<AnimationEntry> mAnimationList;
|
||||
|
||||
void addAnimation(const LLUUID& id,const LLUUID& playedBy); // called in llviewermessage.cpp
|
||||
void requestList(AnimationExplorer* explorer); // request animation list
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// AnimationExplorer: floater that shows recently played animations and gives
|
||||
// options to preview, stop animations and revoke animation permissions
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
class LLButton;
|
||||
class LLCheckBoxCtrl;
|
||||
class LLMessageSystem;
|
||||
class LLScrollListCtrl;
|
||||
class LLView;
|
||||
|
||||
class AnimationExplorer
|
||||
: public LLFloater
|
||||
{
|
||||
friend class LLFloaterReg;
|
||||
|
||||
private:
|
||||
AnimationExplorer(const LLSD& key);
|
||||
~AnimationExplorer();
|
||||
|
||||
public:
|
||||
/*virtual*/ BOOL postBuild();
|
||||
void addAnimation(const LLUUID& id,const LLUUID& playedBy,F64 time); // called from RecentAnimationList
|
||||
|
||||
// copied from llfloaterbvhpreview.h
|
||||
BOOL handleMouseDown(S32 x, S32 y, MASK mask);
|
||||
BOOL handleMouseUp(S32 x, S32 y, MASK mask);
|
||||
BOOL handleHover(S32 x, S32 y, MASK mask);
|
||||
BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
|
||||
void onMouseCaptureLost();
|
||||
|
||||
void requestNameCallback(LLMessageSystem* msg); // object name query callback
|
||||
|
||||
protected:
|
||||
LLScrollListCtrl* mAnimationScrollList;
|
||||
LLButton* mStopButton;
|
||||
LLButton* mRevokeButton;
|
||||
LLButton* mStopAndRevokeButton;
|
||||
LLCheckBoxCtrl* mNoOwnedAnimationsCheckBox;
|
||||
|
||||
LLView* mPreviewCtrl; // dummy control on the floater where the avatar preview should go
|
||||
LLPointer<LLPreviewAnimation> mAnimationPreview; // actual avatar preview
|
||||
|
||||
S32 mLastMouseX;
|
||||
S32 mLastMouseY;
|
||||
|
||||
LLUUID mCurrentAnimationID; // currently selected animation's asset ID
|
||||
LLUUID mCurrentObject; // object ID that played the currently selected animation
|
||||
|
||||
std::vector<LLUUID> mRequestedIDs; // list of object IDs we requested named for
|
||||
std::map<LLUUID,std::string> mKnownIDs; // known list of names for object IDs
|
||||
|
||||
void draw();
|
||||
void update(); // request list update from RecentAnimationList
|
||||
void updateList(F64 current_timestamp); // update times and playing status in animation list
|
||||
void startMotion(const LLUUID& motionID);
|
||||
|
||||
void onSelectAnimation();
|
||||
void onStopPressed();
|
||||
void onRevokePressed();
|
||||
void onStopAndRevokePressed();
|
||||
void onOwnedCheckToggled();
|
||||
};
|
||||
|
||||
#endif // ANIMATIONEXPLORER_H
|
||||
|
|
@ -1249,5 +1249,9 @@ void LLPreviewAnimation::pan(F32 right, F32 up)
|
|||
mCameraOffset.mV[VZ] = llclamp(mCameraOffset.mV[VZ] + up * mCameraDistance / mCameraZoom, -1.f, 1.f);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// <FS:Zi> Animation Explorer
|
||||
LLVOAvatar* LLPreviewAnimation::getDummyAvatar()
|
||||
{
|
||||
return (LLVOAvatar*) mDummyAvatar;
|
||||
}
|
||||
// </FS:Zi>
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ public:
|
|||
virtual BOOL needsUpdate() { return mNeedsUpdate; }
|
||||
|
||||
LLVOAvatar* getPreviewAvatar();
|
||||
LLVOAvatar* getDummyAvatar(); // <FS:Zi> Animation Explorer
|
||||
|
||||
protected:
|
||||
BOOL mNeedsUpdate;
|
||||
|
|
|
|||
|
|
@ -147,6 +147,7 @@
|
|||
|
||||
// *NOTE: Please add files in alphabetical order to keep merges easy.
|
||||
// ND: And for FS please put yours after this line, for easier merges too
|
||||
#include "animationexplorer.h"
|
||||
#include "ao.h"
|
||||
#include "daeexport.h"
|
||||
#include "floatermedialists.h"
|
||||
|
|
@ -385,6 +386,7 @@ void LLViewerFloaterReg::registerFloaters()
|
|||
|
||||
// *NOTE: Please keep these alphabetized for easier merges
|
||||
// ND: And for FS please put yours after this line, for easier merges too
|
||||
LLFloaterReg::add("animation_explorer", "floater_animation_explorer.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<AnimationExplorer>);
|
||||
LLFloaterReg::add("animation_overrider", "floater_ao.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<FloaterAO>);
|
||||
LLFloaterReg::add("area_search", "floater_fs_area_search.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<FSAreaSearch>);
|
||||
LLFloaterReg::add("contactsets", "floater_contactsets.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<lggContactSetsFloater>);
|
||||
|
|
|
|||
|
|
@ -161,6 +161,8 @@ const static boost::regex NEWLINES("\\n{1}");
|
|||
#pragma warning (disable:4702)
|
||||
#endif
|
||||
|
||||
#include "animationexplorer.h" // <FS:Zi> Animation Explorer
|
||||
|
||||
extern void on_new_message(const LLSD& msg);
|
||||
|
||||
//
|
||||
|
|
@ -5744,6 +5746,12 @@ void process_object_properties(LLMessageSystem *msg, void**user_data)
|
|||
{
|
||||
area_search_floater->processObjectProperties(msg);
|
||||
}
|
||||
|
||||
AnimationExplorer* explorer=LLFloaterReg::findTypedInstance<AnimationExplorer>("animation_explorer");
|
||||
if(explorer)
|
||||
{
|
||||
explorer->requestNameCallback(msg);
|
||||
}
|
||||
}
|
||||
// </FS:Techwolf Lupindo> area search
|
||||
|
||||
|
|
@ -6326,6 +6334,12 @@ void process_avatar_animation(LLMessageSystem *mesgsys, void **user_data)
|
|||
if (!anim_found)
|
||||
{
|
||||
avatarp->mAnimationSources.insert(LLVOAvatar::AnimationSourceMap::value_type(object_id, animation_id));
|
||||
// <FS:Zi> Animation Explorer
|
||||
if(avatarp==gAgentAvatarp)
|
||||
{
|
||||
RecentAnimationList::instance().addAnimation(animation_id,object_id);
|
||||
}
|
||||
// </FS:Zi>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,104 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||
<floater
|
||||
can_close="true"
|
||||
can_drag_on_left="false"
|
||||
can_minimize="false"
|
||||
can_resize="true"
|
||||
height="314"
|
||||
help_topic="fs_animation_explorer"
|
||||
layout="topleft"
|
||||
min_height="314"
|
||||
min_width="400"
|
||||
name="animation_explorer"
|
||||
save_rect="true"
|
||||
title="Animation Explorer"
|
||||
width="524">
|
||||
|
||||
<scroll_list
|
||||
bottom="-4"
|
||||
draw_heading="true"
|
||||
follows="all"
|
||||
layout="topleft"
|
||||
left="4"
|
||||
name="animation_list"
|
||||
top="4"
|
||||
width="256">
|
||||
<scroll_list.column
|
||||
label="Played by"
|
||||
name="played_by" />
|
||||
<scroll_list.column
|
||||
label="Played"
|
||||
name="played" />
|
||||
<scroll_list.column
|
||||
label="Timestamp"
|
||||
name="timestamp"
|
||||
width="-1" />
|
||||
<scroll_list.column
|
||||
label="Animation ID"
|
||||
name="animation_id"
|
||||
width="-1" />
|
||||
<scroll_list.column
|
||||
label="Object ID"
|
||||
name="object_id"
|
||||
width="-1" />
|
||||
</scroll_list>
|
||||
|
||||
<view_border
|
||||
bevel_style="in"
|
||||
follows="top|bottom|right"
|
||||
height="256"
|
||||
name="animation_preview"
|
||||
layout="topleft"
|
||||
left_pad="4"
|
||||
top_delta="0"
|
||||
width="256" />
|
||||
|
||||
<panel
|
||||
follows="bottom|right"
|
||||
height="48"
|
||||
name="buttons_panel"
|
||||
top_pad="4"
|
||||
width="256">
|
||||
|
||||
<button
|
||||
follows="top|right"
|
||||
height="22"
|
||||
label="Stop"
|
||||
layout="topleft"
|
||||
left="0"
|
||||
name="stop_btn"
|
||||
top="0"
|
||||
width="98" />
|
||||
|
||||
<button
|
||||
follows="top|right"
|
||||
height="22"
|
||||
label="Stop and Revoke"
|
||||
layout="topleft"
|
||||
left_pad="4"
|
||||
name="stop_and_revoke_btn"
|
||||
width="154" />
|
||||
|
||||
<button
|
||||
follows="top|right"
|
||||
height="22"
|
||||
label="Revoke"
|
||||
layout="topleft"
|
||||
left="0"
|
||||
name="revoke_btn"
|
||||
top_pad="4"
|
||||
width="98" />
|
||||
|
||||
<check_box
|
||||
follows="top|right"
|
||||
height="22"
|
||||
label="No Owned Animations"
|
||||
left_pad="4"
|
||||
name="no_owned_animations_check"
|
||||
tool_tip="When checked this will filter out all animations that are owned by your avatar, like AO animations or system default animations."
|
||||
top_delta="-4"
|
||||
width="154" />
|
||||
|
||||
</panel>
|
||||
|
||||
</floater>
|
||||
|
|
@ -1170,6 +1170,13 @@
|
|||
function="Floater.Toggle"
|
||||
parameter="sound_explorer" />
|
||||
</menu_item_call>
|
||||
<menu_item_call
|
||||
label="Animation Explorer"
|
||||
name="Animation Explorer">
|
||||
<menu_item_call.on_click
|
||||
function="Floater.Toggle"
|
||||
parameter="animation_explorer" />
|
||||
</menu_item_call>
|
||||
<menu_item_call
|
||||
label="Asset Blacklist"
|
||||
name="asset_blacklist">
|
||||
|
|
|
|||
|
|
@ -2606,4 +2606,8 @@ Try enclosing path to the editor with double quotes.
|
|||
<!-- <FS:Zi> Notify user about preferences settings changes to skin defaults -->
|
||||
<string name="skin_defaults_starlight_location">Showing your current location in the menu bar was disabled as a default for the Starlight skin series.</string>
|
||||
<string name="skin_defaults_starlight_navbar">Showing the navigation bar was enabled as a default for the Starlight skin series.</string>
|
||||
|
||||
<!-- Animation Explorer -->
|
||||
<string name="animation_explorer_seconds_ago">[SECONDS] seconds ago</string>
|
||||
<string name="animation_explorer_still_playing">Still playing</string>
|
||||
</strings>
|
||||
|
|
|
|||
Loading…
Reference in New Issue