diff --git a/pyogp/lib/base/appearance.py b/pyogp/lib/base/appearance.py
index 4dfbec2..debbd99 100644
--- a/pyogp/lib/base/appearance.py
+++ b/pyogp/lib/base/appearance.py
@@ -14,7 +14,7 @@ from pyogp.lib.base.message.message import Message, Block
from pyogp.lib.base.utilities.helpers import Helpers
from pyogp.lib.base.exc import NotImplemented
from pyogp.lib.base.objects import Object
-from pyogp.lib.base.params import VisualParams
+from pyogp.lib.base.visualparams import VisualParams
from pyogp.lib.base.datatypes import UUID, Vector3
from pyogp.lib.base.utilities.enums import BakedIndex, TextureIndex, \
WearableMap, AssetType, WearablesIndex
diff --git a/pyogp/lib/base/assets.py b/pyogp/lib/base/assets.py
index 9872a33..bf904de 100644
--- a/pyogp/lib/base/assets.py
+++ b/pyogp/lib/base/assets.py
@@ -14,9 +14,10 @@ from pyogp.lib.base.utilities.enums import TransferChannelType, TransferSourceTy
from pyogp.lib.base.message.message_handler import MessageHandler
from pyogp.lib.base.message.message import Message, Block
from pyogp.lib.base.utilities.helpers import Helpers
-from pyogp.lib.base.exc import NotImplemented
+from pyogp.lib.base.exc import NotImplemented, ResourceError, ResourceNotFound
from pyogp.lib.base.objects import Object
from pyogp.lib.base.datatypes import Vector3, UUID
+from pyogp.lib.base.caps import Capability
# initialize logging
@@ -35,12 +36,12 @@ class AssetManager(DataManager):
super(AssetManager, self).__init__(agent, settings)
#indexed by assetID
self.assets = {}
-
+
def enable_callbacks(self):
pass
- def request_asset(self, assetID, assetType, isPriority, callback):
+ def request_asset(self, assetID, assetType, isPriority, callback=None, itemID=None):
"""
Sends a TransferRequest to the sim for asset assetID with type assetType,
will call back with the assetID and True with asset received or False
@@ -55,26 +56,31 @@ class AssetManager(DataManager):
def onTransferPacket(packet):
"""
TransferPacket of a successful TransferRequest
+ TODO wait for all all packets to arrive and assemble the data
"""
# fill in data for Asset in the requests queue and pop it off and story in assets dict
if str(transferID) == str(packet.blocks['TransferData'][0].get_variable('TransferID').data):
self.assets[str(assetID)] = AssetWearable(assetID, assetType,
packet.blocks['TransferData'][0].get_variable('Data').data)
- callback(assetID, True)
+ if callback != None:
+ callback(assetID, True)
transferPacketHandler.unsubscribe(onTransferPacket)
def onTransferInfo(packet):
"""
Status of TransferRequest
Account for size and multiple packets
+ TODO set packet count
"""
+
if str(transferID) == str(packet.blocks['TransferInfo'][0].get_variable('TransferID')):
status = packet.blocks['TransferInfo'][0].get_variable("Status").data
if status != TransferStatus.OK:
log(WARNING, "Request for asset %s failed with status %s" \
% (assetID, status))
- callback(assetID, False)
+ if callback != None:
+ callback(assetID, False)
transferPacketHandler.unsubscribe(onTransferPacket)
transferInfoHandler.unsubscribe(onTransferInfo)
@@ -85,8 +91,17 @@ class AssetManager(DataManager):
priority = 1.0
else:
priortity = 0.0
- params = assetID.get_bytes() \
- + Helpers().int_to_bytes(assetType)
+
+ params = ''
+ if itemID != None:
+ params += self.agent.agent_id.get_bytes() + \
+ self.agent.session_id.get_bytes() + \
+ self.agent.agent_id.get_bytes() + \
+ UUID().get_bytes() + \
+ itemID.get_bytes()
+
+ params += assetID.get_bytes() + \
+ Helpers().int_to_bytes(assetType)
self.send_TransferRequest(transferID,
TransferChannelType.Asset,
@@ -94,11 +109,71 @@ class AssetManager(DataManager):
priority,
params)
+
+ """
+ def upload_asset(self, transaction_id, type_, tempfile, store_local,
+ asset_data=None):
+
+ assetUploadCompleteHandler = self.agent.region.message_handler.register('AssetUploadComplete')
+ def onAssetUploadComplete(packet):
+ log(INFO, "AssetUploadComplete: %s" % packet)
+
+ assetUploadCompleteHandler.subscribe(onAssetUploadComplete)
+
+ self.send_AssetUploadRequest(transaction_id, type_, tempfile,
+ store_local)
+ """
+ def upload_script_via_caps(self, item_id, script):
+
+ def upload_script_via_caps_responder(response):
+
+ if response['state'] == 'upload':
+ cap = Capability('UpdateScriptAgentResponse', response['uploader'])
+ response = cap.POST_FILE(script)
+ upload_script_via_caps_responder(response)
+ elif response['state'] == 'complete':
+ log(DEBUG, "Upload of script Successful")
+ else:
+ log(WARNING, "Upload failed")
+
+ cap = self.agent.region.capabilities['UpdateScriptAgent']
+ post_body = {'item_id' : str(item_id), 'target': 'lsl2'}
+ custom_headers = {'Accept' : 'application/llsd+xml'}
+
+ try:
+ response = cap.POST(post_body, custom_headers)
+ except ResourceError, error:
+ log(ERROR, error)
+ return
+ except ResourceNotFound, error:
+ log(ERROR, "404 calling: %s" % (error))
+ return
+ upload_script_via_caps_responder(response)
+
+
+
+
+ def upload_via_udp(self):
+ pass
def get_asset(self, assetID):
-
return self.assets[str(assetID)]
+ def send_AssetUploadRequest(self, TransactionID, Type, Tempfile, \
+ StoreLocal, AssetData=None):
+ """
+ Sends an AssetUploadRequest packet to request that an asset be
+ uploaded to the to the sim
+ """
+ packet = Message('AssetUploadRequest',
+ Block('AssetBlock',
+ TransactionID = TransactionID,
+ Type = Type,
+ Tempfile = Tempfile,
+ StoreLocal = StoreLocal,
+ AssetData = AssetData))
+ self.agent.region.enqueue_message(packet)
+
def send_TransferRequest(self, TransferID, ChannelType, SourceType,
Priority, Params):
@@ -118,8 +193,6 @@ class AssetManager(DataManager):
self.agent.region.enqueue_message(packet)
-
-
class Asset(object):
def __init__(self, assetID, assetType, data):
self.assetID = assetID
diff --git a/pyogp/lib/base/caps.py b/pyogp/lib/base/caps.py
index de3194a..b83549d 100644
--- a/pyogp/lib/base/caps.py
+++ b/pyogp/lib/base/caps.py
@@ -2,7 +2,7 @@
import urllib2
from types import *
from logging import getLogger, CRITICAL, ERROR, WARNING, INFO, DEBUG
-
+import re
# related
# pyogp
@@ -107,15 +107,42 @@ class Capability(object):
else:
raise ResourceError(self.public_url, e.code, e.msg, e.fp.read(), method="POST")
+ return self._response_handler(response)
+
+ def POST_FILE(self, file_name, custom_headers={}):
+ """ Opens file at file_name and posts contents to this cap. """
+ headers = {"Content-type" : "application/octet-stream"}
+ fd = open(file_name)
+ payload = fd.read()
+ fd.close
+
+ try:
+ response = self.restclient.POST(self.public_url,
+ payload, headers=headers)
+ except HTTPError, e:
+ if e.code==404:
+ raise ResourceNotFound(self.public_url)
+ else:
+ raise ResourceError(self.public_url, e.code, e.msg,
+ e.fp.read(), method="POST")
+
+ return self._response_handler(response)
+
+ def _response_handler(self, response):
# now deserialize the data again, we ask for a utility with the content type
# as the name
content_type_charset = response.headers['Content-Type']
content_type = content_type_charset.split(";")[0] # remove the charset part
+ pattern = re.compile('<\?xml\sversion="1.0"\s\?>.*?')
# ToDo: write a generic serializer/deserializer
- if (content_type == 'application/llsd+xml') or (content_type == 'application/xml'):
+ if (content_type == 'application/llsd+xml') or \
+ (content_type == 'application/xml') or \
+ (content_type == 'text/html' and \
+ pattern.match(response.body) != None):
deserializer = LLSDDeserializer()
else:
+ print response
raise DeserializerNotFound(content_type)
data = deserializer.deserialize(response.body)
@@ -125,6 +152,7 @@ class Capability(object):
return data
+
def __repr__(self):
return "" %(self.name, self.public_url)
diff --git a/pyogp/lib/base/inventory.py b/pyogp/lib/base/inventory.py
index 752ccc1..706b509 100644
--- a/pyogp/lib/base/inventory.py
+++ b/pyogp/lib/base/inventory.py
@@ -182,16 +182,17 @@ class InventoryManager(DataManager):
container[index[0]].inventory[inventory_index[0]] = inventory_item
if self.settings.LOG_VERBOSE:
- log(DEBUG, 'Replacing a stored inventory item: %s for agent \'%s\'' % (inventory_item.ItemID, self.agent.agent_id))
+ log(DEBUG, 'Replacing a stored inventory item: %s' % (inventory_item.ItemID))
except:
container[index[0]].inventory.append(inventory_item)
if self.settings.LOG_VERBOSE:
- log(DEBUG, 'Storing a new inventory item: %s in agent \'%s\'' % (inventory_item.ItemID, self.agent.agent_id))
+ log(DEBUG, 'Storing a new inventory item: %s ' % (inventory_item.ItemID))
- def search_inventory(self, folder_list = [], item_id = None, name = None, match_list = []):
+ def search_inventory(self, folder_list = [], item_id = None, name = None,
+ match_list = []):
""" search through all inventory folders for an id(uuid) or Name, and
return a list of matching InventoryItems or InventoryFolders
@@ -200,60 +201,52 @@ class InventoryManager(DataManager):
This does not request inventory from the grid. It could, were we to go about enabling this...
"""
+
+ def match():
+ _match = lambda arg : False
+ if item_id != None:
+ def _match(arg):
+ if isinstance(arg, InventoryItem):
+ return str(arg.ItemID) == str(item_id)
+ else:
+ return str(arg.FolderID) == str(item_id)
+ elif name != None:
+ pattern = re.compile(name)
+ def _match(arg):
+ if pattern.match(arg.Name):
+ return True
+ else:
+ return False
+ return _match
+
+ is_match = match()
# search our inventory storage if we aren't told what to look in
- if folder_list == []:
+ if folder_list == []:
search_folders = self.folders
else:
search_folders = folder_list
- if item_id != None:
-
- item_id = UUID(str(item_id))
-
- for item in search_folders:
-
- if isinstance(item, InventoryItem):
- if str(item.ItemID) == str(item_id):
- match_list.append(item)
-
- elif isinstance(item, InventoryFolder):
- matches = self.search_inventory_folder(item.FolderID, _id = item_id)
- match_list.extend(matches)
-
- return match_list
-
- elif name != None:
-
- for item in search_folders:
-
- pattern = re.compile(name)
-
- if isinstance(item, InventoryItem):
- if pattern.match(item.Name):
- match_list.append(item)
-
- elif isinstance(item, InventoryFolder):
- matches = self.search_inventory_folder(item.FolderID, name = name.strip())
- match_list.extend(matches)
-
- return match_list
-
- else:
-
- # return an empty list
- return []
-
+ for item in search_folders:
+ if is_match(item):
+ match_list.append(item)
+ if isinstance(item, InventoryFolder):
+ matches = self.search_inventory_folder(item.FolderID,
+ _id=item_id,
+ name=name)
+ match_list.extend(matches)
+ return match_list
+
def search_inventory_folder(self, folder_id, _id = None, name = None):
""" search an inventory folder for _id or name
return a list of matches
"""
-
+
match_list = []
-
+
search_folder = [folder for folder in self.folders if str(folder.FolderID) == str(folder_id)][0]
-
+
for item in search_folder.inventory:
if _id != None:
@@ -261,9 +254,8 @@ class InventoryManager(DataManager):
if isinstance(item, InventoryItem):
if str(item.ItemID) == str(_id):
match_list.append(item)
-
elif isinstance(item, InventoryFolder):
- if item.FolderID == _id:
+ if str(item.FolderID) == str(_id):
match_list.append(item)
elif name != None:
@@ -469,6 +461,81 @@ class InventoryManager(DataManager):
self.agent.send_ImprovedInstantMessage(self.agent.agent_id, self.agent.session_id, 0, FromAgentID, 0, UUID(), self.agent.Position, 0, accept_key, ID, 0, self.agent.Name(), '', '')
+ def create_new_item(self, folder, name, desc, asset_type, inv_type,
+ wearable_type, next_owner_permission, callback=None):
+ """
+ Creates a new item in folder.
+ """
+ transaction_id = UUID()
+ transaction_id.random()
+
+ updateCreateInventoryHandler = self.agent.region.message_handler.register('UpdateCreateInventoryItem')
+
+ def onUpdateCreateInventoryItem(packet):
+ if str(transaction_id) != \
+ str(packet.blocks['AgentData'][0]\
+ .get_variable('TransactionID').data):
+ inv_data = packet.blocks['InventoryData'][0]
+ item = InventoryItem(inv_data.get_variable('ItemID').data,
+ inv_data.get_variable('FolderID').data,
+ inv_data.get_variable('CreatorID').data,
+ inv_data.get_variable('OwnerID').data,
+ inv_data.get_variable('GroupID').data,
+ inv_data.get_variable('BaseMask').data,
+ inv_data.get_variable('OwnerMask').data,
+ inv_data.get_variable('GroupMask').data,
+ inv_data.get_variable('EveryoneMask').data,
+ inv_data.get_variable('NextOwnerMask').data,
+ inv_data.get_variable('GroupOwned').data,
+ inv_data.get_variable('AssetID').data,
+ inv_data.get_variable('Type').data,
+ inv_data.get_variable('InvType').data,
+ inv_data.get_variable('Flags').data,
+ inv_data.get_variable('SaleType').data,
+ inv_data.get_variable('SalePrice').data,
+ inv_data.get_variable('Name').data,
+ inv_data.get_variable('Description').data,
+ inv_data.get_variable('CreationDate').data,
+ inv_data.get_variable('CRC').data)
+
+ self._store_inventory_item(item)
+ updateCreateInventoryHandler.unsubscribe(onUpdateCreateInventoryItem)
+ if callback != None:
+ callback(item)
+
+ updateCreateInventoryHandler.subscribe(onUpdateCreateInventoryItem)
+
+ self.send_CreateInventoryItem(self.agent.agent_id,
+ self.agent.session_id,
+ 0,
+ folder.FolderID,
+ transaction_id,
+ next_owner_permission,
+ asset_type,
+ inv_type,
+ wearable_type,
+ name,
+ desc)
+
+ def send_CreateInventoryItem(self, agent_id, session_id, callback_id,
+ folder_id, transaction_id, next_owner_mask,
+ type_, inv_type, wearable_type, name, desc):
+ """ sends a CreateInventoryItem message """
+ args = [Block('AgentData',
+ AgentID = agent_id,
+ SessionID = session_id)]
+ args += [Block('InventoryBlock',
+ CallbackID = callback_id,
+ FolderID = folder_id,
+ TransactionID = transaction_id,
+ NextOwnerMask = next_owner_mask,
+ Type = type_,
+ InvType = inv_type,
+ WearableType = wearable_type,
+ Name = name,
+ Description = desc)]
+ self.agent.region.enqueue_message(Message("CreateInventoryItem", *args))
+
def sendFetchInventoryDescendentsRequest(self, folder_id = None):
""" send a request to the grid for folder contents """
@@ -863,7 +930,29 @@ class InventoryItem(object):
Tests: tests/test_inventory.py
"""
- def __init__(self, ItemID = None, FolderID = None, CreatorID = None, OwnerID = None, GroupID = None, BaseMask = None, OwnerMask = None, GroupMask = None, EveryoneMask = None, NextOwnerMask = 0, GroupOwned = None, AssetID = None, Type = None, InvType = None, Flags = None, SaleType = None, SalePrice = None, Name = None, Description = None, CreationDate = None, CRC = None, LastOwnerID = UUID()):
+ def __init__(self,
+ ItemID = None,
+ FolderID = None,
+ CreatorID = None,
+ OwnerID = None,
+ GroupID = None,
+ BaseMask = None,
+ OwnerMask = None,
+ GroupMask = None,
+ EveryoneMask = None,
+ NextOwnerMask = 0,
+ GroupOwned = None,
+ AssetID = None,
+ Type = None,
+ InvType = None,
+ Flags = None,
+ SaleType = None,
+ SalePrice = None,
+ Name = None,
+ Description = None,
+ CreationDate = None,
+ CRC = None,
+ LastOwnerID = UUID()):
""" initialize the inventory item """
self.type = 'InventoryItem'
@@ -984,47 +1073,49 @@ def sendRezObject(agent, inventory_item, RayStart, RayEnd, FromTaskID = UUID(),
packet = Message('RezObject',
Block('AgentData',
- AgentID = agent.agent_id,
- SessionID = agent.session_id,
- GroupID = agent.ActiveGroupID),
+ AgentID = agent.agent_id,
+ SessionID = agent.session_id,
+ GroupID = agent.ActiveGroupID),
Block('RezData',
- FromTaskID = UUID(str(FromTaskID)),
- BypassRaycast = BypassRaycast,
- RayStart = RayStart,
- RayEnd = RayEnd,
- RayTargetID = UUID(str(RayTargetID)),
- RayEndIsIntersection = RayEndIsIntersection,
- RezSelected = RezSelected,
- RemoveItem = RemoveItem,
- ItemFlags = ItemFlags,
- GroupMask = GroupMask,
- EveryoneMask = EveryoneMask,
- NextOwnerMask = NextOwnerMask),
+ FromTaskID = UUID(str(FromTaskID)),
+ BypassRaycast = BypassRaycast,
+ RayStart = RayStart,
+ RayEnd = RayEnd,
+ RayTargetID = UUID(str(RayTargetID)),
+ RayEndIsIntersection = RayEndIsIntersection,
+ RezSelected = RezSelected,
+ RemoveItem = RemoveItem,
+ ItemFlags = ItemFlags,
+ GroupMask = GroupMask,
+ EveryoneMask = EveryoneMask,
+ NextOwnerMask = NextOwnerMask),
Block('InventoryData',
- ItemID = inventory_item.ItemID,
- FolderID = inventory_item.FolderID,
- CreatorID = inventory_item.CreatorID,
- OwnerID = inventory_item.OwnerID,
- GroupID = inventory_item.GroupID,
- BaseMask = inventory_item.BaseMask,
- OwnerMask = inventory_item.OwnerMask,
- GroupMask = inventory_item.GroupMask,
- EveryoneMask = inventory_item.EveryoneMask,
- GroupOwned = inventory_item.GroupOwned,
- TransactionID = UUID(),
- Type = inventory_item.Type,
- InvType = inventory_item.InvType,
- Flags = inventory_item.Flags,
- SaleType = inventory_item.SaleType,
- SalePrice = inventory_item.SalePrice,
- Name = inventory_item.Name,
- Description = inventory_item.Description,
- CreationDate = inventory_item.CreationDate,
- CRC = inventory_item.CRC,
- NextOwnerMask = inventory_item.NextOwnerMask))
+ ItemID = inventory_item.ItemID,
+ FolderID = inventory_item.FolderID,
+ CreatorID = inventory_item.CreatorID,
+ OwnerID = inventory_item.OwnerID,
+ GroupID = inventory_item.GroupID,
+ BaseMask = inventory_item.BaseMask,
+ OwnerMask = inventory_item.OwnerMask,
+ GroupMask = inventory_item.GroupMask,
+ EveryoneMask = inventory_item.EveryoneMask,
+ GroupOwned = inventory_item.GroupOwned,
+ TransactionID = UUID(),
+ Type = inventory_item.Type,
+ InvType = inventory_item.InvType,
+ Flags = inventory_item.Flags,
+ SaleType = inventory_item.SaleType,
+ SalePrice = inventory_item.SalePrice,
+ Name = inventory_item.Name,
+ Description = inventory_item.Description,
+ CreationDate = inventory_item.CreationDate,
+ CRC = inventory_item.CRC,
+ NextOwnerMask = inventory_item.NextOwnerMask))
agent.region.enqueue_message(packet)
+
+
"""
Contributors can be viewed at:
http://svn.secondlife.com/svn/linden/projects/2008/pyogp/CONTRIBUTORS.txt
diff --git a/pyogp/lib/base/objects.py b/pyogp/lib/base/objects.py
index 7bcdee7..a81a3cb 100644
--- a/pyogp/lib/base/objects.py
+++ b/pyogp/lib/base/objects.py
@@ -7,11 +7,13 @@ import math
# related
+
# pyogp
from pyogp.lib.base import *
from pyogp.lib.base.datamanager import DataManager
from pyogp.lib.base.permissions import PermissionsTarget, PermissionsMask
from pyogp.lib.base.datatypes import UUID, Vector3, Quaternion
+from pyogp.lib.base.event_system import AppEvent
# pyogp message
from pyogp.lib.base.message.message_handler import MessageHandler
@@ -20,7 +22,8 @@ from pyogp.lib.base.message.message import Message, Block
# pyogp utilities
from pyogp.lib.base.utilities.helpers import Helpers
-from pyogp.lib.base.utilities.enums import PCodeEnum, CompressedUpdateFlags
+from pyogp.lib.base.utilities.enums import PCodeEnum, CompressedUpdateFlags, \
+ Permissions, AssetType
# initialize logging
logger = getLogger('pyogp.lib.base.objects')
@@ -329,6 +332,11 @@ class ObjectManager(DataManager):
else:
#if self.settings.LOG_VERBOSE and self.settings.ENABLE_OBJECT_LOGGING: log(DEBUG, "Updating an object's attributes. LocalID = %s" % (object_properties['LocalID']))
_object._update_properties(prim_properties)
+ if _object.UpdateFlags & 2 != 0 and self.agent != None:
+
+ self.agent.events_handler.handle(AppEvent("ObjectSelected",
+ payload = {'object':_object}))
+
def request_object_update(self, AgentID, SessionID, ID_CacheMissType_list = None):
""" requests object updates from the simulator
@@ -360,9 +368,28 @@ class ObjectManager(DataManager):
# not sure what RayTargetID is, send as uuid of zeros
RayTargetID = UUID()
- self.object_add(self.agent.agent_id, self.agent.session_id, GroupID = GroupID, PCode = PCodeEnum.Primitive, Material = 3, AddFlags = 2, PathCurve = 16, ProfileCurve = 1, PathBegin = 0, PathEnd = 0, PathScaleX = 100, PathScaleY = 100, PathShearX = 0, PathShearY = 0, PathTwist = 0, PathTwistBegin = 0, PathRadiusOffset = 0, PathTaperX = 0, PathTaperY = 0, PathRevolutions = 0, PathSkew = 0, ProfileBegin = 0, ProfileEnd = 0, ProfileHollow = 0, BypassRaycast = 1, RayStart = location_to_rez, RayEnd = location_to_rez, RayTargetID = RayTargetID, RayEndIsIntersection = 0, Scale = (0.5, 0.5, 0.5), Rotation = (0, 0, 0, 1), State = 0)
+ self.object_add(self.agent.agent_id, self.agent.session_id,
+ GroupID = GroupID, PCode = PCodeEnum.Primitive,
+ Material = 3, AddFlags = 2, PathCurve = 16,
+ ProfileCurve = 1, PathBegin = 0, PathEnd = 0,
+ PathScaleX = 100, PathScaleY = 100, PathShearX = 0,
+ PathShearY = 0, PathTwist = 0, PathTwistBegin = 0,
+ PathRadiusOffset = 0, PathTaperX = 0, PathTaperY = 0,
+ PathRevolutions = 0, PathSkew = 0, ProfileBegin = 0,
+ ProfileEnd = 0, ProfileHollow = 0, BypassRaycast = 1,
+ RayStart = location_to_rez, RayEnd = location_to_rez,
+ RayTargetID = RayTargetID, RayEndIsIntersection = 0,
+ Scale = (0.5, 0.5, 0.5), Rotation = (0, 0, 0, 1),
+ State = 0)
- def object_add(self, AgentID, SessionID, PCode, Material, AddFlags, PathCurve, ProfileCurve, PathBegin, PathEnd, PathScaleX, PathScaleY, PathShearX, PathShearY, PathTwist, PathTwistBegin, PathRadiusOffset, PathTaperX, PathTaperY, PathRevolutions, PathSkew, ProfileBegin, ProfileEnd, ProfileHollow, BypassRaycast, RayStart, RayEnd, RayTargetID, RayEndIsIntersection, Scale, Rotation, State, GroupID = UUID()):
+ def object_add(self, AgentID, SessionID, PCode, Material, AddFlags,
+ PathCurve, ProfileCurve, PathBegin, PathEnd, PathScaleX,
+ PathScaleY, PathShearX, PathShearY, PathTwist,
+ PathTwistBegin, PathRadiusOffset, PathTaperX,
+ PathTaperY, PathRevolutions, PathSkew, ProfileBegin,
+ ProfileEnd, ProfileHollow, BypassRaycast, RayStart,
+ RayEnd, RayTargetID, RayEndIsIntersection, Scale,
+ Rotation, State, GroupID = UUID()):
'''
ObjectAdd - create new object in the world
Simulator will assign ID and send message back to signal
@@ -580,7 +607,7 @@ class ObjectManager(DataManager):
X=Helpers.packed_u8_to_float(objdata, 13, -REGION_SIZE, REGION_SIZE),
Y=Helpers.packed_u8_to_float(objdata, 14, -REGION_SIZE, REGION_SIZE),
Z=Helpers.packed_u8_to_float(objdata, 15, -REGION_SIZE, REGION_SIZE))
-
+
object_list.append(object_properties)
self.update_multiple_objects_properties(object_list)
@@ -913,6 +940,61 @@ class ObjectManager(DataManager):
self.update_multiple_objects_properties(object_list)
+ def send_RezScript(self, agent, prim, item_id=UUID(),
+ Enabled=True,
+ GroupID=UUID(),
+ BaseMask=Permissions.All,
+ OwnerMask=Permissions.All,
+ GroupMask=Permissions.None_,
+ EveryoneMask=Permissions.None_,
+ NextOwnerMask=Permissions.Transfer&Permissions.Move,
+ GroupOwned=False,
+ Type=AssetType.LSLText,
+ InvType=AssetType.LSLText,
+ Flags=0,
+ SaleType=0,
+ SalePrice=0,
+ Name="New Script",
+ Description="Created by PyOGP",
+ CreationDate=0,
+ CRC=0):
+ """ sends a RezScript message to the sim, not providing a item_id will
+ rez the default script otherwise the script with ItemID item_id will be rezzed
+ to prim"""
+ packet = Message('RezScript',
+ Block('AgentData',
+ AgentID = agent.agent_id,
+ SessionID = agent.session_id,
+ GroupID = agent.ActiveGroupID),
+ Block('UpdateBlock',
+ ObjectLocalID = prim.LocalID,
+ Enabled = Enabled),
+ Block('InventoryBlock',
+ ItemID = item_id,
+ FolderID = prim.FullID,
+ CreatorID = agent.agent_id,
+ OwnerID = agent.agent_id,
+ GroupID = GroupID,
+ BaseMask = BaseMask,
+ OwnerMask = OwnerMask,
+ GroupMask = GroupMask,
+ EveryoneMask = EveryoneMask,
+ NextOwnerMask = NextOwnerMask,
+ GroupOwned = GroupOwned,
+ TransactionID = UUID(),
+ Type = Type,
+ InvType = InvType,
+ Flags = Flags,
+ SaleType = SaleType,
+ SalePrice = SalePrice,
+ Name = Name,
+ Description = Description,
+ CreationDate = CreationDate,
+ CRC = CRC))
+ agent.region.enqueue_message(packet)
+
+
+
class Object(object):
""" represents an Object
@@ -1214,7 +1296,7 @@ class Object(object):
"""
- self.send_ObjectSelect(agent, agent.agent_id, agent.session_id, [self.LocalID])
+ self.send_ObjectDeselect(agent, agent.agent_id, agent.session_id, [self.LocalID])
def send_ObjectDeselect(self, agent, AgentID, SessionID, ObjectLocalIDs):
""" send an ObjectDeselect message to the agent's host simulator
@@ -1230,13 +1312,15 @@ class Object(object):
agent.region.enqueue_message(packet)
+
def _update_properties(self, properties):
""" takes a dictionary of attribute:value and makes it so """
- for attribute in properties:
+ for attribute in properties.keys():
setattr(self, attribute, properties[attribute])
+
"""
Contributors can be viewed at:
http://svn.secondlife.com/svn/linden/projects/2008/pyogp/CONTRIBUTORS.txt
diff --git a/pyogp/lib/base/tests/test_appearance.py b/pyogp/lib/base/tests/test_appearance.py
index cdacbc1..971b015 100644
--- a/pyogp/lib/base/tests/test_appearance.py
+++ b/pyogp/lib/base/tests/test_appearance.py
@@ -22,8 +22,6 @@ class TestAppearance(unittest.TestCase):
self.settings = Settings()
self.agent = Agent()
self.appearance = AppearanceManager(self.agent, settings = self.settings)
-
-
self.agent.agent_id = UUID("01234567-89ab-cdef-0123-456789abcdef")
self.agent.session_id = UUID("fedcba98-7654-3210-fedc-ba9876543210")
self.agent.region = DummyRegion()
diff --git a/pyogp/lib/base/tests/test_inventory.py b/pyogp/lib/base/tests/test_inventory.py
index 14137e1..fa5e3f9 100644
--- a/pyogp/lib/base/tests/test_inventory.py
+++ b/pyogp/lib/base/tests/test_inventory.py
@@ -5,7 +5,14 @@ import unittest
import uuid
# pyogp
-from pyogp.lib.base.inventory import InventoryManager, InventoryFolder
+from pyogp.lib.base.inventory import InventoryManager, InventoryFolder, \
+ InventoryItem
+from pyogp.lib.base.datatypes import UUID
+from pyogp.lib.base.agent import Agent
+from pyogp.lib.base.region import Region
+from pyogp.lib.base.utilities.enums import AssetType, InventoryType, \
+ WearablesIndex, Permissions
+from pyogp.lib.base.message.message import Message, Block
# pyogp tests
import pyogp.lib.base.tests.config
@@ -16,37 +23,186 @@ class TestInventory(unittest.TestCase):
self.inventory = InventoryManager()
- self.folder_data = [{'parent_id': '00000000-0000-0000-0000-000000000000', 'version': 154, 'name': 'My Inventory', 'type_default': 8, 'folder_id': '0201a00f-afde-477d-967b-e731d186b9d6'}, {'parent_id': '0201a00f-afde-477d-967b-e731d186b9d6', 'version': 9, 'name': 'Trash', 'type_default': 14, 'folder_id': '1640c442-85a9-c917-361a-f86bf72dab1a'}, {'parent_id': '0201a00f-afde-477d-967b-e731d186b9d6', 'version': 1, 'name': 'Animations', 'type_default': 20, 'folder_id': '2e406320-ab10-6e2e-8f6f-de2572ffd426'}, {'parent_id': '0201a00f-afde-477d-967b-e731d186b9d6', 'version': 6, 'name': 'Daft Tux', 'type_default': -1, 'folder_id': '3d62430b-9a61-7921-f376-46fb81b61594'}, {'parent_id': '0201a00f-afde-477d-967b-e731d186b9d6', 'version': 2, 'name': 'Bot attachments1', 'type_default': -1, 'folder_id': '54e00f7f-1110-26d4-de54-6bd0809a429b'}, {'parent_id': '0201a00f-afde-477d-967b-e731d186b9d6', 'version': 4, 'name': 'Daft Tux', 'type_default': -1, 'folder_id': '57e90615-2b0f-f029-3c09-3bbfa89f09f1'}, {'parent_id': '0201a00f-afde-477d-967b-e731d186b9d6', 'version': 394, 'name': 'Totoro', 'type_default': -1, 'folder_id': '6115057c-8db5-be07-2701-397b819e84a5'}, {'parent_id': '0201a00f-afde-477d-967b-e731d186b9d6', 'version': 3, 'name': 'Calling Cards', 'type_default': 2, 'folder_id': '629d9d71-ffc3-dbe4-3b96-0dc75c7be1bc'}, {'parent_id': '0201a00f-afde-477d-967b-e731d186b9d6', 'version': 5, 'name': 'PinkieBot', 'type_default': -1, 'folder_id': '8a0cef67-18d8-fb6d-06ef-f1520595cf34'}, {'parent_id': '0201a00f-afde-477d-967b-e731d186b9d6', 'version': 96, 'name': 'Objects', 'type_default': 6, 'folder_id': '8ed27f52-b020-509b-585d-ad2f3bfbce05'}, {'parent_id': '0201a00f-afde-477d-967b-e731d186b9d6', 'version': 4, 'name': 'Notecards', 'type_default': 7, 'folder_id': '909ee313-b342-88b5-dca4-45d9df75b4b8'}, {'parent_id': '0201a00f-afde-477d-967b-e731d186b9d6', 'version': 7, 'name': 'PinkieBot', 'type_default': -1, 'folder_id': '948c687f-ae1e-bf86-3faa-6cd1b2f132ff'}, {'parent_id': '0201a00f-afde-477d-967b-e731d186b9d6', 'version': 1, 'name': 'Textures', 'type_default': 0, 'folder_id': '9aacf954-8a44-f4ca-5913-34d035eeae41'}, {'parent_id': '0201a00f-afde-477d-967b-e731d186b9d6', 'version': 1, 'name': 'Sounds', 'type_default': 1, 'folder_id': 'bf2a5d50-2766-5031-1ffb-20acd137b58f'}, {'parent_id': '0201a00f-afde-477d-967b-e731d186b9d6', 'version': 1, 'name': 'Lost And Found', 'type_default': 16, 'folder_id': 'd6d82d34-47ff-afec-f71f-b1ea20df9ccb'}, {'parent_id': '0201a00f-afde-477d-967b-e731d186b9d6', 'version': 675, 'name': 'Totoro Box for Bots', 'type_default': -1, 'folder_id': 'e2bc553b-d0c4-c588-f664-04d8474f8376'}, {'parent_id': '0201a00f-afde-477d-967b-e731d186b9d6', 'version': 1, 'name': 'Landmarks', 'type_default': 3, 'folder_id': 'e7c67062-6b47-feb6-85d7-86013cdb068c'}, {'parent_id': '0201a00f-afde-477d-967b-e731d186b9d6', 'version': 1, 'name': 'Scripts', 'type_default': 10, 'folder_id': 'f7e94373-f376-fd46-59a5-57d2562bf514'}, {'parent_id': '52aaafe8-7c5e-8fe0-b47e-097198648c9b', 'version': 4, 'name': 'PinkieBot', 'type_default': -1, 'folder_id': '155551ef-c49a-98b8-d554-ab9f7a1b1ae8'}, {'parent_id': '52aaafe8-7c5e-8fe0-b47e-097198648c9b', 'version': 2, 'name': 'Bot attachments1', 'type_default': -1, 'folder_id': '15edc217-14dc-b454-7c82-535e2fa423b2'}, {'parent_id': '52aaafe8-7c5e-8fe0-b47e-097198648c9b', 'version': 63, 'name': 'Trash', 'type_default': 14, 'folder_id': '52aaafe8-7c5e-8fe0-b47e-097198648c9b'}, {'parent_id': '52aaafe8-7c5e-8fe0-b47e-097198648c9b', 'version': 1, 'name': 'Photo Album', 'type_default': 15, 'folder_id': '580fb866-1c5f-4f58-8927-0d9e295799f4'}, {'parent_id': '52aaafe8-7c5e-8fe0-b47e-097198648c9b', 'version': 2, 'name': 'Calling Cards', 'type_default': 2, 'folder_id': '6f4c244f-8f14-42f9-a900-4b73f9a2a48e'}, {'parent_id': '52aaafe8-7c5e-8fe0-b47e-097198648c9b', 'version': 7, 'name': 'Scripts', 'type_default': 10, 'folder_id': '7adc4a9a-0370-4833-a25c-872be4ae6e22'}, {'parent_id': '52aaafe8-7c5e-8fe0-b47e-097198648c9b', 'version': 1, 'name': 'Landmarks', 'type_default': 3, 'folder_id': '7b3f2f88-666e-4b68-80b1-4dab3359ba3b'}, {'parent_id': '52aaafe8-7c5e-8fe0-b47e-097198648c9b', 'version': 5, 'name': 'Textures', 'type_default': 0, 'folder_id': '82af0bfc-42e5-4134-980d-a7587e563499'}, {'parent_id': '52aaafe8-7c5e-8fe0-b47e-097198648c9b', 'version': 8, 'name': 'Notecards', 'type_default': 7, 'folder_id': '8fe0babc-c915-4481-9299-2ec868541496'}, {'parent_id': '52aaafe8-7c5e-8fe0-b47e-097198648c9b', 'version': 9, 'name': 'Body Parts', 'type_default': 13, 'folder_id': 'aba5a5d2-9e13-401c-943d-95f79904c487'}, {'parent_id': '52aaafe8-7c5e-8fe0-b47e-097198648c9b', 'version': 3, 'name': 'Gestures', 'type_default': 21, 'folder_id': 'bd1d2af5-df49-4b98-9fc6-301b49042a89'}, {'parent_id': '52aaafe8-7c5e-8fe0-b47e-097198648c9b', 'version': 49, 'name': 'Objects', 'type_default': 6, 'folder_id': 'c55798a9-463a-4065-9604-4572924387a8'}, {'parent_id': '52aaafe8-7c5e-8fe0-b47e-097198648c9b', 'version': 7, 'name': 'Clothing', 'type_default': 5, 'folder_id': 'c833cc69-ee0d-4d50-b014-be8101cbb7c1'}, {'parent_id': '52aaafe8-7c5e-8fe0-b47e-097198648c9b', 'version': 21, 'name': 'Object', 'type_default': -1, 'folder_id': 'cc22dc06-71fa-0059-f2af-64723c987068'}, {'parent_id': '52aaafe8-7c5e-8fe0-b47e-097198648c9b', 'version': 37, 'name': 'Lost And Found', 'type_default': 16, 'folder_id': 'd01c9207-347f-48cc-a307-06f7a967e974'}, {'parent_id': '52aaafe8-7c5e-8fe0-b47e-097198648c9b', 'version': 1, 'name': 'Animations', 'type_default': 20, 'folder_id': 'dcb179f7-a58a-4b97-8bfa-bc395988945a'}, {'parent_id': '52aaafe8-7c5e-8fe0-b47e-097198648c9b', 'version': 45, 'name': 'Totoro', 'type_default': -1, 'folder_id': 'effd593a-10b8-8fb1-52a3-86b930b5b6cb'}, {'parent_id': '52aaafe8-7c5e-8fe0-b47e-097198648c9b', 'version': 1, 'name': 'Sounds', 'type_default': 1, 'folder_id': 'fca217d3-62b9-498f-b084-a137582850da'}, {'parent_id': 'bd1d2af5-df49-4b98-9fc6-301b49042a89', 'version': 19, 'name': 'Female Gestures', 'type_default': -1, 'folder_id': '01a2f40b-a034-5911-d6a3-7804547c105a'}, {'parent_id': 'bd1d2af5-df49-4b98-9fc6-301b49042a89', 'version': 28, 'name': 'Common Gestures', 'type_default': -1, 'folder_id': '38bc2d0e-f626-6fd6-3ea7-cb8f9b753af3'}]
-
- def tearDown(self):
-
- pass
-
- def test_display_folder_contents_by_id(self):
+ self.folder_data = [{'parent_id': '00000000-0000-0000-0000-000000000000', 'version': 154, 'name': 'My Inventory', 'type_default': 8, 'folder_id': '0201a00f-afde-477d-967b-e731d186b9d6'},
+ {'parent_id': '0201a00f-afde-477d-967b-e731d186b9d6', 'version': 9, 'name': 'Trash', 'type_default': 14, 'folder_id': '1640c442-85a9-c917-361a-f86bf72dab1a'},
+ {'parent_id': '0201a00f-afde-477d-967b-e731d186b9d6', 'version': 1, 'name': 'Animations', 'type_default': 20, 'folder_id': '2e406320-ab10-6e2e-8f6f-de2572ffd426'},
+ {'parent_id': '0201a00f-afde-477d-967b-e731d186b9d6', 'version': 6, 'name': 'Daft Tux', 'type_default': -1, 'folder_id': '3d62430b-9a61-7921-f376-46fb81b61594'},
+ {'parent_id': '0201a00f-afde-477d-967b-e731d186b9d6', 'version': 2, 'name': 'Bot attachments1', 'type_default': -1, 'folder_id': '54e00f7f-1110-26d4-de54-6bd0809a429b'},
+ {'parent_id': '0201a00f-afde-477d-967b-e731d186b9d6', 'version': 4, 'name': 'Daft Tux', 'type_default': -1, 'folder_id': '57e90615-2b0f-f029-3c09-3bbfa89f09f1'},
+ {'parent_id': '0201a00f-afde-477d-967b-e731d186b9d6', 'version': 394, 'name': 'Totoro', 'type_default': -1, 'folder_id': '6115057c-8db5-be07-2701-397b819e84a5'},
+ {'parent_id': '0201a00f-afde-477d-967b-e731d186b9d6', 'version': 3, 'name': 'Calling Cards', 'type_default': 2, 'folder_id': '629d9d71-ffc3-dbe4-3b96-0dc75c7be1bc'},
+ {'parent_id': '0201a00f-afde-477d-967b-e731d186b9d6', 'version': 5, 'name': 'PinkieBot', 'type_default': -1, 'folder_id': '8a0cef67-18d8-fb6d-06ef-f1520595cf34'},
+ {'parent_id': '0201a00f-afde-477d-967b-e731d186b9d6', 'version': 96, 'name': 'Objects', 'type_default': 6, 'folder_id': '8ed27f52-b020-509b-585d-ad2f3bfbce05'},
+ {'parent_id': '0201a00f-afde-477d-967b-e731d186b9d6', 'version': 4, 'name': 'Notecards', 'type_default': 7, 'folder_id': '909ee313-b342-88b5-dca4-45d9df75b4b8'},
+ {'parent_id': '0201a00f-afde-477d-967b-e731d186b9d6', 'version': 7, 'name': 'PinkieBot', 'type_default': -1, 'folder_id': '948c687f-ae1e-bf86-3faa-6cd1b2f132ff'},
+ {'parent_id': '0201a00f-afde-477d-967b-e731d186b9d6', 'version': 1, 'name': 'Textures', 'type_default': 0, 'folder_id': '9aacf954-8a44-f4ca-5913-34d035eeae41'},
+ {'parent_id': '0201a00f-afde-477d-967b-e731d186b9d6', 'version': 1, 'name': 'Sounds', 'type_default': 1, 'folder_id': 'bf2a5d50-2766-5031-1ffb-20acd137b58f'},
+ {'parent_id': '0201a00f-afde-477d-967b-e731d186b9d6', 'version': 1, 'name': 'Lost And Found', 'type_default': 16, 'folder_id': 'd6d82d34-47ff-afec-f71f-b1ea20df9ccb'},
+ {'parent_id': '0201a00f-afde-477d-967b-e731d186b9d6', 'version': 675, 'name': 'Totoro Box for Bots', 'type_default': -1, 'folder_id': 'e2bc553b-d0c4-c588-f664-04d8474f8376'},
+ {'parent_id': '0201a00f-afde-477d-967b-e731d186b9d6', 'version': 1, 'name': 'Landmarks', 'type_default': 3, 'folder_id': 'e7c67062-6b47-feb6-85d7-86013cdb068c'},
+ {'parent_id': '0201a00f-afde-477d-967b-e731d186b9d6', 'version': 1, 'name': 'Scripts', 'type_default': 10, 'folder_id': 'f7e94373-f376-fd46-59a5-57d2562bf514'},
+ {'parent_id': '52aaafe8-7c5e-8fe0-b47e-097198648c9b', 'version': 4, 'name': 'PinkieBot', 'type_default': -1, 'folder_id': '155551ef-c49a-98b8-d554-ab9f7a1b1ae8'},
+ {'parent_id': '52aaafe8-7c5e-8fe0-b47e-097198648c9b', 'version': 2, 'name': 'Bot attachments1', 'type_default': -1, 'folder_id': '15edc217-14dc-b454-7c82-535e2fa423b2'},
+ {'parent_id': '52aaafe8-7c5e-8fe0-b47e-097198648c9b', 'version': 63, 'name': 'Trash', 'type_default': 14, 'folder_id': '52aaafe8-7c5e-8fe0-b47e-097198648c9b'},
+ {'parent_id': '52aaafe8-7c5e-8fe0-b47e-097198648c9b', 'version': 1, 'name': 'Photo Album', 'type_default': 15, 'folder_id': '580fb866-1c5f-4f58-8927-0d9e295799f4'},
+ {'parent_id': '52aaafe8-7c5e-8fe0-b47e-097198648c9b', 'version': 2, 'name': 'Calling Cards', 'type_default': 2, 'folder_id': '6f4c244f-8f14-42f9-a900-4b73f9a2a48e'},
+ {'parent_id': '52aaafe8-7c5e-8fe0-b47e-097198648c9b', 'version': 7, 'name': 'Scripts', 'type_default': 10, 'folder_id': '7adc4a9a-0370-4833-a25c-872be4ae6e22'},
+ {'parent_id': '52aaafe8-7c5e-8fe0-b47e-097198648c9b', 'version': 1, 'name': 'Landmarks', 'type_default': 3, 'folder_id': '7b3f2f88-666e-4b68-80b1-4dab3359ba3b'},
+ {'parent_id': '52aaafe8-7c5e-8fe0-b47e-097198648c9b', 'version': 5, 'name': 'Textures', 'type_default': 0, 'folder_id': '82af0bfc-42e5-4134-980d-a7587e563499'},
+ {'parent_id': '52aaafe8-7c5e-8fe0-b47e-097198648c9b', 'version': 8, 'name': 'Notecards', 'type_default': 7, 'folder_id': '8fe0babc-c915-4481-9299-2ec868541496'},
+ {'parent_id': '52aaafe8-7c5e-8fe0-b47e-097198648c9b', 'version': 9, 'name': 'Body Parts', 'type_default': 13, 'folder_id': 'aba5a5d2-9e13-401c-943d-95f79904c487'},
+ {'parent_id': '52aaafe8-7c5e-8fe0-b47e-097198648c9b', 'version': 3, 'name': 'Gestures', 'type_default': 21, 'folder_id': 'bd1d2af5-df49-4b98-9fc6-301b49042a89'},
+ {'parent_id': '52aaafe8-7c5e-8fe0-b47e-097198648c9b', 'version': 49, 'name': 'Objects', 'type_default': 6, 'folder_id': 'c55798a9-463a-4065-9604-4572924387a8'},
+ {'parent_id': '52aaafe8-7c5e-8fe0-b47e-097198648c9b', 'version': 7, 'name': 'Clothing', 'type_default': 5, 'folder_id': 'c833cc69-ee0d-4d50-b014-be8101cbb7c1'},
+ {'parent_id': '52aaafe8-7c5e-8fe0-b47e-097198648c9b', 'version': 21, 'name': 'Object', 'type_default': -1, 'folder_id': 'cc22dc06-71fa-0059-f2af-64723c987068'},
+ {'parent_id': '52aaafe8-7c5e-8fe0-b47e-097198648c9b', 'version': 37, 'name': 'Lost And Found', 'type_default': 16, 'folder_id': 'd01c9207-347f-48cc-a307-06f7a967e974'},
+ {'parent_id': '52aaafe8-7c5e-8fe0-b47e-097198648c9b', 'version': 1, 'name': 'Animations', 'type_default': 20, 'folder_id': 'dcb179f7-a58a-4b97-8bfa-bc395988945a'},
+ {'parent_id': '52aaafe8-7c5e-8fe0-b47e-097198648c9b', 'version': 45, 'name': 'Totoro', 'type_default': -1, 'folder_id': 'effd593a-10b8-8fb1-52a3-86b930b5b6cb'},
+ {'parent_id': '52aaafe8-7c5e-8fe0-b47e-097198648c9b', 'version': 1, 'name': 'Sounds', 'type_default': 1, 'folder_id': 'fca217d3-62b9-498f-b084-a137582850da'},
+ {'parent_id': 'bd1d2af5-df49-4b98-9fc6-301b49042a89', 'version': 19, 'name': 'Female Gestures', 'type_default': -1, 'folder_id': '01a2f40b-a034-5911-d6a3-7804547c105a'},
+ {'parent_id': 'bd1d2af5-df49-4b98-9fc6-301b49042a89', 'version': 28, 'name': 'Common Gestures', 'type_default': -1, 'folder_id': '38bc2d0e-f626-6fd6-3ea7-cb8f9b753af3'}]
for folder in self.folder_data:
-
self.inventory._store_inventory_folder(folder)
+ uuid_ = UUID('12345678-1234-1234-1234-123456789abc')
+ inventory_item = InventoryItem(uuid_,
+ '0201a00f-afde-477d-967b-e731d186b9d6',
+ uuid_,
+ uuid_,
+ UUID(),
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ False,
+ uuid_,
+ 10,
+ 10,
+ 0,
+ 0,
+ 0,
+ "a_item",
+ "a_item_desc",
+ 0,
+ 0)
+ self.inventory._store_inventory_item(inventory_item)
+
+ def tearDown(self):
+ self.inventory = None
+ self.folder_data = None
+
+ def test_display_folder_contents_by_id(self):
+
self.assertEquals(len(self.inventory.display_folder_contents(folder_id = uuid.UUID('52aaafe8-7c5e-8fe0-b47e-097198648c9b'))), 18)
def test_display_folder_contents_by_nonexistant_id(self):
- for folder in self.folder_data:
-
- self.inventory._store_inventory_folder(folder)
-
self.assertEquals(len(self.inventory.display_folder_contents(folder_id = uuid.UUID('00000001-0000-0000-0000-000000000000'))), 0)
- '''
- def test_display_folder_contents_by_name(self):
+ def test_search_inventory_for_folders(self):
+
+ matches = self.inventory.search_inventory(self.inventory.folders,
+ item_id='0201a00f-afde-477d-967b-e731d186b9d6')
+ self.assertEqual(len(matches), 1)
+ folder = matches.pop()
+ self.assertEqual(folder.Name, 'My Inventory')
+
+ matches = self.inventory.search_inventory(self.inventory.folders,
+ name='Trash')
+ self.assertTrue(len(matches), 1)
+ folder = matches.pop()
+ self.assertEqual(str(folder.FolderID), '52aaafe8-7c5e-8fe0-b47e-097198648c9b')
+
+ def test_search_inventory_for_items(self):
+
+ matches = self.inventory.search_inventory(self.inventory.folders,
+ item_id='12345678-1234-1234-1234-123456789abc')
+ self.assertTrue(len(matches), 1)
+ item = matches.pop()
+ self.assertEqual(item.Name, 'a_item')
+
+ matches = self.inventory.search_inventory(self.inventory.folders,
+ name='a_item')
+ self.assertTrue(len(matches), 1)
+ item = matches.pop()
+ self.assertEqual(str(item.ItemID), '12345678-1234-1234-1234-123456789abc')
+
+ def test_create_new_item(self):
+
+ self.inventory.agent = Agent()
+ agent_id = UUID()
+ agent_id.random()
+ self.inventory.agent.agent_id = agent_id
+
+ self.inventory.agent.region = DummyRegion()
+
+ matches = self.inventory.search_inventory(self.inventory.folders,
+ name='My Inventory')
+ self.assertEqual(len(matches), 1)
+ folder = matches.pop()
+ self.inventory.create_new_item(folder, "Name", "Desc", AssetType.LSLText,
+ InventoryType.LSL, WearablesIndex.WT_SHAPE,
+ 0)
+ packet = self.inventory.agent.region.dummy_packet_holder.pop()
+ self.assertEqual(packet.name, "CreateInventoryItem")
+
+ self.assertEqual(packet.get_block('InventoryBlock')[0].get_variable('FolderID').data, folder.FolderID)
+ self.assertEqual(packet.get_block('InventoryBlock')[0].get_variable('Name').data, 'Name')
+ self.assertEqual(packet.get_block('InventoryBlock')[0].get_variable('Description').data, 'Desc')
+
+ fake_uuid = UUID()
+ fake_uuid.random()
+ packet = Message('UpdateCreateInventoryItem',
+ Block('AgentData',
+ AgentID = UUID(),
+ SimApproved = True,
+ TransactionID = UUID()),
+ Block('InventoryData',
+ ItemID=fake_uuid,
+ FolderID=folder.FolderID,
+ CallbackID=0,
+ CreatorID=agent_id,
+ OwnerID=agent_id,
+ GroupID=UUID(),
+ BaseMask=Permissions.All,
+ OwnerMask=Permissions.All,
+ GroupMask=Permissions.None_,
+ EveryoneMask=Permissions.None_,
+ NextOwnerMask=Permissions.None_,
+ GroupOwned=False,
+ AssetID=UUID(),
+ Type=AssetType.LSLText,
+ InvType=InventoryType.LSL,
+ Flags=0,
+ SaleType=0,
+ SalePrice=0,
+ Name="Name",
+ Description="Desc",
+ CreationDate=0,
+ CRC=0))
+ self.inventory.agent.region.message_handler.handle(packet)
+ matches = self.inventory.search_inventory(self.inventory.folders,
+ name="Name")
+ self.assertEqual(len(matches), 1)
+ item = matches.pop()
+ self.assertEqual(item.Name, "Name")
+ '''
+ def test_display_folder_contents_by_name(self):
for folder in self.folder_data:
self.inventory._store_inventory_folder(folder)
self.assertEquals(len(self.inventory._display_folder_contents(name = 'Trash')), 18)
- '''
+ '''
+
+
+class DummyRegion(Region):
+ dummy_packet_holder = []
+ def enqueue_message(self, packet, reliable = False):
+ self.dummy_packet_holder.append(packet)
def test_suite():
from unittest import TestSuite, makeSuite
diff --git a/pyogp/lib/base/tests/test_objects.py b/pyogp/lib/base/tests/test_objects.py
index 5b7bad6..eee8182 100644
--- a/pyogp/lib/base/tests/test_objects.py
+++ b/pyogp/lib/base/tests/test_objects.py
@@ -8,9 +8,12 @@ from binascii import unhexlify
from pyogp.lib.base.objects import *
from pyogp.lib.base.settings import Settings
from pyogp.lib.base.region import Region
+from pyogp.lib.base.agent import Agent
+from pyogp.lib.base.datatypes import UUID, Vector3
# pyogp messaging
from pyogp.lib.base.message.udpdeserializer import UDPMessageDeserializer
+from pyogp.lib.base.message.message import Message, Block
# pyogp tests
import pyogp.lib.base.tests.config
@@ -29,6 +32,7 @@ class TestObjects(unittest.TestCase):
self.object_store = ObjectManager(region = self.region, settings = self.settings)
self.object_store.enable_callbacks()
+ self.data = []
def tearDown(self):
pass
@@ -67,7 +71,59 @@ class TestObjects(unittest.TestCase):
self.assertEquals(known_objects, [(str(uuid.UUID('e2ba7ac7-db28-24e3-484d-f418b045e62d')), 159536), (str(uuid.UUID('6cbafc4a-9758-9481-cd74-c7ccc89e7440')), 171059), (str(uuid.UUID('d2b300c3-71f1-6887-2750-6d48da05e2f5')), 171036), (str(uuid.UUID('dbb7d110-3f65-0859-d494-3dc40ffb2b61')), 171037), (str(uuid.UUID('1f389eb9-8639-28ff-c37b-a3e4f39a7fed')), 171038)])
+ def test_onObjectUpdate_selected(self):
+ self.object_store.agent = Agent()
+ fake_uuid = UUID()
+ fake_uuid.random()
+ packet = Message('ObjectUpdate',
+ Block('RegionData',
+ RegionHandle=0,
+ TimeDilation=0),
+ Block('ObjectData',
+ ID=1,
+ State=1,
+ FullID=fake_uuid,
+ CRC=0,
+ PCode=0,
+ Material=0,
+ ClickAction=0,
+ Scale=Vector3(X=0.0, Y=0.0, Z=0.0),
+ ObjectData='',
+ ParentID=fake_uuid,
+ UpdateFlags=0,
+ ProfileCurve=0,
+ PathBegin=0.0,
+ PathEnd=0.0,
+ PathScaleX=0.0,
+ PathScaleY=0.0,
+ PathShearX=0.0,
+ PathShearY=0.0,
+ PathTwist=-1,
+ PathTwistBegin=-1,
+ PathRadiusOffset=-1,
+ PathTaperX=-1,
+ PathTaperY=-1,
+ PathRevolutions=0,
+ PathSkew=-1,
+ ProfileBegin=0,
+ ProfileEnd=0,
+ ProfileHollow=0,
+ TextureEntry='',
+ TextureAnim='',
+ NameValue='Test',
+ Data='',
+ Text='',
+ TextColor=0x0,
+ MedialURL=''))
+
+ def callback(payload):
+ self.data.append("foo")
+ object_handler = self.object_store.agent.events_handler.register("ObjectSelected")
+ object_handler.subscribe(callback)
+ self.object_store.region.message_handler.handle(packet)
+ self.assertTrue(self.data.pop, "foo")
+
def test_suite():
from unittest import TestSuite, makeSuite
suite = TestSuite()
diff --git a/pyogp/lib/base/utilities/enums.py b/pyogp/lib/base/utilities/enums.py
index 8e78028..b825cff 100644
--- a/pyogp/lib/base/utilities/enums.py
+++ b/pyogp/lib/base/utilities/enums.py
@@ -439,7 +439,17 @@ class TransferStatus(object):
Error = -1
UnknownSource = -2
InsufficientPermissions = -3
-
+
+
+
+class Permissions(object):
+ Transfer = 1 << 13
+ Modify = 1 << 14
+ Copy = 1 << 15
+ Move = 1 << 19
+ None_ = 0
+ All = 0x7FFFFFFF
+ Unrestricted = Transfer | Modify | Copy
"""
Contributors can be viewed at:
http://svn.secondlife.com/svn/linden/projects/2008/pyogp/CONTRIBUTORS.txt
diff --git a/pyogp/lib/base/params.py b/pyogp/lib/base/visualparams.py
similarity index 100%
rename from pyogp/lib/base/params.py
rename to pyogp/lib/base/visualparams.py