diff --git a/indra/newview/floaterao.cpp b/indra/newview/floaterao.cpp index 2038aaa13..7b2618dd8 100644 --- a/indra/newview/floaterao.cpp +++ b/indra/newview/floaterao.cpp @@ -1,7 +1,7 @@ -/** +/** * @file llfloaterao.cpp * @brief clientside animation overrider - * by Skills Hak + * by Skills Hak & Liru Færs */ #include "llviewerprecompiledheaders.h" @@ -10,23 +10,23 @@ #include "llagent.h" #include "llagentcamera.h" -#include "llvoavatarself.h" #include "llanimationstates.h" -#include "lluictrlfactory.h" -#include "llstartup.h" -#include "llpreviewnotecard.h" -#include "llviewertexteditor.h" #include "llcombobox.h" #include "llfirstuse.h" - #include "llinventory.h" +#include "llinventorybridge.h" #include "llinventoryfunctions.h" #include "llinventorypanel.h" #include "llinventorymodelbackgroundfetch.h" -#include "roles_constants.h" +#include "llmemorystream.h" +#include "llnotecard.h" +#include "llpreviewnotecard.h" +#include "llstartup.h" +#include "lltexteditor.h" +#include "lluictrlfactory.h" +#include "llvoavatarself.h" #include "llviewerregion.h" - -#include "llinventorybridge.h" +#include "roles_constants.h" #include @@ -44,15 +44,12 @@ namespace bool is_underwater() { return enable_swim() && gAgentAvatarp && gAgentAvatarp->mBelowWater; } } -class AONotecardCallback : public LLInventoryCallback +class AONotecardCallback final : public LLInventoryCallback { public: - AONotecardCallback(std::string &filename) - { - mFileName = filename; - } + AONotecardCallback(const std::string& filename) : mFileName(filename) {} - void fire(const LLUUID &inv_item) + void fire(const LLUUID &inv_item) override { if (!mFileName.empty()) { @@ -77,8 +74,7 @@ public: while (!file.eof()) { getline(file, line); - line += '\n'; - text->insertText(line); + text->insertText(line + '\n'); } file.close(); @@ -92,16 +88,11 @@ private: std::string mFileName; }; -AOInvTimer* gAOInvTimer = nullptr; - // ------------------------------------------------------- -AOStandTimer* mAOStandTimer; - -AOStandTimer::AOStandTimer() : LLEventTimer( gSavedSettings.getF32("AOStandInterval") ) +AOStandTimer::AOStandTimer() : LLEventTimer(F32_MAX) { - tick(); } AOStandTimer::~AOStandTimer() { @@ -115,11 +106,10 @@ void AOStandTimer::reset() } BOOL AOStandTimer::tick() { - LLFloaterAO::stand_iterator++; // LL_INFOS() << "tick" << LL_ENDL; - LLFloaterAO::ChangeStand(); + if (auto ao = AOSystem::getIfExists()) + ao->cycleStand(); return false; -// return LLFloaterAO::ChangeStand(); //timer is always active now .. } // ------------------------------------------------------- @@ -130,80 +120,74 @@ AOInvTimer::AOInvTimer() : LLEventTimer( 1.0f ) AOInvTimer::~AOInvTimer() { } +bool AOInvTimer::needed() +{ + return LLStartUp::getStartupState() < STATE_INVENTORY_SEND // Haven't done inventory transfer yet + || !LLInventoryModelBackgroundFetch::instance().isEverythingFetched(); // Everything hasn't been fetched yet +} +void AOInvTimer::createIfNeeded() +{ + if (needed()) LLSingleton::getInstance(); + else AOSystem::getInstance(); +} BOOL AOInvTimer::tick() { - if(LLStartUp::getStartupState() >= STATE_INVENTORY_SEND) + if (!gSavedSettings.getBOOL("AOEnabled")) return true; // If disabled on a tick, we don't care anymore + if (!needed()) { - if(LLInventoryModelBackgroundFetch::instance().isEverythingFetched()) - { -// cmdline_printchat("Inventory fetched, loading AO."); - LLFloaterAO::getInstance(); // Initializes everything - return true; - } +// cmdline_printchat("Inventory fetched, loading AO."); + AOSystem::getInstance(); // Initializes everything + return true; } - return !gSavedSettings.getBOOL("AOEnabled"); + return false; +} + +class ObjectNameMatches final : public LLInventoryCollectFunctor +{ +public: + ObjectNameMatches(const std::string& name, const LLUUID& folder) : mName(name), mFolder(folder) {} + virtual ~ObjectNameMatches() {} + bool operator()(LLInventoryCategory* cat, LLInventoryItem* item) override + { + return item && item->getParentUUID() == mFolder && item->getName() == mName; + } +private: + const std::string& mName; + const LLUUID& mFolder; +}; + +static LLUUID invfolderid; +static LLUUID getAssetIDByName(const std::string& name) +{ + if (name.empty()) return LLUUID::null; + + LLViewerInventoryCategory::cat_array_t cats; + LLViewerInventoryItem::item_array_t items; + ObjectNameMatches matches(name, invfolderid); + gInventory.collectDescendentsIf(LLUUID::null, cats, items, false, matches, true); + + return items.empty() ? LLUUID(name) : items[0]->getAssetUUID(); +}; + +void AOSystem::start() +{ + llassert(!instanceExists() && !AOInvTimer::instanceExists()); // This should only be run once! + + auto control(gSavedSettings.getControl("AOEnabled")); + if (control->get()) AOInvTimer::createIfNeeded(); // Start the clock + + control->getSignal()->connect([](LLControlVariable*, const LLSD& enabled) { + if (enabled.asBoolean()) AOInvTimer::createIfNeeded(); // Start the clock + else deleteSingleton(); + }); } // STUFF ------------------------------------------------------- -AOState LLFloaterAO::mAnimationState = STATE_AGENT_IDLE; -int LLFloaterAO::stand_iterator = 0; - -LLUUID LLFloaterAO::invfolderid = LLUUID::null; -LLUUID LLFloaterAO::mCurrentStandId = LLUUID::null; - -LLComboBox* mcomboBox_stands; -LLComboBox* mcomboBox_walks; -LLComboBox* mcomboBox_runs; -LLComboBox* mcomboBox_jumps; -LLComboBox* mcomboBox_sits; -LLComboBox* mcomboBox_gsits; -LLComboBox* mcomboBox_crouchs; -LLComboBox* mcomboBox_cwalks; -LLComboBox* mcomboBox_falls; -LLComboBox* mcomboBox_hovers; -LLComboBox* mcomboBox_flys; -LLComboBox* mcomboBox_flyslows; -LLComboBox* mcomboBox_flyups; -LLComboBox* mcomboBox_flydowns; -LLComboBox* mcomboBox_lands; -LLComboBox* mcomboBox_typings; -LLComboBox* mcomboBox_floats; -LLComboBox* mcomboBox_swims; -LLComboBox* mcomboBox_swimups; -LLComboBox* mcomboBox_swimdowns; -LLComboBox* mcomboBox_standups; -LLComboBox* mcomboBox_prejumps; - -struct struct_overrides -{ - LLUUID orig_id; - LLUUID ao_id = LLUUID::null; - AOState state; -}; -std::vector mAOOverrides; - -struct struct_stands -{ - LLUUID ao_id; - std::string anim_name; -}; -std::vector mAOStands; - LLFloaterAO::LLFloaterAO(const LLSD&) : LLFloater("floater_ao") +, mCombos({}) { LLUICtrlFactory::getInstance()->buildFloater(this, "floater_ao.xml", nullptr, false); - init(); - gSavedSettings.getControl("AOEnabled")->getSignal()->connect(boost::bind(&LLFloaterAO::run)); - gSavedSettings.getControl("AOEnabled")->getSignal()->connect(std::bind([](const LLSD& enabled) - { - // Toggle typing AO the moment we toggle AO - const bool typing = gAgent.getRenderState() & AGENT_STATE_TYPING; - gAgent.sendAnimationRequest(GetAnimIDFromState(STATE_AGENT_TYPING), enabled && typing ? ANIM_REQUEST_START : ANIM_REQUEST_STOP); - }, std::placeholders::_2)); - gSavedSettings.getControl("AOSitsEnabled")->getSignal()->connect(boost::bind(&LLFloaterAO::run)); - sSwimming = is_underwater(); - gSavedSettings.getControl("AOSwimEnabled")->getSignal()->connect(boost::bind(&LLFloaterAO::toggleSwim, boost::bind(is_underwater))); } void LLFloaterAO::onOpen() @@ -213,28 +197,6 @@ void LLFloaterAO::onOpen() LLFloaterAO::~LLFloaterAO() { - mcomboBox_stands = nullptr; - mcomboBox_walks = nullptr; - mcomboBox_runs = nullptr; - mcomboBox_jumps = nullptr; - mcomboBox_sits = nullptr; - mcomboBox_gsits = nullptr; - mcomboBox_crouchs = nullptr; - mcomboBox_cwalks = nullptr; - mcomboBox_falls = nullptr; - mcomboBox_hovers = nullptr; - mcomboBox_flys = nullptr; - mcomboBox_flyslows = nullptr; - mcomboBox_flyups = nullptr; - mcomboBox_flydowns = nullptr; - mcomboBox_lands = nullptr; - mcomboBox_typings = nullptr; - mcomboBox_floats = nullptr; - mcomboBox_swims = nullptr; - mcomboBox_swimups = nullptr; - mcomboBox_swimdowns = nullptr; - mcomboBox_standups = nullptr; - mcomboBox_prejumps = nullptr; // LL_INFOS() << "floater destroyed" << LL_ENDL; } @@ -242,335 +204,339 @@ BOOL LLFloaterAO::postBuild() { gSavedSettings.getControl("AOAdvanced")->getSignal()->connect(boost::bind(&LLFloaterAO::updateLayout, this, _2)); - getChild("reloadcard")->setCommitCallback(boost::bind(&LLFloaterAO::onClickReloadCard)); - getChild("opencard")->setCommitCallback(boost::bind(&LLFloaterAO::onClickOpenCard)); - getChild("newcard")->setCommitCallback(boost::bind(&LLFloaterAO::onClickNewCard)); - getChild("prevstand")->setCommitCallback(boost::bind(&LLFloaterAO::onClickCycleStand, false)); - getChild("nextstand")->setCommitCallback(boost::bind(&LLFloaterAO::onClickCycleStand, true)); - getChild("standtime")->setCommitCallback(boost::bind(&LLFloaterAO::onSpinnerCommit)); + getChild("reloadcard")->setCommitCallback(boost::bind(&LLFloaterAO::onClickReloadCard, this)); + getChild("opencard")->setCommitCallback(boost::bind(&LLFloaterAO::onClickOpenCard, this)); + getChild("newcard")->setCommitCallback(boost::bind(&LLFloaterAO::onClickNewCard, this)); + getChild("prevstand")->setCommitCallback(boost::bind(&LLFloaterAO::onClickCycleStand, this, false)); + getChild("nextstand")->setCommitCallback(boost::bind(&LLFloaterAO::onClickCycleStand, this, true)); + getChild("standtime")->setCommitCallback(boost::bind(&LLFloaterAO::onSpinnerCommit, this)); - (mcomboBox_stands = getChild("stands"))->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit,_1)); - (mcomboBox_walks = getChild("walks"))->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit,_1)); - (mcomboBox_runs = getChild("runs"))->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit,_1)); - (mcomboBox_jumps = getChild("jumps"))->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit,_1)); - (mcomboBox_sits = getChild("sits"))->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit,_1)); - (mcomboBox_gsits = getChild("gsits"))->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit,_1)); - (mcomboBox_crouchs = getChild("crouchs"))->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit,_1)); - (mcomboBox_cwalks = getChild("cwalks"))->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit,_1)); - (mcomboBox_falls = getChild("falls"))->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit, _1)); - (mcomboBox_hovers = getChild("hovers"))->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit, _1)); - (mcomboBox_flys = getChild("flys"))->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit, _1)); - (mcomboBox_flyslows = getChild("flyslows"))->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit, _1)); - (mcomboBox_flyups = getChild("flyups"))->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit, _1)); - (mcomboBox_flydowns = getChild("flydowns"))->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit, _1)); - (mcomboBox_lands = getChild("lands"))->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit, _1)); - (mcomboBox_typings = getChild("typings"))->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit, _1)); - (mcomboBox_floats = getChild("floats"))->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit, _1)); - (mcomboBox_swims = getChild("swims"))->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit, _1)); - (mcomboBox_swimups = getChild("swimups"))->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit, _1)); - (mcomboBox_swimdowns = getChild("swimdowns"))->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit, _1)); - (mcomboBox_standups = getChild("standups"))->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit,_1)); - (mcomboBox_prejumps = getChild("prejumps"))->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit,_1)); + auto ao = AOSystem::getIfExists(); + const auto& cb = boost::bind(&LLFloaterAO::onComboBoxCommit, this, _1); + const auto& setup_combo = [&](const std::string& name, const AOState& state) { + if (auto combo = findChild(name)) + { + combo->setCommitCallback(cb); + LLControlVariablePtr setting = nullptr; + if (auto aop = ao ? ao->mAOOverrides[state] : nullptr) + setting = aop->setting; + else // AO is down or missing override struct(why?), try getting from UI + setting = combo->getControl(combo->getControlName()); + if (setting) combo->add(setting->get().asStringRef(), ADD_BOTTOM, true); + mCombos[state] = combo; + } + }; + setup_combo("stands", STATE_AGENT_IDLE); + setup_combo("walks", STATE_AGENT_WALK); + setup_combo("runs", STATE_AGENT_RUN); + setup_combo("prejumps", STATE_AGENT_PRE_JUMP); + setup_combo("jumps", STATE_AGENT_JUMP); + setup_combo("turnlefts", STATE_AGENT_TURNLEFT); + setup_combo("turnrights", STATE_AGENT_TURNRIGHT); + setup_combo("sits", STATE_AGENT_SIT); + setup_combo("gsits", STATE_AGENT_SIT_GROUND); + setup_combo("hovers", STATE_AGENT_HOVER); + setup_combo("flydowns", STATE_AGENT_HOVER_DOWN); + setup_combo("flyups", STATE_AGENT_HOVER_UP); + setup_combo("crouchs", STATE_AGENT_CROUCH); + setup_combo("cwalks", STATE_AGENT_CROUCHWALK); + setup_combo("falls", STATE_AGENT_FALLDOWN); + setup_combo("standups", STATE_AGENT_STANDUP); + setup_combo("lands", STATE_AGENT_LAND); + setup_combo("flys", STATE_AGENT_FLY); + setup_combo("flyslows", STATE_AGENT_FLYSLOW); + setup_combo("typings", STATE_AGENT_TYPE); + setup_combo("swimdowns", STATE_AGENT_SWIM_DOWN); + setup_combo("swimups", STATE_AGENT_SWIM_UP); + setup_combo("swims", STATE_AGENT_SWIM); + setup_combo("floats", STATE_AGENT_FLOAT); updateLayout(gSavedSettings.getBOOL("AOAdvanced")); + AOSystem::requestConfigNotecard(false); return true; } -void LLFloaterAO::onSpinnerCommit() -{ - if (mAOStandTimer) mAOStandTimer->reset(); -} - -void LLFloaterAO::onComboBoxCommit(LLUICtrl* ctrl) -{ - if (LLComboBox* box = (LLComboBox*)ctrl) - { - if (box->getName() == "stands") - { - stand_iterator = box->getCurrentIndex(); - cmdline_printchat(llformat("Changing stand to %s.",mAOStands[stand_iterator].anim_name.c_str())); - ChangeStand(); - } - else - { - AOState state = getStateFromCombo(box); - std::string stranim = box->getValue().asString(); -// LL_INFOS() << "state " << state << " - " << getAnimationState() << LL_ENDL; - gAgent.sendAnimationRequest(GetAnimIDFromState(state), ANIM_REQUEST_STOP); - bool start_cond = getAnimationState() == state && gSavedSettings.getBOOL("AOEnabled"); - switch (state) - { - case STATE_AGENT_SIT: - case STATE_AGENT_GROUNDSIT: - start_cond &= gAgentAvatarp && gAgentAvatarp->isSitting() && gSavedSettings.getBOOL("AOSitsEnabled"); - break; - default: break; - } - LLUUID anim = getAssetIDByName(stranim); - if (start_cond) gAgent.sendAnimationRequest(anim, ANIM_REQUEST_START); - gSavedPerAccountSettings.setString(ctrl->getControlName(), stranim); - for (auto& ao : mAOOverrides) - { - if (state == ao.state) - { - ao.ao_id = anim; - break; - } - } - } - } -} - void LLFloaterAO::updateLayout(bool advanced) { reshape(advanced ? 800 : 200, getRect().getHeight()); childSetVisible("tabcontainer", advanced); } -void LLFloaterAO::init() +void LLFloaterAO::onSpinnerCommit() const { - mAOStands.clear(); - mAOOverrides.clear(); - - struct_overrides overrideloader; - overrideloader.orig_id = ANIM_AGENT_WALK; overrideloader.state = STATE_AGENT_WALK; mAOOverrides.push_back(overrideloader); - overrideloader.orig_id = ANIM_AGENT_RUN; overrideloader.state = STATE_AGENT_RUN; mAOOverrides.push_back(overrideloader); - overrideloader.orig_id = ANIM_AGENT_PRE_JUMP; overrideloader.state = STATE_AGENT_PRE_JUMP; mAOOverrides.push_back(overrideloader); - overrideloader.orig_id = ANIM_AGENT_JUMP; overrideloader.state = STATE_AGENT_JUMP; mAOOverrides.push_back(overrideloader); - overrideloader.orig_id = ANIM_AGENT_TURNLEFT; overrideloader.state = STATE_AGENT_TURNLEFT; mAOOverrides.push_back(overrideloader); - overrideloader.orig_id = ANIM_AGENT_TURNRIGHT; overrideloader.state = STATE_AGENT_TURNRIGHT; mAOOverrides.push_back(overrideloader); - - overrideloader.orig_id = ANIM_AGENT_SIT; overrideloader.state = STATE_AGENT_SIT; mAOOverrides.push_back(overrideloader); - overrideloader.orig_id = ANIM_AGENT_SIT_FEMALE; overrideloader.state = STATE_AGENT_SIT; mAOOverrides.push_back(overrideloader); - overrideloader.orig_id = ANIM_AGENT_SIT_GENERIC; overrideloader.state = STATE_AGENT_SIT; mAOOverrides.push_back(overrideloader); - overrideloader.orig_id = ANIM_AGENT_SIT_GROUND; overrideloader.state = STATE_AGENT_GROUNDSIT; mAOOverrides.push_back(overrideloader); - overrideloader.orig_id = ANIM_AGENT_SIT_GROUND_CONSTRAINED; overrideloader.state = STATE_AGENT_GROUNDSIT; mAOOverrides.push_back(overrideloader); - - overrideloader.orig_id = ANIM_AGENT_HOVER; overrideloader.state = STATE_AGENT_HOVER; mAOOverrides.push_back(overrideloader); - overrideloader.orig_id = ANIM_AGENT_HOVER_DOWN; overrideloader.state = STATE_AGENT_HOVER_DOWN; mAOOverrides.push_back(overrideloader); - overrideloader.orig_id = ANIM_AGENT_HOVER_UP; overrideloader.state = STATE_AGENT_HOVER_UP; mAOOverrides.push_back(overrideloader); - - overrideloader.orig_id = ANIM_AGENT_CROUCH; overrideloader.state = STATE_AGENT_CROUCH; mAOOverrides.push_back(overrideloader); - overrideloader.orig_id = ANIM_AGENT_CROUCHWALK; overrideloader.state = STATE_AGENT_CROUCHWALK; mAOOverrides.push_back(overrideloader); - - overrideloader.orig_id = ANIM_AGENT_FALLDOWN; overrideloader.state = STATE_AGENT_FALLDOWN; mAOOverrides.push_back(overrideloader); - overrideloader.orig_id = ANIM_AGENT_STANDUP; overrideloader.state = STATE_AGENT_STANDUP; mAOOverrides.push_back(overrideloader); - overrideloader.orig_id = ANIM_AGENT_LAND; overrideloader.state = STATE_AGENT_LAND; mAOOverrides.push_back(overrideloader); - overrideloader.orig_id = ANIM_AGENT_TYPE; overrideloader.state = STATE_AGENT_TYPING; mAOOverrides.push_back(overrideloader); - - overrideloader.orig_id = ANIM_AGENT_FLY; overrideloader.state = STATE_AGENT_FLY; mAOOverrides.push_back(overrideloader); - overrideloader.orig_id = ANIM_AGENT_FLYSLOW; overrideloader.state = STATE_AGENT_FLYSLOW; mAOOverrides.push_back(overrideloader); - - overrideloader.orig_id = ANIM_AGENT_HOVER; overrideloader.state = STATE_AGENT_FLOAT; mAOOverrides.push_back(overrideloader); - overrideloader.orig_id = ANIM_AGENT_HOVER_DOWN; overrideloader.state = STATE_AGENT_SWIM_DOWN; mAOOverrides.push_back(overrideloader); - overrideloader.orig_id = ANIM_AGENT_HOVER_UP; overrideloader.state = STATE_AGENT_SWIM_UP; mAOOverrides.push_back(overrideloader); - - overrideloader.orig_id = ANIM_AGENT_FLY; overrideloader.state = STATE_AGENT_SWIM; mAOOverrides.push_back(overrideloader); - - bool success = true; - - if(LLStartUp::getStartupState() >= STATE_INVENTORY_SEND) - { - if(LLInventoryModelBackgroundFetch::instance().isEverythingFetched()) - { - LLUUID configncitem = (LLUUID)gSavedPerAccountSettings.getString("AOConfigNotecardID"); - if (configncitem.notNull()) - { - success = false; - const LLInventoryItem* item = gInventory.getItem(configncitem); - if(item) - { - if (gAgent.allowOperation(PERM_COPY, item->getPermissions(),GP_OBJECT_MANIPULATE) || gAgent.isGodlike()) - { - if(!item->getAssetUUID().isNull()) - { - LLUUID* new_uuid = new LLUUID(configncitem); - LLHost source_sim = LLHost::invalid; - invfolderid = item->getParentUUID(); - gAssetStorage->getInvItemAsset(source_sim, - gAgent.getID(), - gAgent.getSessionID(), - item->getPermissions().getOwner(), - LLUUID::null, - item->getUUID(), - item->getAssetUUID(), - item->getType(), - &onNotecardLoadComplete, - (void*)new_uuid, - true); - success = true; - } - } - } - } - } - } - - if (!success) - { - cmdline_printchat("Could not read the specified Config Notecard"); - } - -// mAnimationState = STATE_AGENT_IDLE; -// mCurrentStandId = LLUUID::null; -// setAnimationState(STATE_AGENT_IDLE); + if (auto ao = AOSystem::getIfExists()) + ao->mAOStandTimer.reset(); } - -void LLFloaterAO::run() +void LLFloaterAO::onComboBoxCommit(LLUICtrl* ctrl) const { - setAnimationState(STATE_AGENT_IDLE); // reset state - AOState state = getAnimationState(); // check if sitting or hovering - bool enabled = gSavedSettings.getBOOL("AOEnabled"); - if (state == STATE_AGENT_IDLE || state == STATE_AGENT_STAND) + if (LLComboBox* box = (LLComboBox*)ctrl) { - if (enabled) + std::string stranim = box->getValue().asString(); + if (auto ao = AOSystem::getIfExists()) { - if (mAOStandTimer) + if (box == mCombos[STATE_AGENT_IDLE]) { - mAOStandTimer->reset(); - ChangeStand(); + ao->stand_iterator = box->getCurrentIndex(); + llassert(ao->stand_iterator < ao->mAOStands.size()); + const auto& name = ao->mAOStands[ao->stand_iterator].anim_name; + llassert(name == box->getValue().asStringRef()); + cmdline_printchat("Changing stand to " + name + '.'); + ao->updateStand(); + ao->mAOStandTimer.reset(); } else { - mAOStandTimer = new AOStandTimer(); + AOState state = getStateFromCombo(box); + llassert(state != STATE_AGENT_END); + const LLUUID& anim = getAssetIDByName(stranim); + if (auto aop = ao->mAOOverrides[state]) + { +// LL_INFOS() << "state " << state << " - " << aop->playing() << LL_ENDL; + bool was_playing = aop->playing; + if (was_playing) aop->play(false); + aop->ao_id = anim; + if (was_playing) aop->play(); + } } } - else - { - stopMotion(getCurrentStandId(), true); //stop stand first then set state - setAnimationState(STATE_AGENT_IDLE); - } - } - else - { - bool sit = false; - switch (state) - { - case STATE_AGENT_SIT: - case STATE_AGENT_GROUNDSIT: - sit = true; - stopMotion(getCurrentStandId(), true); // Stop the current stand - break; - default: break; - } - gAgent.sendAnimationRequest(GetAnimIDFromState(state), (enabled && (!sit || gSavedSettings.getBOOL("AOSitsEnabled"))) ? ANIM_REQUEST_START : ANIM_REQUEST_STOP); + gSavedPerAccountSettings.setString(ctrl->getControlName(), stranim); } } -void LLFloaterAO::typing(bool start) +void LLFloaterAO::onClickCycleStand(bool next) const +{ + auto ao = AOSystem::getIfExists(); + if (!ao) return; + auto stand = ao->cycleStand(next, false); + ao->mAOStandTimer.reset(); + if (stand < 0) return; + cmdline_printchat("Changed stand to " + ao->mAOStands[stand].anim_name + '.'); +} + +void LLFloaterAO::onClickReloadCard() const +{ + AOSystem::instance().initSingleton(); +} + +void LLFloaterAO::onClickOpenCard() const +{ + if (!AOInvTimer::needed()) + { + LLUUID config_nc_id = (LLUUID)gSavedPerAccountSettings.getString("AOConfigNotecardID"); + if (config_nc_id.notNull()) + if (LLViewerInventoryItem* item = gInventory.getItem(config_nc_id)) + if (gAgent.allowOperation(PERM_COPY, item->getPermissions(), GP_OBJECT_MANIPULATE) || gAgent.isGodlike()) + if(!item->getAssetUUID().isNull()) + open_notecard(item, "Note: " + item->getName(), LLUUID::null, false); + } +} + +void LLFloaterAO::onClickNewCard() const +{ + // load the template file from app_settings/ao_template.ini then + // create a new properly-formatted notecard in the user's inventory + std::string ao_template = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "ao_template.ini"); + if (ao_template.empty()) + { + ao_template = "#Can't find ao_template.ini in app_settings!"; + LL_WARNS() << ao_template << LL_ENDL; + ao_template += "\n#ZHAO II Style Notecards are supported."; + } + + create_inventory_item(gAgentID, gAgentSessionID, + LLUUID::null, LLTransactionID::tnull, "New AO Notecard", + "Drop this notecard in your AO window to use", LLAssetType::AT_NOTECARD, + LLInventoryType::IT_NOTECARD, NOT_WEARABLE, PERM_ALL, new AONotecardCallback(ao_template)); +} + +AOState LLFloaterAO::getStateFromCombo(const LLComboBox* combo) const +{ + if (combo) + { + const auto& end = mCombos.end(); + const auto it = std::find(mCombos.begin(), end, combo); + if (it != end) return (AOState)std::distance(mCombos.begin(), it); + } + return STATE_AGENT_END; +} + +AOSystem::overrides::overrides(const char* setting_name) + : setting(setting_name ? gSavedPerAccountSettings.getControl("AODefault" + std::string(setting_name)) : nullptr) + , playing(false) +{ +} + +bool AOSystem::overrides::play_condition() const +{ + // Stop stand first then play + instance().stopCurrentStand(); + return false; +} + +void AOSystem::overrides::play(bool start) +{ + if (playing == start) return; +// LL_INFOS() << "st" << (start ? "art" : "op") << " override: " << aop->getOverride() << LL_ENDL; + // We can always stop, but starting is particular + if (start) + { + if (play_condition()) + return; + } + else if (playing && !isLowPriority()) // Stands were turned off if this isn't a low priority overrides + { + if (!isAgentAvatarValid() && !gAgentAvatarp->isSitting() && !gAgent.getFlying()) // check if sitting or hovering + instance().stand().play(); + } + playing = start; + gAgent.sendAnimationRequest(ao_id, start ? ANIM_REQUEST_START : ANIM_REQUEST_STOP); +} + +bool AOSystem::override_stand::play_condition() const +{ + // Do not call base, stands do their own thing + // stands have lowest priority + return (!isAgentAvatarValid() || gAgentAvatarp->isSitting()) + && (gAgentCamera.cameraMouselook() && gSavedSettings.getBOOL("AONoStandsInMouselook")); +} + +bool AOSystem::override_sit::play_condition() const +{ + overrides::play_condition(); + return !gSavedSettings.getBOOL("AOSitsEnabled"); +} + +bool AOSystem::override_stand::overrideAnim(bool swimming, const LLUUID& anim) const +{ + return anim == ANIM_AGENT_STAND; +} + +static AOState getSitType() +{ + return gAgentAvatarp->getParent() ? STATE_AGENT_SIT : STATE_AGENT_SIT_GROUND; +} + +AOSystem::AOSystem() +: stand_iterator(0) +, mAOOverrides({}) +{ +// TODO: When we move to C++20 and when GCC and MSVC support it (at the time of writing, neither fully do), use __VA_OPT__ here instead. +#define ANY_OVERRIDE(which, state, ...) mAOOverrides[STATE_AGENT_##state] = new which(ANIM_AGENT_##state, ##__VA_ARGS__) +#define BASIC_OVERRIDE(state, ...) ANY_OVERRIDE(override_single, ##state, ##__VA_ARGS__) + mAOOverrides[STATE_AGENT_IDLE] = new override_stand(); + BASIC_OVERRIDE(WALK, "Walk"); + BASIC_OVERRIDE(RUN, "Run"); + BASIC_OVERRIDE(PRE_JUMP, "PreJump"); + BASIC_OVERRIDE(JUMP, "Jump"); + BASIC_OVERRIDE(TURNLEFT); + BASIC_OVERRIDE(TURNRIGHT); + +#define SIT_OVERRIDE(control, state, ...) mAOOverrides[STATE_AGENT_##state] = new override_sit(uuid_set_t{ANIM_AGENT_##state, __VA_ARGS__}, control) + SIT_OVERRIDE("Sit", SIT, ANIM_AGENT_SIT_FEMALE, ANIM_AGENT_SIT_GENERIC); + SIT_OVERRIDE("GroundSit", SIT_GROUND, ANIM_AGENT_SIT_GROUND_CONSTRAINED); +#undef SIT_OVERRIDE + + BASIC_OVERRIDE(HOVER, "Hover", false); + BASIC_OVERRIDE(HOVER_DOWN, "FlyDown", false); + BASIC_OVERRIDE(HOVER_UP, "FlyUp", false); + + BASIC_OVERRIDE(CROUCH, "Crouch"); + BASIC_OVERRIDE(CROUCHWALK, "CrouchWalk"); + BASIC_OVERRIDE(FALLDOWN, "Fall"); + BASIC_OVERRIDE(STANDUP, "StandUp"); + BASIC_OVERRIDE(LAND, "Land"); + + BASIC_OVERRIDE(FLY, "Fly", false); + BASIC_OVERRIDE(FLYSLOW, "FlySlow", false); + + ANY_OVERRIDE(override_low_priority, TYPE, "Typing"); + + mAOOverrides[STATE_AGENT_SWIM_DOWN] = new override_single(ANIM_AGENT_HOVER_DOWN, "SwimDown", true); + mAOOverrides[STATE_AGENT_SWIM_UP] = new override_single(ANIM_AGENT_HOVER_UP, "SwimUp", true); + mAOOverrides[STATE_AGENT_SWIM] = new override_single(ANIM_AGENT_FLY, "Swim", true); + mAOOverrides[STATE_AGENT_FLOAT] = new override_single(ANIM_AGENT_HOVER, "Float", true); +#undef BASIC_OVERRIDE +#undef ANY_OVERRIDE + + sSwimming = is_underwater(); + mConnections[0] = gSavedSettings.getControl("AOSitsEnabled")->getSignal()->connect([this](LLControlVariable*, const LLSD& val) { + if (!isAgentAvatarValid() || !gAgentAvatarp->isSitting()) return; + gAgent.sendAnimationRequest(mAOOverrides[getSitType()]->ao_id, val.asBoolean() ? ANIM_REQUEST_START : ANIM_REQUEST_STOP); + }); + mConnections[1] = gSavedSettings.getControl("AOSwimEnabled")->getSignal()->connect(boost::bind(&AOSystem::toggleSwim, this, boost::bind(is_underwater))); +} + +AOSystem::~AOSystem() +{ + stopAllOverrides(); + for (auto& ao : mAOOverrides) + { + if (ao) + { + delete ao; + ao = nullptr; + } + } +} + +void AOSystem::requestConfigNotecard(bool reload) +{ + LLUUID configncitem = (LLUUID)gSavedPerAccountSettings.getString("AOConfigNotecardID"); + if (configncitem.notNull()) + { + bool success = false; + if (const LLInventoryItem* item = gInventory.getItem(configncitem)) + { + if (gAgent.allowOperation(PERM_COPY, item->getPermissions(), GP_OBJECT_MANIPULATE) || gAgent.isGodlike()) + { + if (item->getAssetUUID().notNull()) + { + invfolderid = item->getParentUUID(); + gAssetStorage->getInvItemAsset(LLHost::invalid, + gAgentID, + gAgentSessionID, + item->getPermissions().getOwner(), + LLUUID::null, + item->getUUID(), + item->getAssetUUID(), + item->getType(), + [reload](LLVFS* vfs, const LLUUID& asset_uuid, LLAssetType::EType type, void* user_data, S32 status, LLExtStat ext_status) + { + parseNotecard(vfs, asset_uuid, type, status, reload); + }, + nullptr, + true); + success = true; + } + } + } + if (!success) cmdline_printchat("Could not read the specified Config Notecard"); + } +} + +void AOSystem::initSingleton() +{ + mAOStands.clear(); + requestConfigNotecard(); +} + +void AOSystem::typing(bool start) { uuid_vec_t anims; // If we're stopping, stop regardless, just in case the setting was toggled during (e.g.: keyboard shortcut) if (!start || gSavedSettings.getBOOL("PlayTypingAnim")) // Linden typing anims.push_back(ANIM_AGENT_TYPE); - if (gSavedSettings.getBOOL("AOEnabled")) // Typing override - anims.push_back(GetAnimIDFromState(STATE_AGENT_TYPING)); + if (const auto& ao = getIfExists()) // Typing override + anims.push_back(ao->mAOOverrides[STATE_AGENT_TYPE]->getOverride()); if (anims.empty()) return; gAgent.sendAnimationRequests(anims, start ? ANIM_REQUEST_START : ANIM_REQUEST_STOP); } -AOState LLFloaterAO::flyToSwimState(const AOState& state) +AOState GetStateFromToken(const std::string& strtoken) { - switch (state) - { - case STATE_AGENT_HOVER: return STATE_AGENT_FLOAT; - case STATE_AGENT_FLY: return STATE_AGENT_SWIM; - case STATE_AGENT_HOVER_UP: return STATE_AGENT_SWIM_UP; - case STATE_AGENT_HOVER_DOWN: return STATE_AGENT_SWIM_DOWN; - default: return state; - } -} - -AOState LLFloaterAO::swimToFlyState(const AOState& state) -{ - switch (state) - { - case STATE_AGENT_FLOAT: return STATE_AGENT_HOVER; - case STATE_AGENT_SWIM: return STATE_AGENT_FLY; - case STATE_AGENT_SWIM_UP: return STATE_AGENT_HOVER_UP; - case STATE_AGENT_SWIM_DOWN: return STATE_AGENT_HOVER_DOWN; - default: return state; - } -} - -AOState LLFloaterAO::getAnimationState() -{ - if (gAgentAvatarp) - { - if (gAgentAvatarp->isSitting()) setAnimationState(STATE_AGENT_SIT); - else if (gAgent.getFlying()) setAnimationState(STATE_AGENT_HOVER); - } - return mAnimationState; -} - -void LLFloaterAO::setAnimationState(const AOState& state) -{ - mAnimationState = sSwimming ? flyToSwimState(state) : state; -} - -LLUUID LLFloaterAO::getCurrentStandId() -{ - return mCurrentStandId; -} - -void LLFloaterAO::setCurrentStandId(const LLUUID& id) -{ - mCurrentStandId = id; -} - -bool LLFloaterAO::swimCheck(const AOState& state) -{ - switch (state) - { - case STATE_AGENT_HOVER: - case STATE_AGENT_FLY: - case STATE_AGENT_HOVER_UP: - case STATE_AGENT_HOVER_DOWN: - return !sSwimming; - case STATE_AGENT_FLOAT: - case STATE_AGENT_SWIM: - case STATE_AGENT_SWIM_UP: - case STATE_AGENT_SWIM_DOWN: - return sSwimming; - default: return true; - } -} - -LLUUID LLFloaterAO::GetAnimID(const LLUUID& id) -{ - for (const auto& ao : mAOOverrides) - { - if (swimCheck(ao.state) && ao.orig_id == id) - { - return ao.ao_id; - } - } - return LLUUID::null; -} - -AOState LLFloaterAO::GetStateFromAnimID(const LLUUID& id) -{ - for (const auto& ao : mAOOverrides) - { - if (swimCheck(ao.state) && ao.orig_id == id) return ao.state; - } - return STATE_AGENT_IDLE; -} - -LLUUID LLFloaterAO::GetAnimIDFromState(const AOState& state) -{ - for (const auto& ao : mAOOverrides) - { - if (ao.state == state) return ao.ao_id; - } - return LLUUID::null; -} - -AOState LLFloaterAO::GetStateFromToken(std::string strtoken) -{ - if (strtoken == "[ Sitting On Ground ]") return STATE_AGENT_GROUNDSIT; + if (strtoken == "[ Sitting On Ground ]") return STATE_AGENT_SIT_GROUND; if (strtoken == "[ Sitting ]") return STATE_AGENT_SIT; if (strtoken == "[ Crouching ]") return STATE_AGENT_CROUCH; if (strtoken == "[ Crouch Walking ]") return STATE_AGENT_CROUCHWALK; @@ -588,297 +554,165 @@ AOState LLFloaterAO::GetStateFromToken(std::string strtoken) if (strtoken == "[ Turning Left ]") return STATE_AGENT_TURNLEFT; if (strtoken == "[ Walking ]") return STATE_AGENT_WALK; if (strtoken == "[ Landing ]") return STATE_AGENT_LAND; - if (strtoken == "[ Standing ]") return STATE_AGENT_STAND; + if (strtoken == "[ Standing ]") return STATE_AGENT_IDLE; if (strtoken == "[ Swimming Down ]") return STATE_AGENT_SWIM_DOWN; if (strtoken == "[ Swimming Up ]") return STATE_AGENT_SWIM_UP; if (strtoken == "[ Swimming Forward ]") return STATE_AGENT_SWIM; if (strtoken == "[ Floating ]") return STATE_AGENT_FLOAT; - if (strtoken == "[ Typing ]") return STATE_AGENT_TYPING; - return STATE_AGENT_IDLE; + if (strtoken == "[ Typing ]") return STATE_AGENT_TYPE; + return STATE_AGENT_END; } -void LLFloaterAO::onClickCycleStand(bool next) +void AOSystem::updateStand() { - if (mAOStands.empty()) return; - stand_iterator += (next ? 1 : -1); - if (stand_iterator < 0) stand_iterator = int( mAOStands.size()-stand_iterator); - if (stand_iterator > int( mAOStands.size()-1)) stand_iterator = 0; - cmdline_printchat(llformat("Changing stand to %s.",mAOStands[stand_iterator].anim_name.c_str())); - ChangeStand(); + auto& stand_ao = stand(); + bool is_standing = stand_ao.playing; + if (is_standing) stand_ao.play(false); // Stop stand first + stand_ao.update(mAOStands, stand_iterator); // Now update stand + if (is_standing && !mAOStands.empty()) // Play stand if needed + stand_ao.play(); } -void LLFloaterAO::ChangeStand() +int AOSystem::cycleStand(bool next, bool random) { - if (gSavedSettings.getBOOL("AOEnabled")) + if (mAOStands.empty()) return -1; + const int size = mAOStands.size(); + if (size > 1) { - if (gAgentAvatarp) - { - if (gSavedSettings.getBOOL("AONoStandsInMouselook") && gAgentCamera.cameraMouselook()) return; - - if (gAgentAvatarp->isSitting()) - { -// stopMotion(getCurrentStandId(), true); //stop stand first then set state -// if (getAnimationState() != STATE_AGENT_GROUNDSIT) setAnimationState(STATE_AGENT_SIT); -// setCurrentStandId(LLUUID::null); - return; - } - } - AOState state = getAnimationState(); - if (state == STATE_AGENT_IDLE || state == STATE_AGENT_STAND)// stands have lowest priority - { - if (mAOStands.empty()) return; - if (gSavedSettings.getBOOL("AOStandRandomize")) - { - stand_iterator = ll_rand(mAOStands.size()-1); - } - if (stand_iterator < 0) stand_iterator = int( mAOStands.size()-stand_iterator); - if (stand_iterator > int( mAOStands.size()-1)) stand_iterator = 0; - - int stand_iterator_previous = stand_iterator -1; - - if (stand_iterator_previous < 0) stand_iterator_previous = int( mAOStands.size()-1); - - if (mAOStands[stand_iterator].ao_id.notNull()) - { - stopMotion(getCurrentStandId(), true); //stop stand first then set state - startMotion(mAOStands[stand_iterator].ao_id, true); - - setAnimationState(STATE_AGENT_STAND); - setCurrentStandId(mAOStands[stand_iterator].ao_id); - if (mcomboBox_stands) mcomboBox_stands->selectNthItem(stand_iterator); -// LL_INFOS() << "changing stand to " << mAOStands[stand_iterator].anim_name << LL_ENDL; - } - } - } - else stopMotion(getCurrentStandId(), true); -} - -void LLFloaterAO::toggleSwim(bool underwater) -{ - static const LLCachedControl enabled(gSavedSettings, "AOEnabled", false); - - sSwimming = underwater && enable_swim(); - - // Don't send requests if we have the AO disabled. - if (enabled) - { - AOState state = getAnimationState(); - if (state != STATE_AGENT_IDLE && state != STATE_AGENT_STAND) // Don't bother if we're just standing or idle (Who pushed us?!) - { - // Stop all of the previous states - constexpr std::array swim_states = { STATE_AGENT_FLOAT, STATE_AGENT_SWIM, STATE_AGENT_SWIM_UP, STATE_AGENT_SWIM_DOWN }; - constexpr std::array fly_states = { STATE_AGENT_HOVER, STATE_AGENT_FLY, STATE_AGENT_HOVER_UP, STATE_AGENT_HOVER_DOWN }; - uuid_vec_t vec; - for (const auto& state : sSwimming ? fly_states : swim_states) - vec.push_back(GetAnimIDFromState(state)); - gAgent.sendAnimationRequests(vec, ANIM_REQUEST_STOP); - // Process new animations - gAgentAvatarp->processAnimationStateChanges(); - } - } -} - -void LLFloaterAO::doMotion(const LLUUID& id, bool start, bool stand) -{ - if (id.isNull()) return; - LLUUID anim = id; - if (stand) - { - if (start) - { - if (gAgentAvatarp && gAgentAvatarp->isSitting()) - return; - } - else setAnimationState(STATE_AGENT_IDLE); - } - else - { - anim = GetAnimID(id); - if (anim.isNull() || !gSavedSettings.getBOOL("AOEnabled")) return; - AOState state = GetStateFromAnimID(id); - if (start) - { - stopMotion(getCurrentStandId(), true); //stop stand first then set state - setAnimationState(state); -// LL_INFOS() << " state " << getAnimationState() << " start anim " << id << " overriding with " << anim << LL_ENDL; - if (state == STATE_AGENT_SIT && !gSavedSettings.getBOOL("AOSitsEnabled")) return; - } + if (random && gSavedSettings.getBOOL("AOStandRandomize")) + for (auto previous = stand_iterator; previous == stand_iterator; + stand_iterator = ll_rand(size)); else { -// LL_INFOS() << " state " << getAnimationState() << "/" << state << "(now 0) stop anim " << id << " overriding with " << anim << LL_ENDL; - if (getAnimationState() == state) setAnimationState(STATE_AGENT_IDLE); - ChangeStand(); // startMotion(getCurrentStandId(), true); + stand_iterator += next ? 1 : -1; + // Wrap around + if (stand_iterator == size) stand_iterator = 0; + else if (stand_iterator == -1) stand_iterator = size - 1; } + if (auto floater = LLFloaterAO::findInstance()) + if (auto combo = floater->getComboFromState(STATE_AGENT_IDLE)) + combo->selectNthItem(stand_iterator); +// LL_INFOS() << "changing stand to " << mAOStands[stand_iterator].anim_name << LL_ENDL; } - gAgent.sendAnimationRequest(anim, start ? ANIM_REQUEST_START : ANIM_REQUEST_STOP); + updateStand(); + return stand_iterator; } -void LLFloaterAO::onClickReloadCard() +void AOSystem::toggleSwim(bool underwater) { - if (LLInventoryModelBackgroundFetch::instance().isEverythingFetched()) - { - init(); - } -} + sSwimming = underwater && enable_swim(); -void LLFloaterAO::onClickOpenCard() -{ - if (LLInventoryModelBackgroundFetch::instance().isEverythingFetched()) + if (isStanding()) return; // Don't bother if we're just standing (Who pushed us?!) + + typedef std::array flies_t; + // Stop all of the previous states +#define AOO(state) mAOOverrides[STATE_AGENT_##state] + const flies_t swims = { AOO(FLOAT), AOO(SWIM), AOO(SWIM_UP), AOO(SWIM_DOWN) }; + const flies_t flies = { AOO(HOVER), AOO(FLY), AOO(HOVER_UP), AOO(HOVER_DOWN) }; +#undef AOO + const auto& oldaos = sSwimming ? flies : swims; + const auto& newaos = sSwimming ? swims : flies; + + for (auto i = 0; i < oldaos.size(); ++i) { - LLUUID configncitem = (LLUUID)gSavedPerAccountSettings.getString("AOConfigNotecardID"); - if (configncitem.notNull()) + auto& old = *oldaos[i]; + if (old.playing) { - if (LLViewerInventoryItem* item = gInventory.getItem(configncitem)) - { - if (gAgent.allowOperation(PERM_COPY, item->getPermissions(),GP_OBJECT_MANIPULATE) || gAgent.isGodlike()) - { - if(!item->getAssetUUID().isNull()) - open_notecard(item, "Note: " + item->getName(), LLUUID::null, false); - } - } + old.play(false); + newaos[i]->play(); } } } -void LLFloaterAO::onClickNewCard() +void AOSystem::doMotion(const LLUUID& id, bool start) { - // load the template file from app_settings/ao_template.ini then - // create a new properly-formatted notecard in the user's inventory - std::string ao_template = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "ao_template.ini"); - if (!ao_template.empty()) + if (id.isNull() || !gAgentAvatarp) return; + + overrides* aop = nullptr; + AOState state = STATE_AGENT_IDLE; + for (U8 i = STATE_AGENT_IDLE; !aop && i < STATE_AGENT_END; ++i) { - LLPointer cb = new AONotecardCallback(ao_template); - create_inventory_item(gAgentID, gAgentSessionID, - LLUUID::null, LLTransactionID::tnull, "New AO Notecard", - "Drop this notecard in your AO window to use", LLAssetType::AT_NOTECARD, - LLInventoryType::IT_NOTECARD, NOT_WEARABLE, PERM_ALL, cb); - } - else - { - LL_WARNS() << "Can't find ao_template.ini in app_settings!" << LL_ENDL; - } -} - -struct AOAssetInfo -{ - std::string path, name; -}; - -AOState LLFloaterAO::getStateFromCombo(const LLComboBox* combo) -{ - if (combo == mcomboBox_stands) return STATE_AGENT_STAND; - if (combo == mcomboBox_walks) return STATE_AGENT_WALK; - if (combo == mcomboBox_runs) return STATE_AGENT_RUN; - if (combo == mcomboBox_jumps) return STATE_AGENT_JUMP; - if (combo == mcomboBox_sits) return STATE_AGENT_SIT; - if (combo == mcomboBox_gsits) return STATE_AGENT_GROUNDSIT; - if (combo == mcomboBox_crouchs) return STATE_AGENT_CROUCH; - if (combo == mcomboBox_cwalks) return STATE_AGENT_CROUCHWALK; - if (combo == mcomboBox_falls) return STATE_AGENT_FALLDOWN; - if (combo == mcomboBox_hovers) return STATE_AGENT_HOVER; - if (combo == mcomboBox_flys) return STATE_AGENT_FLY; - if (combo == mcomboBox_flyslows) return STATE_AGENT_FLYSLOW; - if (combo == mcomboBox_flyups) return STATE_AGENT_HOVER_UP; - if (combo == mcomboBox_flydowns) return STATE_AGENT_HOVER_DOWN; - if (combo == mcomboBox_lands) return STATE_AGENT_LAND; - if (combo == mcomboBox_typings) return STATE_AGENT_TYPING; - if (combo == mcomboBox_floats) return STATE_AGENT_FLOAT; - if (combo == mcomboBox_swims) return STATE_AGENT_SWIM; - if (combo == mcomboBox_swimups) return STATE_AGENT_SWIM_UP; - if (combo == mcomboBox_swimdowns) return STATE_AGENT_SWIM_DOWN; - if (combo == mcomboBox_standups) return STATE_AGENT_STANDUP; - if (combo == mcomboBox_prejumps) return STATE_AGENT_PRE_JUMP; - return STATE_AGENT_IDLE; -} - -LLComboBox* LLFloaterAO::getComboFromState(const AOState& state) -{ - switch (state) - { - case STATE_AGENT_STAND: return mcomboBox_stands; - case STATE_AGENT_WALK: return mcomboBox_walks; - case STATE_AGENT_RUN: return mcomboBox_runs; - case STATE_AGENT_JUMP: return mcomboBox_jumps; - case STATE_AGENT_SIT: return mcomboBox_sits; - case STATE_AGENT_GROUNDSIT: return mcomboBox_gsits; - case STATE_AGENT_CROUCH: return mcomboBox_crouchs; - case STATE_AGENT_CROUCHWALK: return mcomboBox_cwalks; - case STATE_AGENT_FALLDOWN: return mcomboBox_falls; - case STATE_AGENT_HOVER: return mcomboBox_hovers; - case STATE_AGENT_FLY: return mcomboBox_flys; - case STATE_AGENT_FLYSLOW: return mcomboBox_flyslows; - case STATE_AGENT_HOVER_UP: return mcomboBox_flyups; - case STATE_AGENT_HOVER_DOWN: return mcomboBox_flydowns; - case STATE_AGENT_LAND: return mcomboBox_lands; - case STATE_AGENT_TYPING: return mcomboBox_typings; - case STATE_AGENT_FLOAT: return mcomboBox_floats; - case STATE_AGENT_SWIM: return mcomboBox_swims; - case STATE_AGENT_SWIM_UP: return mcomboBox_swimups; - case STATE_AGENT_SWIM_DOWN: return mcomboBox_swimdowns; - case STATE_AGENT_STANDUP: return mcomboBox_standups; - case STATE_AGENT_PRE_JUMP: return mcomboBox_prejumps; - default: return nullptr; - } -} - -void LLFloaterAO::onNotecardLoadComplete(LLVFS *vfs,const LLUUID& asset_uuid,LLAssetType::EType type,void* user_data, S32 status, LLExtStat ext_status) -{ - if(status == LL_ERR_NOERR) - { - S32 size = vfs->getSize(asset_uuid, type); - U8* buffer = new U8[size]; - vfs->getData(asset_uuid, type, buffer, 0, size); - - if(type == LLAssetType::AT_NOTECARD) + auto& ao = mAOOverrides[i]; + if (ao && ao->overrideAnim(sSwimming, id)) { - LLViewerTextEditor* edit = new LLViewerTextEditor("",LLRect(0,0,0,0),S32_MAX,""); - if(edit->importBuffer((char*)buffer, (S32)size)) + aop = ao; + state = (AOState)i; + } + } + if (aop) + { +// LL_INFOS() << "st" << (start ? "art" : "op") << " anim " << id << " state " << state << LL_ENDL; + aop->play(start); + } +} + +void AOSystem::stopAllOverrides() const +{ + if (!isAgentAvatarValid()) return; + uuid_vec_t anims; + for (auto& ao : mAOOverrides) + { + if (ao->playing) + { + anims.push_back(ao->getOverride()); + ao->playing = false; + } + } + for (const auto& stand : mAOStands) + anims.push_back(stand.ao_id); + gAgent.sendAnimationRequests(anims, ANIM_REQUEST_STOP); +} + +void AOSystem::parseNotecard(LLVFS *vfs, const LLUUID& asset_uuid, LLAssetType::EType type, S32 status, bool reload) +{ + if (status == LL_ERR_NOERR) + { + if (type == LLAssetType::AT_NOTECARD) + { + AOSystem* self = getIfExists(); + S32 size = vfs->getSize(asset_uuid, LLAssetType::AT_NOTECARD); + U8* buffer = new U8[size]; + vfs->getData(asset_uuid, type, buffer, 0, size); + LLMemoryStream str(buffer, size); + LLNotecard nc; + if (nc.importStream(str)) { LL_INFOS() << "ao nc decode success" << LL_ENDL; - std::string card = edit->getText(); - edit->die(); - if (mcomboBox_stands) + if (self && reload) self->stopAllOverrides(); + + auto floater = LLFloaterAO::findInstance(); + if (floater) + for (auto& combo : floater->mCombos) { - mcomboBox_stands->clear(); - mcomboBox_stands->removeall(); + if (combo) + { + combo->clear(); + combo->removeall(); + } } - if (mcomboBox_walks) mcomboBox_walks->clear(); - if (mcomboBox_runs) mcomboBox_runs->clear(); - if (mcomboBox_jumps) mcomboBox_jumps->clear(); - if (mcomboBox_sits) mcomboBox_sits->clear(); - if (mcomboBox_gsits) mcomboBox_gsits->clear(); - if (mcomboBox_crouchs) mcomboBox_cwalks->clear(); - if (mcomboBox_cwalks) mcomboBox_cwalks->clear(); - if (mcomboBox_falls) mcomboBox_falls->clear(); - if (mcomboBox_hovers) mcomboBox_hovers->clear(); - if (mcomboBox_flys) mcomboBox_flys->clear(); - if (mcomboBox_flyslows) mcomboBox_flyslows->clear(); - if (mcomboBox_flyups) mcomboBox_flyups->clear(); - if (mcomboBox_flydowns) mcomboBox_flydowns->clear(); - if (mcomboBox_lands) mcomboBox_lands->clear(); - if (mcomboBox_typings) mcomboBox_typings->clear(); - if (mcomboBox_floats) mcomboBox_floats->clear(); - if (mcomboBox_swims) mcomboBox_swims->clear(); - if (mcomboBox_swimups) mcomboBox_swimups->clear(); - if (mcomboBox_swimdowns) mcomboBox_swimdowns->clear(); - if (mcomboBox_standups) mcomboBox_standups->clear(); - if (mcomboBox_prejumps) mcomboBox_prejumps->clear(); typedef boost::tokenizer > tokenizer; boost::char_separator sep("\n"); - tokenizer tokline(card, sep); + tokenizer tokline(nc.getText(), sep); for (const auto& strline : tokline) { // LL_INFOS() << "uncommented line: " << strline << LL_ENDL; - boost::regex type("^(\\s*)(\\[ )(.*)( \\])"); boost::smatch what; if (boost::regex_search(strline, what, type)) { - std::string strtoken(what[0]); + const std::string strtoken(what[0]); + const AOState state = GetStateFromToken(strtoken); + if (state == STATE_AGENT_END) + { + LL_WARNS() << "Invalid token: " << strtoken << LL_ENDL; + continue; + } // LL_INFOS() << "type: " << strtoken << LL_ENDL; + LLComboBox* combo = floater ? floater->getComboFromState(state) : nullptr; + auto aop = (reload && self) ? self->mAOOverrides[state] : nullptr; // LL_INFOS() << "anims in type: " << boost::regex_replace(strline, type, "") << LL_ENDL; boost::char_separator sep("|,"); @@ -886,90 +720,86 @@ void LLFloaterAO::onNotecardLoadComplete(LLVFS *vfs,const LLUUID& asset_uuid,LLA tokenizer tokanimnames(stranimnames, sep); for (const auto& stranim : tokanimnames) { - LLUUID animid(getAssetIDByName(stranim)); + if (stranim.empty()) continue; + const auto& animid(getAssetIDByName(stranim)); // LL_INFOS() << invfolderid.asString().c_str() << LL_ENDL; // LL_INFOS() << "anim: " << stranim.c_str() << " assetid: " << animid << LL_ENDL; - if (animid.isNull()) + if (animid.notNull()) { - cmdline_printchat(llformat("Warning: animation '%s' could not be found (Section: %s).",stranim.c_str(),strtoken.c_str())); - } - else - { - const AOState state = GetStateFromToken(strtoken); - switch (state) + if (aop) // If we're reloading { - case STATE_AGENT_STAND: - mAOStands.push_back({ animid, stranim }); - default: break; + if (state == STATE_AGENT_IDLE) + self->mAOStands.push_back({ animid, stranim }); + else + aop->ao_id = animid; } - if (LLComboBox* combo = getComboFromState(state)) - { - //LL_INFOS() << "1 anim: " << stranim.c_str() << " assetid: " << animid << LL_ENDL; - if (!combo->selectByValue(stranim)) //check if exist - combo->add(stranim, ADD_BOTTOM, true); - } - - for (auto& ao : mAOOverrides) - { - if (state == ao.state) - { - ao.ao_id = animid; - break; - } - } + if (combo && !combo->selectByValue(stranim)) // check if exists + combo->add(stranim, ADD_BOTTOM, true); } + else cmdline_printchat("Warning: animation '" + stranim + "' could not be found (Section: " + strtoken + ")."); } } } LL_INFOS() << "ao nc read sucess" << LL_ENDL; - for (auto& ao : mAOOverrides) + if (self) { - if (LLComboBox* combo = getComboFromState(ao.state)) + if (auto combo = floater ? floater->getComboFromState(STATE_AGENT_IDLE) : nullptr) + combo->selectNthItem(self->stand_iterator); + + for (U8 i = STATE_AGENT_IDLE+1; i < STATE_AGENT_END; ++i) { - std::string defaultanim = gSavedPerAccountSettings.getString(combo->getControlName()); - const LLUUID ao_id = getAssetIDByName(defaultanim); - if (ao_id != LLUUID::null) ao.ao_id = ao_id; - combo->selectByValue(defaultanim); + auto& aop = self->mAOOverrides[i]; + if (!aop) continue; + auto& ao = *aop; + const auto& setting = ao.setting; + if (!setting && ao.ao_id.isNull()) continue; + const auto& defaultanim = setting ? setting->get().asStringRef() : ao.ao_id.asString(); + if (defaultanim.empty()) continue; + const LLUUID& ao_id = getAssetIDByName(defaultanim); + if (reload && ao_id.notNull()) ao.ao_id = ao_id; + if (LLComboBox* combo = floater ? floater->getComboFromState(i) : nullptr) + if (!combo->selectByValue(defaultanim)) + combo->add(defaultanim, ADD_BOTTOM, true); + } + + if (reload && isAgentAvatarValid()) + { + // Fix the stand iter, container size may have changed + auto& iter = self->stand_iterator; + const auto& stands = self->mAOStands; + iter = llmin(iter, (int)stands.size()-1); + // Update the current stand + self->stand().update(stands, iter); + self->mAOStandTimer.reset(); + + const auto& anims = gAgentAvatarp->mPlayingAnimations; + bool playing = false; + for (auto& aop : self->mAOOverrides) + { + for (const auto& anim : anims) + { + if (aop && aop->overrideAnim(sSwimming, anim.first)) + { + if (!aop->isLowPriority()) playing = true; + aop->play(); + break; + } + } + } + + if (!playing) self->stand().play(); // Play stand if nothing was being played, this sometimes happens + + // Toggle typing AO the moment we toggle AO + typing(gAgent.getRenderState() & AGENT_STATE_TYPING); } } - run(); - } - else - { - LL_INFOS() << "ao nc decode error" << LL_ENDL; } + else LL_INFOS() << "ao nc decode error" << LL_ENDL; + delete[] buffer; } } - else - { - LL_INFOS() << "ao nc read error" << LL_ENDL; - } + else LL_INFOS() << "ao nc read error" << LL_ENDL; } - -class ObjectNameMatches : public LLInventoryCollectFunctor -{ -public: - ObjectNameMatches(std::string name) : sName(name) {} - virtual ~ObjectNameMatches() {} - virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item) - { - return item && item->getParentUUID() == LLFloaterAO::invfolderid && item->getName() == sName; - } -private: - std::string sName; -}; - -const LLUUID& LLFloaterAO::getAssetIDByName(const std::string& name) -{ - if (name.empty() || !LLInventoryModelBackgroundFetch::instance().isEverythingFetched()) return LLUUID::null; - - LLViewerInventoryCategory::cat_array_t cats; - LLViewerInventoryItem::item_array_t items; - ObjectNameMatches matches(name); - gInventory.collectDescendentsIf(LLUUID::null,cats,items,false, matches); - - return items.empty() ? LLUUID::null : items[0]->getAssetUUID(); -}; diff --git a/indra/newview/floaterao.h b/indra/newview/floaterao.h index 2aaa789c9..e532db03b 100644 --- a/indra/newview/floaterao.h +++ b/indra/newview/floaterao.h @@ -2,54 +2,51 @@ #ifndef LL_LLFLOATERAO_H #define LL_LLFLOATERAO_H -#include "llfloater.h" -#include "llviewercontrol.h" #include "llagent.h" +#include "llcontrol.h" #include "lleventtimer.h" +#include "llfloater.h" -enum AOState +enum AOState : U8 { - STATE_AGENT_IDLE = 0, - STATE_AGENT_WALK = 1, - STATE_AGENT_RUN = 2, - STATE_AGENT_STAND = 3, + STATE_AGENT_IDLE , + STATE_AGENT_WALK, + STATE_AGENT_RUN, - STATE_AGENT_PRE_JUMP = 4, - STATE_AGENT_JUMP = 5, - STATE_AGENT_TURNLEFT = 6, - STATE_AGENT_TURNRIGHT = 7, + STATE_AGENT_PRE_JUMP, + STATE_AGENT_JUMP, + STATE_AGENT_TURNLEFT, + STATE_AGENT_TURNRIGHT, - STATE_AGENT_SIT = 8, - STATE_AGENT_GROUNDSIT = 9, + STATE_AGENT_SIT, + STATE_AGENT_SIT_GROUND, - STATE_AGENT_HOVER = 10, - STATE_AGENT_HOVER_DOWN = 11, - STATE_AGENT_HOVER_UP = 12, + STATE_AGENT_HOVER, + STATE_AGENT_HOVER_DOWN, + STATE_AGENT_HOVER_UP, - STATE_AGENT_CROUCH = 13, - STATE_AGENT_CROUCHWALK = 14, - STATE_AGENT_FALLDOWN = 15, - STATE_AGENT_STANDUP = 16, - STATE_AGENT_LAND = 17, + STATE_AGENT_CROUCH, + STATE_AGENT_CROUCHWALK, + STATE_AGENT_FALLDOWN, + STATE_AGENT_STANDUP, + STATE_AGENT_LAND, - STATE_AGENT_FLY = 18, - STATE_AGENT_FLYSLOW = 19, + STATE_AGENT_FLY, + STATE_AGENT_FLYSLOW, - STATE_AGENT_TYPING = 20, + STATE_AGENT_TYPE, - STATE_AGENT_SWIM_DOWN = 21, - STATE_AGENT_SWIM_UP = 22, - STATE_AGENT_SWIM = 23, - STATE_AGENT_FLOAT = 24, + STATE_AGENT_SWIM_DOWN, + STATE_AGENT_SWIM_UP, + STATE_AGENT_SWIM, + STATE_AGENT_FLOAT, STATE_AGENT_END }; - - - -class AOStandTimer : public LLEventTimer +class AOStandTimer final : public LLEventTimer { + friend class AOSystem; public: AOStandTimer(); ~AOStandTimer(); @@ -57,78 +54,146 @@ public: void reset(); }; -class AOInvTimer : public LLEventTimer +class AOInvTimer final : public LLEventTimer, public LLSingleton { -public: + friend class LLSingleton; + friend class AOSystem; AOInvTimer(); ~AOInvTimer(); + static void createIfNeeded(); +public: + static bool needed(); BOOL tick() override; }; -class LLFloaterAO : public LLFloater, public LLFloaterSingleton +class LLFloaterAO final : public LLFloater, public LLFloaterSingleton { + friend class AOSystem; public: - LLFloaterAO(const LLSD&); + LLFloaterAO(const LLSD&); BOOL postBuild() override; void onOpen() override; - virtual ~LLFloaterAO(); - - static void init(); - - static void run(); + virtual ~LLFloaterAO(); void updateLayout(bool advanced); - //static bool loadAnims(); + void onClickCycleStand(bool next) const; + void onClickReloadCard() const; + void onClickOpenCard() const; + void onClickNewCard() const; - static void typing(bool start); - static AOState flyToSwimState(const AOState& state); - static AOState swimToFlyState(const AOState& state); - static AOState getAnimationState(); - static void setAnimationState(const AOState& state); - - static LLUUID getCurrentStandId(); - static void setCurrentStandId(const LLUUID& id); - static int stand_iterator; - static void ChangeStand(); - static void toggleSwim(bool underwater); - - static void doMotion(const LLUUID& id, bool start, bool stand = false); - static void startMotion(const LLUUID& id, bool stand = false) { doMotion(id, true, stand); } - static void stopMotion(const LLUUID& id, bool stand = false) { doMotion(id, false, stand); } - - static bool swimCheck(const AOState& state); - static LLUUID GetAnimID(const LLUUID& id); - - static AOState GetStateFromAnimID(const LLUUID& id); - static LLUUID GetAnimIDFromState(const AOState& state); - static AOState GetStateFromToken(std::string strtoken); - - static void onClickCycleStand(bool next); - static void onClickReloadCard(); - static void onClickOpenCard(); - static void onClickNewCard(); - - static LLUUID invfolderid; - static const LLUUID& getAssetIDByName(const std::string& name); - private: - - static AOState mAnimationState; - static LLUUID mCurrentStandId; - - static void onSpinnerCommit(); - static void onComboBoxCommit(LLUICtrl* ctrl); + void onSpinnerCommit() const; + void onComboBoxCommit(LLUICtrl* ctrl) const; + std::array mCombos; protected: - static AOState getStateFromCombo(const class LLComboBox* combo); - static LLComboBox* getComboFromState(const AOState& state); - - static void onNotecardLoadComplete(LLVFS *vfs,const LLUUID& asset_uuid,LLAssetType::EType type,void* user_data, S32 status, LLExtStat ext_status); - + AOState getStateFromCombo(const class LLComboBox* combo) const; + LLComboBox* getComboFromState(const U8& state) const { return mCombos[state]; } }; -extern AOInvTimer* gAOInvTimer; +class AOSystem final : public LLSingleton +{ + friend class LLSingleton; + friend class AOInvTimer; + friend class LLFloaterAO; + AOSystem(); + ~AOSystem(); +public: + static void start(); // Runs the necessary actions to get the AOSystem ready, then initializes it. + void initSingleton() override; + + static void typing(bool start); + + int stand_iterator; + bool isStanding() const { return stand().playing; } + void updateStand(); + int cycleStand(bool next = true, bool random = true); + void toggleSwim(bool underwater); + + void doMotion(const LLUUID& id, bool start); + void startMotion(const LLUUID& id) { doMotion(id, true); } + void stopMotion(const LLUUID& id) { doMotion(id, false); } + void stopCurrentStand() const { stand().play(false); } + void stopAllOverrides() const; + +protected: + struct struct_stands + { + LLUUID ao_id; + std::string anim_name; + }; + typedef std::vector stands_vec; + stands_vec mAOStands; + + struct overrides + { + virtual bool overrideAnim(bool swimming, const LLUUID& anim) const = 0; + virtual const LLUUID& getOverride() const { return ao_id; } + virtual bool play_condition() const; // True if prevented from playing + virtual bool isLowPriority() const { return false; } + void play(bool start = true); + LLUUID ao_id; + LLPointer setting; + bool playing; + virtual ~overrides() {} + protected: + overrides(const char* setting_name); + }; + struct override_low_priority final : public overrides + { + override_low_priority(const LLUUID& id, const char* setting_name = nullptr) + : overrides(setting_name), orig_id(id) {} + bool overrideAnim(bool swimming, const LLUUID & anim) const override { return orig_id == anim; } + bool play_condition() const override { return false; } + bool isLowPriority() const override { return true; } + private: + const LLUUID orig_id; + }; + struct override_single final : public overrides + { + override_single(const LLUUID& id, const char* setting_name = nullptr, U8 swim = 2) + : overrides(setting_name), orig_id(id), swim(swim) {} + bool overrideAnim(bool swimming, const LLUUID& anim) const override { return (swim == 2 || !!swim == swimming) && orig_id == anim; } + private: + const LLUUID orig_id; + const U8 swim; // 2 = irrelevant, 0 = flying, 1 = swimming + }; + struct override_stand final : public overrides + { + override_stand() : overrides(nullptr) {} + bool overrideAnim(bool swimming, const LLUUID& anim) const override; + bool play_condition() const override; + bool isLowPriority() const override { return true; } + void update(const stands_vec& stands, const int& iter) + { + if (stands.empty()) ao_id.setNull(); + else ao_id = stands[iter].ao_id; + } + }; + struct override_sit final : public overrides + { + override_sit(const uuid_set_t& ids, const char* setting_name = nullptr) + : overrides(setting_name) + , orig_ids(ids) + {} + bool overrideAnim(bool swimming, const LLUUID& anim) const override { return orig_ids.find(anim) != orig_ids.end(); } + bool play_condition() const override; + private: + const uuid_set_t orig_ids; + }; + std::array mAOOverrides; + + override_stand& stand() const { return static_cast(*mAOOverrides[STATE_AGENT_IDLE]); } + +private: + std::array mConnections; + + AOStandTimer mAOStandTimer; + + static void requestConfigNotecard(bool reload = true); + static void parseNotecard(LLVFS* vfs, const LLUUID& asset_uuid, LLAssetType::EType type, S32 status, bool reload); +}; #endif diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 28e5b8a5b..93924cfaa 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -2116,7 +2116,7 @@ void LLAgent::startTyping() } } - LLFloaterAO::typing(true); // Singu Note: Typing anims handled by AO/settings. + AOSystem::typing(true); // Singu Note: Typing anims handled by AO/settings. gChatBar-> sendChatFromViewer("", CHAT_TYPE_START, FALSE); } @@ -2129,7 +2129,7 @@ void LLAgent::stopTyping() if (mRenderState & AGENT_STATE_TYPING) { clearRenderState(AGENT_STATE_TYPING); - LLFloaterAO::typing(false); // Singu Note: Typing anims handled by AO/settings. + AOSystem::typing(false); // Singu Note: Typing anims handled by AO/settings. gChatBar-> sendChatFromViewer("", CHAT_TYPE_STOP, FALSE); } diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp index 727a59f4b..0b051809f 100644 --- a/indra/newview/llagentcamera.cpp +++ b/indra/newview/llagentcamera.cpp @@ -2265,7 +2265,8 @@ void LLAgentCamera::changeCameraToMouselook(BOOL animate) mMouselookTimer.reset(); gFocusMgr.setKeyboardFocus(NULL); - if (gSavedSettings.getBOOL("AONoStandsInMouselook")) LLFloaterAO::stopMotion(LLFloaterAO::getCurrentStandId(), true); + auto ao = AOSystem::getIfExists(); + if (ao && gSavedSettings.getBOOL("AONoStandsInMouselook")) ao->stopCurrentStand(); updateLastCamera(); mCameraMode = CAMERA_MODE_MOUSELOOK; diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 77382fd07..74645bde9 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -161,6 +161,7 @@ // in save_settings_to_globals() #include "llbutton.h" #include "llcombobox.h" +#include "floaterao.h" #include "floaterlocalassetbrowse.h" #include "llsurface.h" #include "llvotree.h" @@ -1659,6 +1660,8 @@ bool LLAppViewer::cleanup() LLCalc::cleanUp(); + AOSystem::deleteSingleton(); + LL_INFOS() << "Global stuff deleted" << LL_ENDL; // Note: this is where LLFeatureManager::getInstance()-> used to be deleted. diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 750de91bb..71b8e55e0 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -2687,10 +2687,7 @@ bool idle_startup() } // Start the AO now that settings have loaded and login successful -- MC - if (!gAOInvTimer) - { - gAOInvTimer = new AOInvTimer(); - } + AOSystem::start(); gViewerWindow->showCursor(); gViewerWindow->getWindow()->resetBusyCount(); diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index bd43feff0..796bb6c93 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -4266,7 +4266,8 @@ void LLVOAvatar::idleUpdateBelowWater() BOOL old_below = mBelowWater; mBelowWater = avatar_height < water_height; if (old_below != mBelowWater) - LLFloaterAO::toggleSwim(mBelowWater); + if (auto ao = AOSystem::getIfExists()) + ao->toggleSwim(mBelowWater); } void LLVOAvatar::slamPosition() @@ -6301,7 +6302,7 @@ void LLVOAvatar::processAnimationStateChanges() } // clear all current animations - const bool AOEnabled(gSavedSettings.getBOOL("AOEnabled")); // + auto ao = isSelf() ? AOSystem::getIfExists() : nullptr; // AO is only for ME AnimIterator anim_it; for (anim_it = mPlayingAnimations.begin(); anim_it != mPlayingAnimations.end();) { @@ -6310,8 +6311,7 @@ void LLVOAvatar::processAnimationStateChanges() // playing, but not signaled, so stop if (found_anim == mSignaledAnimations.end()) { - if (AOEnabled && isSelf()) - LLFloaterAO::stopMotion(anim_it->first, FALSE); // if the AO replaced this anim serverside then stop it serverside + if (ao) ao->stopMotion(anim_it->first); // if the AO replaced this anim serverside then stop it serverside processSingleAnimationStateChange(anim_it->first, FALSE); // @@ -6337,10 +6337,7 @@ void LLVOAvatar::processAnimationStateChanges() // if (processSingleAnimationStateChange(anim_it->first, TRUE)) { - if (AOEnabled && isSelf()) // AO is only for ME - { - LLFloaterAO::startMotion(anim_it->first, false); // AO overrides the anim if needed - } + if (ao) ao->startMotion(anim_it->first); // AO overrides the anim if needed mPlayingAnimations[anim_it->first] = anim_it->second; ++anim_it; @@ -8040,8 +8037,6 @@ void LLVOAvatar::sitDown(BOOL bSitting) mIsSitting = bSitting; if (isSelf()) { - LLFloaterAO::ChangeStand(); - // [RLVa:KB] - Checked: 2010-08-29 (RLVa-1.2.1c) | Modified: RLVa-1.2.1c if (rlv_handler_t::isEnabled()) {