summaryrefslogtreecommitdiff
path: root/indra/newview/llviewerobject.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llviewerobject.cpp')
-rw-r--r--indra/newview/llviewerobject.cpp181
1 files changed, 177 insertions, 4 deletions
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index 7f51ad1065..382bdb0a93 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -27,6 +27,7 @@
#include "llviewerprecompiledheaders.h"
#include "llviewerobject.h"
+#include "llscripteditorws.h"
#include "llaudioengine.h"
#include "indra_constants.h"
@@ -420,6 +421,13 @@ void LLViewerObject::markDead()
LL_PROFILE_ZONE_SCOPED;
//LL_INFOS() << "Marking self " << mLocalID << " as dead." << LL_ENDL;
+ // If this is a published root prim, notify the WS extension before teardown.
+ auto ws_server = LLScriptEditorWSServer::getServer();
+ if (ws_server && ws_server->isObjectPublished(mID))
+ {
+ ws_server->unpublishObject(mID, "deleted");
+ }
+
// Root object of this hierarchy unlinks itself.
if (getParent())
{
@@ -744,6 +752,18 @@ void LLViewerObject::setNameValueList(const std::string& name_value_list)
}
start = end+1;
}
+
+ if (auto ws_server = LLScriptEditorWSServer::getServer())
+ {
+ LLNameValue* nv_name = getNVPair("Name");
+ LLNameValue* nv_desc = getNVPair("Desc");
+ if (nv_name || nv_desc)
+ {
+ std::string obj_name = nv_name ? nv_name->getString() : "";
+ std::string obj_desc = nv_desc ? nv_desc->getString() : "";
+ ws_server->onObjectPropertyChanged(mID, obj_name, obj_desc);
+ }
+ }
}
bool LLViewerObject::isAnySelected() const
@@ -936,6 +956,24 @@ void LLViewerObject::addChild(LLViewerObject *childp)
{
mSeatCount++;
}
+ else
+ {
+ if (auto ws_server = LLScriptEditorWSServer::getServer())
+ {
+ // If the child was itself a published root, unpublish it — it is now a child prim
+ if (ws_server->isObjectPublished(childp->getID()))
+ {
+ ws_server->unpublishObject(childp->getID(), "linked");
+ }
+
+ // If our root is a published object, notify of the structural change
+ LLUUID root_id = getRootEdit()->getID();
+ if (ws_server->isObjectPublished(root_id))
+ {
+ ws_server->onLinksetChildAdded(root_id, childp);
+ }
+ }
+ }
}
}
@@ -979,6 +1017,18 @@ void LLViewerObject::removeChild(LLViewerObject *childp)
bool add_to_end = true;
LLSelectMgr::getInstance()->selectObjectAndFamily(childp, add_to_end);
}
+
+ // Notify WS server of linkset structure change
+ if (!isDead() && !childp->isDead() && !childp->isAvatar())
+ {
+ if (auto ws_server = LLScriptEditorWSServer::getServer())
+ {
+ if (ws_server->isObjectPublished(getID()))
+ {
+ ws_server->onLinksetChildRemoved(getID(), childp->getID());
+ }
+ }
+ }
}
void LLViewerObject::addThisAndAllChildren(std::vector<LLViewerObject*>& objects)
@@ -2766,10 +2816,15 @@ void LLViewerObject::doUpdateInventory(
// save a script, which involves removing the old one, and rezzing
// in the new one. This method should be called with the asset id
// of the new and old script AFTER the bytecode has been saved.
-void LLViewerObject::saveScript(
- const LLViewerInventoryItem* item,
- bool active,
- bool is_new)
+// When creating a new script, the asset should be null. The server
+// will create the new script based on the script_language (LSL or Lua)
+// If a template_id is provided, the new script will be a copy of that item.
+//
+// *IMPORTANT* If template_id is provided, it must be the ITEM ID of a
+// copy/mod-able script in the user's inventory. The simulator will verify
+// permissions.
+void LLViewerObject::saveScript(const LLViewerInventoryItem* item,
+ bool active, bool is_new, const LLUUID& template_id)
{
/*
* XXXPAM Investigate not making this copy. Seems unecessary, but I'm unsure about the
@@ -2798,12 +2853,104 @@ void LLViewerObject::saveScript(
msg->addBOOLFast(_PREHASH_Enabled, enabled);
msg->nextBlockFast(_PREHASH_InventoryBlock);
task_item->packMessage(msg);
+
+ // This is a completely new script (no asset id) and we've provided a template.
+ // Note that the script subtype on the template will override any subtype on the item.
+ if (task_item->getAssetUUID().isNull() && template_id.notNull())
+ {
+ msg->nextBlock("NewScriptInfo");
+ msg->addUUID("TemplateID", template_id);
+ }
+
msg->sendReliable(mRegionp->getHost());
// do the internal logic
doUpdateInventory(task_item, TASK_INVENTORY_ITEM_KEY, is_new);
}
+void LLViewerObject::createInventoryItem(
+ LLAssetType::EType asset_type,
+ LLInventoryType::EType inventory_type,
+ U8 sub_type,
+ const std::string& name,
+ const std::string& description,
+ const LLPermissions& permissions,
+ const LLSD& params,
+ std::function<void(bool, const LLSD&)> callback)
+{
+ if (!mRegionp)
+ {
+ if (callback) callback(false, LLSD().with("message", "No region"));
+ return;
+ }
+
+ std::string cap_url = mRegionp->getCapability("CreateTaskInventoryItem");
+ if (cap_url.empty())
+ {
+ if (callback) callback(false, LLSD().with("message", "Capability not available"));
+ return;
+ }
+
+ LLSD body;
+ body["object_id"] = mID;
+ body["inventory_type"] = (S32)inventory_type;
+ body["asset_type"] = (S32)asset_type;
+ body["sub_type"] = (S32)sub_type;
+ body["name"] = name;
+ body["description"] = description;
+
+ LLSD perm_llsd;
+ perm_llsd["base"] = (S32)permissions.getMaskBase();
+ perm_llsd["owner"] = (S32)permissions.getMaskOwner();
+ perm_llsd["everyone"] = (S32)permissions.getMaskEveryone();
+ perm_llsd["group"] = (S32)permissions.getMaskGroup();
+ perm_llsd["next_owner"] = (S32)permissions.getMaskNextOwner();
+ body["permissions"] = perm_llsd;
+
+ if (params.isDefined())
+ {
+ body["params"] = params;
+ }
+
+ LLCoros::instance().launch("LLViewerObject::createInventoryItemCoro",
+ boost::bind(&LLViewerObject::createInventoryItemCoro, cap_url, body, callback));
+}
+
+// static
+void LLViewerObject::createInventoryItemCoro(
+ const std::string cap_url, const LLSD body,
+ std::function<void(bool, const LLSD&)> callback)
+{
+ LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+ LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter =
+ std::make_shared<LLCoreHttpUtil::HttpCoroutineAdapter>("CreateTaskInventoryItem", httpPolicy);
+ LLCore::HttpRequest::ptr_t httpRequest = std::make_shared<LLCore::HttpRequest>();
+
+ LLSD result = httpAdapter->postAndSuspend(httpRequest, cap_url, body);
+
+ LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+ LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+ bool success = static_cast<bool>(status) && result["success"].asBoolean();
+
+ if (success)
+ {
+ LLUUID object_id = body["object_id"].asUUID();
+ LLViewerObject* obj = gObjectList.findObject(object_id);
+ if (obj)
+ {
+ ++obj->mExpectedInventorySerialNum;
+ obj->dirtyInventory();
+ obj->requestInventory();
+ }
+ }
+
+ if (callback)
+ {
+ callback(success, result);
+ }
+}
+
void LLViewerObject::moveInventory(const LLUUID& folder_id,
const LLUUID& item_id)
{
@@ -4035,6 +4182,11 @@ U32 LLViewerObject::getTriangleCount(S32* vcount) const
return 0;
}
+U32 LLViewerObject::getLODTriangleCount(S32 lod)
+{
+ return 0;
+}
+
U32 LLViewerObject::getHighLODTriangleCount()
{
return 0;
@@ -4056,6 +4208,27 @@ U32 LLViewerObject::recursiveGetTriangleCount(S32* vcount) const
return total_tris;
}
+void LLViewerObject::recursiveGetLODTriangleCount(S32& high_lod, S32& medium_lod, S32& low_lod, S32& lowest_lod)
+{
+ high_lod = (S32)getLODTriangleCount(LLModel::LOD_HIGH);
+ medium_lod = (S32)getLODTriangleCount(LLModel::LOD_MEDIUM);
+ low_lod = (S32)getLODTriangleCount(LLModel::LOD_LOW);
+ lowest_lod = (S32)getLODTriangleCount(LLModel::LOD_IMPOSTOR);
+ LLViewerObject::const_child_list_t& child_list = getChildren();
+ for (LLViewerObject::const_child_list_t::const_iterator iter = child_list.begin();
+ iter != child_list.end(); ++iter)
+ {
+ LLViewerObject* childp = *iter;
+ if (childp)
+ {
+ high_lod += (S32)childp->getLODTriangleCount(LLModel::LOD_HIGH);
+ medium_lod += (S32)childp->getLODTriangleCount(LLModel::LOD_MEDIUM);
+ low_lod += (S32)childp->getLODTriangleCount(LLModel::LOD_LOW);
+ lowest_lod += (S32)childp->getLODTriangleCount(LLModel::LOD_IMPOSTOR);
+ }
+ }
+}
+
// This is using the stored surface area for each volume (which
// defaults to 1.0 for the case of everything except a sculpt) and
// then scaling it linearly based on the largest dimension in the