From 11e6c77129ae27756df627ccc1ea0ffa279976e6 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Thu, 29 Aug 2024 20:04:34 +0300 Subject: Add simple metrics of Lua usage --- indra/newview/llappviewer.cpp | 2 +- indra/newview/llfloaterluadebug.cpp | 2 +- indra/newview/llluamanager.cpp | 16 ++++++++++++---- indra/newview/llluamanager.h | 5 ++++- indra/newview/llviewerstats.cpp | 5 +++++ 5 files changed, 23 insertions(+), 7 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index c259275d8f..686b97390a 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -1252,7 +1252,7 @@ bool LLAppViewer::init() while (scripts.next(script)) { LL_DEBUGS("InitInfo") << "LuaAutorunPath: " << absdir << ": " << script << LL_ENDL; - LLLUAmanager::runScriptFile((abspath / script).string()); + LLLUAmanager::runScriptFile((abspath / script).string(), true); } }); diff --git a/indra/newview/llfloaterluadebug.cpp b/indra/newview/llfloaterluadebug.cpp index ef24481464..1831edb452 100644 --- a/indra/newview/llfloaterluadebug.cpp +++ b/indra/newview/llfloaterluadebug.cpp @@ -127,7 +127,7 @@ void LLFloaterLUADebug::runSelectedScript(const std::vector &filena if (!filepath.empty()) { mScriptPath->setText(filepath); - LLLUAmanager::runScriptFile(filepath, [this](int count, const LLSD &result) + LLLUAmanager::runScriptFile(filepath, false, [this](int count, const LLSD &result) { completion(count, result); }); diff --git a/indra/newview/llluamanager.cpp b/indra/newview/llluamanager.cpp index 22b51d7b72..befd231e92 100644 --- a/indra/newview/llluamanager.cpp +++ b/indra/newview/llluamanager.cpp @@ -49,6 +49,8 @@ #include #include +S32 LLLUAmanager::sAutorunScriptCount = 0; +S32 LLLUAmanager::sScriptCount = 0; std::map LLLUAmanager::sScriptNames; lua_function(sleep, "sleep(seconds): pause the running coroutine") @@ -172,7 +174,7 @@ LLLUAmanager::startScriptFile(const std::string& filename) // Despite returning from startScriptFile(), we need this Promise to // remain alive until the callback has fired. auto promise{ std::make_shared>() }; - runScriptFile(filename, + runScriptFile(filename, false, [promise](int count, LLSD result) { promise->set_value({ count, result }); }); return LLCoros::getFuture(*promise); @@ -183,11 +185,11 @@ LLLUAmanager::script_result LLLUAmanager::waitScriptFile(const std::string& file return startScriptFile(filename).get(); } -void LLLUAmanager::runScriptFile(const std::string &filename, script_result_fn result_cb, - script_finished_fn finished_cb) +void LLLUAmanager::runScriptFile(const std::string &filename, bool autorun, + script_result_fn result_cb, script_finished_fn finished_cb) { // A script_result_fn will be called when LuaState::expr() completes. - LLCoros::instance().launch(filename, [filename, result_cb, finished_cb]() + LLCoros::instance().launch(filename, [filename, autorun, result_cb, finished_cb]() { ScriptObserver observer(LLCoros::getName(), filename); llifstream in_file; @@ -195,6 +197,12 @@ void LLLUAmanager::runScriptFile(const std::string &filename, script_result_fn r if (in_file.is_open()) { + if (autorun) + { + sAutorunScriptCount++; + } + sScriptCount++; + // A script_finished_fn is used to initialize the LuaState. // It will be called when the LuaState is destroyed. LuaState L(finished_cb); diff --git a/indra/newview/llluamanager.h b/indra/newview/llluamanager.h index 50f922a80f..309cb87cac 100644 --- a/indra/newview/llluamanager.h +++ b/indra/newview/llluamanager.h @@ -58,7 +58,7 @@ public: // same semantics as script_result_fn parameters typedef std::pair script_result; - static void runScriptFile(const std::string &filename, script_result_fn result_cb = {}, + static void runScriptFile(const std::string &filename, bool autorun = false, script_result_fn result_cb = {}, script_finished_fn finished_cb = {}); // Start running a Lua script file, returning an LLCoros::Future whose // get() method will pause the calling coroutine until it can deliver the @@ -84,6 +84,9 @@ public: static const std::map getScriptNames() { return sScriptNames; } + static S32 sAutorunScriptCount; + static S32 sScriptCount; + private: static std::map sScriptNames; }; diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index 62b4c390d0..60e8cf2e52 100644 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -66,6 +66,7 @@ #include "llinventorymodel.h" #include "lluiusage.h" #include "lltranslate.h" +#include "llluamanager.h" // "Minimal Vulkan" to get max API Version @@ -673,6 +674,10 @@ void send_viewer_stats(bool include_preferences) system["shader_level"] = shader_level; + LLSD &scripts = body["scripts"]; + scripts["lua_scripts"] = LLLUAmanager::sScriptCount; + scripts["lua_auto_scripts"] = LLLUAmanager::sAutorunScriptCount; + LLSD &download = body["downloads"]; download["world_kbytes"] = F64Kilobytes(gTotalWorldData).value(); -- cgit v1.2.3 From 6e47dc1af90c242c792c90e93d013355c9a43b97 Mon Sep 17 00:00:00 2001 From: Mnikolenko Productengine Date: Fri, 30 Aug 2024 12:18:20 +0300 Subject: Add Lua api to start/stop playing animation --- indra/newview/llagentlistener.cpp | 66 +++++++++++++++++++++++++++ indra/newview/llagentlistener.h | 4 ++ indra/newview/scripts/lua/require/LLAgent.lua | 14 ++++++ 3 files changed, 84 insertions(+) (limited to 'indra/newview') diff --git a/indra/newview/llagentlistener.cpp b/indra/newview/llagentlistener.cpp index 80460666a5..95b7ebd5db 100644 --- a/indra/newview/llagentlistener.cpp +++ b/indra/newview/llagentlistener.cpp @@ -34,12 +34,14 @@ #include "llagentcamera.h" #include "llvoavatar.h" #include "llcommandhandler.h" +#include "llinventorymodel.h" #include "llslurl.h" #include "llurldispatcher.h" #include "llviewernetwork.h" #include "llviewerobject.h" #include "llviewerobjectlist.h" #include "llviewerregion.h" +#include "llvoavatarself.h" #include "llsdutil.h" #include "llsdutil_math.h" #include "lltoolgrab.h" @@ -157,6 +159,19 @@ LLAgentListener::LLAgentListener(LLAgent &agent) add("removeCameraParams", "Reset Follow camera params", &LLAgentListener::removeFollowCamParams); + + add("playAnimation", + "Play [\"item_id\"] animation locally (by default) or [\"inworld\"] (when set to true)", + &LLAgentListener::playAnimation, + llsd::map("item_id", LLSD(), "reply", LLSD())); + add("stopAnimation", + "Stop playing [\"item_id\"] animation", + &LLAgentListener::stopAnimation, + llsd::map("item_id", LLSD(), "reply", LLSD())); + add("getAnimationInfo", + "Return information about [\"item_id\"] animation", + &LLAgentListener::getAnimationInfo, + llsd::map("item_id", LLSD(), "reply", LLSD())); } void LLAgentListener::requestTeleport(LLSD const & event_data) const @@ -591,3 +606,54 @@ void LLAgentListener::removeFollowCamParams(LLSD const & event) const { LLFollowCamMgr::getInstance()->removeFollowCamParams(gAgentID); } + +void LLAgentListener::playAnimation(LLSD const &event_data) +{ + Response response(LLSD(), event_data); + LLViewerInventoryItem* item = gInventory.getItem(event_data["item_id"].asUUID()); + if (!item || (item->getInventoryType() != LLInventoryType::IT_ANIMATION)) + { + return response.error(stringize("Item ", std::quoted(event_data["item_id"].asString()), " was not found")); + } + LLUUID assset_id = item->getAssetUUID(); + if(event_data["inworld"].asBoolean()) + { + gAgent.sendAnimationRequest(assset_id, ANIM_REQUEST_START); + } + else + { + gAgentAvatarp->startMotion(assset_id); + } +} + +void LLAgentListener::stopAnimation(LLSD const &event_data) +{ + Response response(LLSD(), event_data); + LLViewerInventoryItem* item = gInventory.getItem(event_data["item_id"].asUUID()); + if (!item || (item->getInventoryType() != LLInventoryType::IT_ANIMATION)) + { + return response.error(stringize("Item ", std::quoted(event_data["item_id"].asString()), " was not found")); + } + LLUUID assset_id = item->getAssetUUID(); + gAgentAvatarp->stopMotion(assset_id); + gAgent.sendAnimationRequest(assset_id, ANIM_REQUEST_STOP); +} + +void LLAgentListener::getAnimationInfo(LLSD const &event_data) +{ + Response response(LLSD(), event_data); + LLUUID item_id(event_data["item_id"].asUUID()); + LLViewerInventoryItem* item = gInventory.getItem(item_id); + if (!item || (item->getInventoryType() != LLInventoryType::IT_ANIMATION)) + { + return response.error(stringize("Item ", std::quoted(item_id.asString()), " was not found")); + } + // if motion exists, will return existing one + LLMotion* motion = gAgentAvatarp->createMotion(item->getAssetUUID()); + response["anim_info"].insert(item_id.asString(), + llsd::map("duration", motion->getDuration(), + "is_loop", motion->getLoop(), + "num_joints", motion->getNumJointMotions(), + "asset_id", item->getAssetUUID(), + "priority", motion->getPriority())); +} diff --git a/indra/newview/llagentlistener.h b/indra/newview/llagentlistener.h index 2a24de3f52..cf914a17d0 100644 --- a/indra/newview/llagentlistener.h +++ b/indra/newview/llagentlistener.h @@ -60,6 +60,10 @@ private: void setFollowCamParams(LLSD const & event_data) const; void setFollowCamActive(LLSD const & event_data) const; void removeFollowCamParams(LLSD const & event_data) const; + + void playAnimation(LLSD const &event_data); + void stopAnimation(LLSD const &event_data); + void getAnimationInfo(LLSD const &event_data); LLViewerObject * findObjectClosestTo( const LLVector3 & position ) const; diff --git a/indra/newview/scripts/lua/require/LLAgent.lua b/indra/newview/scripts/lua/require/LLAgent.lua index 5ee092f2f6..56907f53cd 100644 --- a/indra/newview/scripts/lua/require/LLAgent.lua +++ b/indra/newview/scripts/lua/require/LLAgent.lua @@ -53,4 +53,18 @@ function LLAgent.removeCamParams() leap.send('LLAgent', {op = 'removeCameraParams'}) end +function LLAgent.playAnimation(...) + local args = mapargs('item_id,inworld', ...) + args.op = 'playAnimation' + return leap.request('LLAgent', args) +end + +function LLAgent.stopAnimation(item_id) + return leap.request('LLAgent', {op = 'stopAnimation', item_id=item_id}) +end + +function LLAgent.getAnimationInfo(item_id) + return leap.request('LLAgent', {op = 'getAnimationInfo', item_id=item_id}).anim_info +end + return LLAgent -- cgit v1.2.3 From 4312a2b7703f6ba35a1cdcd1edc48dddfe084270 Mon Sep 17 00:00:00 2001 From: Mnikolenko Productengine Date: Fri, 30 Aug 2024 14:48:36 +0300 Subject: Add throttle for playing an animation; add demo script --- indra/newview/llagentlistener.cpp | 59 +++++++++++++++------------ indra/newview/llagentlistener.h | 4 ++ indra/newview/scripts/lua/require/LLAgent.lua | 4 ++ indra/newview/scripts/lua/test_animation.lua | 28 +++++++++++++ 4 files changed, 70 insertions(+), 25 deletions(-) create mode 100644 indra/newview/scripts/lua/test_animation.lua (limited to 'indra/newview') diff --git a/indra/newview/llagentlistener.cpp b/indra/newview/llagentlistener.cpp index 95b7ebd5db..4980c7075f 100644 --- a/indra/newview/llagentlistener.cpp +++ b/indra/newview/llagentlistener.cpp @@ -49,9 +49,12 @@ #include "llagentcamera.h" #include +static const F64 PLAY_ANIM_THROTTLE_PERIOD = 1.f; + LLAgentListener::LLAgentListener(LLAgent &agent) : LLEventAPI("LLAgent", "LLAgent listener to (e.g.) teleport, sit, stand, etc."), + mPlayAnimThrottle("playAnimation", &LLAgentListener::playAnimation_, this, PLAY_ANIM_THROTTLE_PERIOD), mAgent(agent) { add("requestTeleport", @@ -607,53 +610,59 @@ void LLAgentListener::removeFollowCamParams(LLSD const & event) const LLFollowCamMgr::getInstance()->removeFollowCamParams(gAgentID); } -void LLAgentListener::playAnimation(LLSD const &event_data) +LLViewerInventoryItem* get_anim_item(LLEventAPI::Response &response, const LLSD &event_data) { - Response response(LLSD(), event_data); LLViewerInventoryItem* item = gInventory.getItem(event_data["item_id"].asUUID()); if (!item || (item->getInventoryType() != LLInventoryType::IT_ANIMATION)) { - return response.error(stringize("Item ", std::quoted(event_data["item_id"].asString()), " was not found")); + response.error(stringize("Animation item ", std::quoted(event_data["item_id"].asString()), " was not found")); + return NULL; + } + return item; +} + +void LLAgentListener::playAnimation(LLSD const &event_data) +{ + Response response(LLSD(), event_data); + if (LLViewerInventoryItem* item = get_anim_item(response, event_data)) + { + mPlayAnimThrottle(item->getAssetUUID(), event_data["inworld"].asBoolean()); } - LLUUID assset_id = item->getAssetUUID(); - if(event_data["inworld"].asBoolean()) +} + +void LLAgentListener::playAnimation_(const LLUUID& asset_id, const bool inworld) +{ + if (inworld) { - gAgent.sendAnimationRequest(assset_id, ANIM_REQUEST_START); + mAgent.sendAnimationRequest(asset_id, ANIM_REQUEST_START); } else { - gAgentAvatarp->startMotion(assset_id); + gAgentAvatarp->startMotion(asset_id); } } void LLAgentListener::stopAnimation(LLSD const &event_data) { Response response(LLSD(), event_data); - LLViewerInventoryItem* item = gInventory.getItem(event_data["item_id"].asUUID()); - if (!item || (item->getInventoryType() != LLInventoryType::IT_ANIMATION)) + if (LLViewerInventoryItem* item = get_anim_item(response, event_data)) { - return response.error(stringize("Item ", std::quoted(event_data["item_id"].asString()), " was not found")); + gAgentAvatarp->stopMotion(item->getAssetUUID()); + mAgent.sendAnimationRequest(item->getAssetUUID(), ANIM_REQUEST_STOP); } - LLUUID assset_id = item->getAssetUUID(); - gAgentAvatarp->stopMotion(assset_id); - gAgent.sendAnimationRequest(assset_id, ANIM_REQUEST_STOP); } void LLAgentListener::getAnimationInfo(LLSD const &event_data) { Response response(LLSD(), event_data); - LLUUID item_id(event_data["item_id"].asUUID()); - LLViewerInventoryItem* item = gInventory.getItem(item_id); - if (!item || (item->getInventoryType() != LLInventoryType::IT_ANIMATION)) + if (LLViewerInventoryItem* item = get_anim_item(response, event_data)) { - return response.error(stringize("Item ", std::quoted(item_id.asString()), " was not found")); + // if motion exists, will return existing one + LLMotion* motion = gAgentAvatarp->createMotion(item->getAssetUUID()); + response["anim_info"] = llsd::map("duration", motion->getDuration(), + "is_loop", motion->getLoop(), + "num_joints", motion->getNumJointMotions(), + "asset_id", item->getAssetUUID(), + "priority", motion->getPriority()); } - // if motion exists, will return existing one - LLMotion* motion = gAgentAvatarp->createMotion(item->getAssetUUID()); - response["anim_info"].insert(item_id.asString(), - llsd::map("duration", motion->getDuration(), - "is_loop", motion->getLoop(), - "num_joints", motion->getNumJointMotions(), - "asset_id", item->getAssetUUID(), - "priority", motion->getPriority())); } diff --git a/indra/newview/llagentlistener.h b/indra/newview/llagentlistener.h index cf914a17d0..c77d1b3fc9 100644 --- a/indra/newview/llagentlistener.h +++ b/indra/newview/llagentlistener.h @@ -31,6 +31,7 @@ #define LL_LLAGENTLISTENER_H #include "lleventapi.h" +#include "throttle.h" class LLAgent; class LLSD; @@ -62,6 +63,7 @@ private: void removeFollowCamParams(LLSD const & event_data) const; void playAnimation(LLSD const &event_data); + void playAnimation_(const LLUUID& asset_id, const bool inworld); void stopAnimation(LLSD const &event_data); void getAnimationInfo(LLSD const &event_data); @@ -70,6 +72,8 @@ private: private: LLAgent & mAgent; LLUUID mFollowTarget; + + LogThrottle mPlayAnimThrottle; }; #endif // LL_LLAGENTLISTENER_H diff --git a/indra/newview/scripts/lua/require/LLAgent.lua b/indra/newview/scripts/lua/require/LLAgent.lua index 56907f53cd..07ef1e0b0b 100644 --- a/indra/newview/scripts/lua/require/LLAgent.lua +++ b/indra/newview/scripts/lua/require/LLAgent.lua @@ -53,6 +53,8 @@ function LLAgent.removeCamParams() leap.send('LLAgent', {op = 'removeCameraParams'}) end +-- Play specified animation by "item_id" locally +-- if "inworld" is specified as true, animation will be played inworld instead function LLAgent.playAnimation(...) local args = mapargs('item_id,inworld', ...) args.op = 'playAnimation' @@ -63,6 +65,8 @@ function LLAgent.stopAnimation(item_id) return leap.request('LLAgent', {op = 'stopAnimation', item_id=item_id}) end +-- Get animation info by "item_id" +-- reply contains "duration", "is_loop", "num_joints", "asset_id", "priority" function LLAgent.getAnimationInfo(item_id) return leap.request('LLAgent', {op = 'getAnimationInfo', item_id=item_id}).anim_info end diff --git a/indra/newview/scripts/lua/test_animation.lua b/indra/newview/scripts/lua/test_animation.lua new file mode 100644 index 0000000000..c16fef4918 --- /dev/null +++ b/indra/newview/scripts/lua/test_animation.lua @@ -0,0 +1,28 @@ +LLInventory = require 'LLInventory' +LLAgent = require 'LLAgent' + +-- Get 'Animations' folder id (you can see all folder types via LLInventory.getFolderTypeNames()) +animations_id = LLInventory.getBasicFolderID('animatn') +-- Get animations from the 'Animation' folder (you can see all folder types via LLInventory.getAssetTypeNames()) +anims = LLInventory.collectDescendentsIf{folder_id=animations_id, type="animatn"}.items + +local anim_ids = {} +for key in pairs(anims) do + table.insert(anim_ids, key) +end + +-- Start playing a random animation +math.randomseed(os.time()) +local random_id = anim_ids[math.random(#anim_ids)] +local anim_info = LLAgent.getAnimationInfo(random_id) + +print("Starting animation locally: " .. anims[random_id].name) +print("Loop: " .. anim_info.is_loop .. " Joints: " .. anim_info.num_joints .. " Duration " .. tonumber(string.format("%.2f", anim_info.duration))) +LLAgent.playAnimation{item_id=random_id} + +-- Stop animation after 3 sec if it's looped or longer than 3 sec +if anim_info.is_loop == 1 or anim_info.duration > 3 then + LL.sleep(3) + print("Stop animation.") + LLAgent.stopAnimation(random_id) +end -- cgit v1.2.3