2009-03-04 07:27:56 +00:00
# standard python libs
from logging import getLogger , CRITICAL , ERROR , WARNING , INFO , DEBUG
2009-03-05 21:50:23 +00:00
import uuid
2009-03-17 20:45:07 +00:00
import re
2009-03-18 21:32:21 +00:00
from binascii import hexlify
import struct
2009-03-24 23:21:47 +00:00
import math
2009-03-04 07:27:56 +00:00
# related
# pyogp
2009-03-18 21:32:21 +00:00
from pyogp . lib . base import *
2009-03-26 02:02:29 +00:00
from pyogp . lib . base . permissions import *
2009-03-11 22:52:07 +00:00
# pyogp message
2009-06-05 21:02:59 +00:00
from pyogp . lib . base . message . message_handler import MessageHandler
2009-03-05 21:50:23 +00:00
from pyogp . lib . base . message . packets import *
2009-03-18 21:32:21 +00:00
from pyogp . lib . base . datatypes import *
2009-03-11 22:52:07 +00:00
# pyogp utilities
2009-03-05 21:50:23 +00:00
from pyogp . lib . base . utilities . helpers import Helpers
2009-04-27 22:48:01 +00:00
from pyogp . lib . base . utilities . enums import *
2009-03-04 07:27:56 +00:00
# initialize logging
2009-03-18 21:32:21 +00:00
logger = getLogger ( ' pyogp.lib.base.objects ' )
2009-03-04 07:27:56 +00:00
log = logger . log
class Objects ( object ) :
2009-03-11 04:57:22 +00:00
""" is an Object Manager
2009-03-04 07:27:56 +00:00
2009-03-11 04:57:22 +00:00
Initialize the event queue client class
>> > objects = Objects ( )
2009-03-04 07:27:56 +00:00
2009-03-11 04:57:22 +00:00
Sample implementations : region . py
Tests : tests / test_objects . py
"""
2009-03-04 07:27:56 +00:00
2009-06-05 21:02:59 +00:00
def __init__ ( self , agent = None , region = None , settings = None , message_handler = None , events_handler = None ) :
2009-03-11 04:57:22 +00:00
""" set up the inventory manager """
2009-03-04 07:27:56 +00:00
2009-03-11 04:57:22 +00:00
# allow the settings to be passed in
# otherwise, grab the defaults
if settings != None :
self . settings = settings
else :
from pyogp . lib . base . settings import Settings
self . settings = Settings ( )
2009-03-04 07:27:56 +00:00
2009-03-11 04:57:22 +00:00
self . agent = agent
self . region = region
2009-03-05 21:50:23 +00:00
2009-03-11 04:57:22 +00:00
# the object store consists of a list
# of Object() instances
self . object_store = [ ]
2009-03-05 21:50:23 +00:00
2009-03-17 04:24:08 +00:00
# the avatar store consists of a list
# of Avatar() instances
self . avatar_store = [ ]
2009-03-11 04:57:22 +00:00
# other useful things
self . helpers = Helpers ( )
2009-03-05 21:50:23 +00:00
2009-03-11 04:57:22 +00:00
# set up callbacks
if self . settings . HANDLE_PACKETS :
2009-06-05 21:02:59 +00:00
# otherwise, let's just use our own
if message_handler != None :
self . message_handler = message_handler
2009-03-11 04:57:22 +00:00
else :
2009-06-05 21:02:59 +00:00
self . message_handler = MessageHandler ( )
2009-03-11 03:56:56 +00:00
2009-06-05 22:22:13 +00:00
onObjectUpdate_received = self . message_handler . register ( ' ObjectUpdate ' )
2009-04-06 21:29:17 +00:00
onObjectUpdate_received . subscribe ( self . onObjectUpdate )
2009-03-11 03:56:56 +00:00
2009-06-05 22:22:13 +00:00
onObjectUpdateCached_received = self . message_handler . register ( ' ObjectUpdateCached ' )
2009-04-06 21:29:17 +00:00
onObjectUpdateCached_received . subscribe ( self . onObjectUpdateCached )
2009-03-14 00:09:15 +00:00
2009-06-05 22:22:13 +00:00
onObjectUpdateCompressed_received = self . message_handler . register ( ' ObjectUpdateCompressed ' )
2009-04-06 21:29:17 +00:00
onObjectUpdateCompressed_received . subscribe ( self . onObjectUpdateCompressed )
2009-03-11 03:56:56 +00:00
2009-06-05 22:22:13 +00:00
onObjectProperties_received = self . message_handler . register ( ' ObjectProperties ' )
2009-04-06 21:29:17 +00:00
onObjectProperties_received . subscribe ( self . onObjectProperties )
2009-03-22 05:37:11 +00:00
2009-06-05 22:22:13 +00:00
onKillObject_received = self . message_handler . register ( ' KillObject ' )
2009-04-06 21:29:17 +00:00
onKillObject_received . subscribe ( self . onKillObject )
2009-03-17 04:24:08 +00:00
2009-04-03 22:00:50 +00:00
# uncomment these to view packets sent back to simulator
2009-06-05 22:22:13 +00:00
# onObjectName_sent = self.message_handler.register('ObjectName')
2009-04-03 22:00:50 +00:00
# onObjectName_sent.subscribe(self.helpers.log_packet, self)
2009-06-05 22:22:13 +00:00
# onDeRezObject_sent = self.message_handler.register('DeRezObject')
2009-04-03 22:00:50 +00:00
# onDeRezObject_sent.subscribe(self.helpers.log_packet, self)
2009-03-17 04:24:08 +00:00
2009-03-11 04:57:22 +00:00
if self . settings . LOG_VERBOSE : log ( INFO , " Initializing object storage " )
2009-03-11 03:56:56 +00:00
2009-03-20 06:15:22 +00:00
def process_multiple_object_updates ( self , objects ) :
""" process a list of object updates """
[ self . process_object_update ( _object ) for _object in objects ]
2009-03-19 18:26:31 +00:00
def process_object_update ( self , _object ) :
2009-03-11 04:57:22 +00:00
""" append to or replace an object in self.objects """
2009-03-11 03:56:56 +00:00
2009-03-18 21:32:21 +00:00
# this is an avatar
if _object . PCode == 47 :
self . store_avatar ( _object )
# this is a Primitive
elif _object . PCode == 9 :
self . store_object ( _object )
else :
if self . settings . LOG_VERBOSE : log ( DEBUG , " Not processing object update of type %s " % ( PCode ( PCode ) ) )
def store_object ( self , _object ) :
2009-03-11 04:57:22 +00:00
# replace an existing list member, else, append
2009-03-11 03:56:56 +00:00
2009-03-22 05:37:11 +00:00
index = [ self . object_store . index ( _object_ ) for _object_ in self . object_store if _object_ . LocalID == _object . LocalID ]
2009-03-11 03:56:56 +00:00
2009-03-18 21:32:21 +00:00
if index != [ ] :
2009-03-11 03:56:56 +00:00
2009-03-11 04:57:22 +00:00
self . object_store [ index [ 0 ] ] = _object
2009-03-11 03:56:56 +00:00
2009-03-24 23:01:16 +00:00
#if self.settings.LOG_VERBOSE: log(DEBUG, 'Updating a stored object: %s in region \'%s\'' % (_object.FullID, self.region.SimName))
2009-03-11 03:56:56 +00:00
2009-03-18 21:32:21 +00:00
else :
2009-03-11 03:56:56 +00:00
2009-03-11 04:57:22 +00:00
self . object_store . append ( _object )
2009-03-11 03:56:56 +00:00
2009-03-24 23:01:16 +00:00
#if self.settings.LOG_VERBOSE: log(DEBUG, 'Stored a new object: %s in region \'%s\'' % (_object.LocalID, self.region.SimName))
2009-03-11 03:56:56 +00:00
2009-03-18 21:32:21 +00:00
def store_avatar ( self , _objectdata ) :
# if the object data pertains to us, update our data!
if str ( _objectdata . FullID ) == str ( self . agent . agent_id ) :
2009-03-21 06:28:10 +00:00
self . agent . Position = _objectdata . Position
self . agent . FootCollisionPlane = _objectdata . FootCollisionPlane
self . agent . Velocity = _objectdata . Velocity
self . agent . Acceleration = _objectdata . Acceleration
self . agent . Rotation = _objectdata . Rotation
self . agent . AngularVelocity = _objectdata . AngularVelocity
2009-03-18 21:32:21 +00:00
2009-03-22 05:37:11 +00:00
index = [ self . avatar_store . index ( _avatar_ ) for _avatar_ in self . avatar_store if _avatar_ . LocalID == _objectdata . LocalID ]
2009-03-18 21:32:21 +00:00
if index != [ ] :
self . avatar_store [ index [ 0 ] ] = _objectdata
2009-03-24 23:01:16 +00:00
#if self.settings.LOG_VERBOSE: log(DEBUG, 'Replacing a stored avatar: %s in region \'%s\'' % (_objectdata.LocalID, self.region.SimName))
2009-03-18 21:32:21 +00:00
else :
self . avatar_store . append ( _objectdata )
2009-03-24 23:01:16 +00:00
#if self.settings.LOG_VERBOSE: log(DEBUG, 'Stored a new avatar: %s in region \'%s\'' % (_objectdata.LocalID, self.region.SimName))
2009-03-18 21:32:21 +00:00
2009-03-22 05:37:11 +00:00
def get_object_from_store ( self , LocalID = None , FullID = None ) :
2009-03-11 04:57:22 +00:00
""" searches the store and returns object if stored, None otherwise """
2009-03-11 03:56:56 +00:00
2009-03-22 05:37:11 +00:00
_object = [ ]
if LocalID != None :
_object = [ _object for _object in self . object_store if _object . LocalID == LocalID ]
2009-03-11 04:57:22 +00:00
elif FullID != None :
2009-03-22 05:37:11 +00:00
_object = [ _object for _object in self . object_store if str ( _object . FullID ) == str ( FullID ) ]
if _object == [ ] :
2009-03-11 04:57:22 +00:00
return None
2009-03-22 05:37:11 +00:00
else :
return _object [ 0 ]
2009-03-11 03:56:56 +00:00
2009-03-22 05:37:11 +00:00
def get_avatar_from_store ( self , LocalID = None , FullID = None ) :
2009-03-18 21:32:21 +00:00
""" searches the store and returns object if stored, None otherwise """
2009-03-22 05:37:11 +00:00
if LocalID != None :
_avatar = [ _avatar for _avatar in self . avatar_store if _avatar . LocalID == LocalID ]
2009-03-18 21:32:21 +00:00
elif FullID != None :
_avatar = [ _avatar for _avatar in self . avatar_store if _avatar . FullID == FullID ]
2009-03-24 23:01:16 +00:00
if _avatar == [ ] :
2009-03-18 21:32:21 +00:00
return None
2009-03-24 23:01:16 +00:00
else :
return _avatar [ 0 ]
def my_objects ( self ) :
""" returns a list of known objects where the calling client is the owner """
2009-03-24 23:21:47 +00:00
matches = [ _object for _object in self . object_store if str ( _object . OwnerID ) == str ( self . agent . agent_id ) ]
return matches
2009-03-18 21:32:21 +00:00
2009-03-17 20:45:07 +00:00
def find_objects_by_name ( self , Name ) :
""" searches the store for known objects by name
2009-03-18 21:32:21 +00:00
2009-03-17 20:45:07 +00:00
returns a list of all such known objects
"""
pattern = re . compile ( Name )
2009-03-20 06:15:22 +00:00
matches = [ _object for _object in self . object_store if pattern . match ( _object . Name ) ]
2009-03-17 20:45:07 +00:00
return matches
2009-03-21 00:12:45 +00:00
def find_objects_within_radius ( self , radius ) :
2009-03-22 05:37:11 +00:00
""" returns objects nearby. returns a list of objects """
if type ( radius ) != float :
radius = float ( radius )
objects_nearby = [ ]
for item in self . object_store :
if item . Position == None : continue
2009-03-21 00:12:45 +00:00
2009-03-24 23:21:47 +00:00
if math . sqrt ( math . pow ( ( item . Position . X - self . agent . Position . X ) , 2 ) + math . pow ( ( item . Position . Y - self . agent . Position . Y ) , 2 ) + math . pow ( ( item . Position . Z - self . agent . Position . Z ) , 2 ) ) < = radius :
2009-03-22 05:37:11 +00:00
objects_nearby . append ( item )
return objects_nearby
2009-03-21 00:12:45 +00:00
2009-03-17 04:24:08 +00:00
def remove_object_from_store ( self , ID = None ) :
2009-03-24 23:01:16 +00:00
victim = self . get_object_from_store ( LocalID = ID )
if victim == None :
victim = self . get_avatar_from_store ( LocalID = ID )
2009-04-06 21:29:17 +00:00
# if we do not know about this object, pass
if victim == None or victim == [ ] :
return
2009-03-18 21:32:21 +00:00
# this is an avatar
2009-04-03 22:00:50 +00:00
if victim . PCode == 47 :
2009-03-18 21:32:21 +00:00
self . kill_stored_avatar ( ID )
# this is a Primitive
2009-04-03 22:00:50 +00:00
elif victim . PCode == 9 :
2009-03-18 21:32:21 +00:00
self . kill_stored_object ( ID )
else :
if self . settings . LOG_VERBOSE and self . settings . ENABLE_OBJECT_LOGGING : log ( DEBUG , " Not processing kill of unstored object type %s " % ( PCode ( PCode ) ) )
2009-03-17 04:24:08 +00:00
2009-03-18 21:32:21 +00:00
def kill_stored_avatar ( self , ID ) :
2009-04-03 22:00:50 +00:00
index = [ self . avatar_store . index ( _avatar_ ) for _avatar_ in self . avatar_store if _avatar_ . LocalID == ID ]
2009-03-18 21:32:21 +00:00
if index != [ ] :
del self . avatar_store [ index [ 0 ] ]
if self . settings . LOG_VERBOSE and self . settings . ENABLE_OBJECT_LOGGING : log ( DEBUG , " Kill on object data for avatar tracked as local id %s " % ( ID ) )
def kill_stored_object ( self , ID ) :
2009-04-03 22:00:50 +00:00
index = [ self . object_store . index ( _object_ ) for _object_ in self . object_store if _object_ . LocalID == ID ]
2009-03-18 21:32:21 +00:00
if index != [ ] :
del self . object_store [ index [ 0 ] ]
if self . settings . LOG_VERBOSE and self . settings . ENABLE_OBJECT_LOGGING : log ( DEBUG , " Kill on object data for object tracked as local id %s " % ( ID ) )
2009-03-17 04:24:08 +00:00
2009-03-22 05:37:11 +00:00
def update_multiple_objects_properties ( self , object_list ) :
""" update the attributes of objects """
2009-03-24 23:01:16 +00:00
#if self.settings.LOG_VERBOSE and self.settings.ENABLE_OBJECT_LOGGING: log(DEBUG, "Processing multiple object properties updates: %s" % (len(object_list)))
2009-03-22 05:37:11 +00:00
for object_properties in object_list :
self . update_object_properties ( object_properties )
2009-03-20 06:15:22 +00:00
2009-03-22 05:37:11 +00:00
def update_object_properties ( self , object_properties ) :
""" update the attributes of an object
2009-03-20 06:15:22 +00:00
2009-03-22 05:37:11 +00:00
If the object is known , we update the properties .
If not , we create a new object
"""
2009-03-24 23:01:16 +00:00
#if self.settings.LOG_VERBOSE and self.settings.ENABLE_OBJECT_LOGGING: log(DEBUG, "Processing object properties update for FullID: %s" % (object_properties['FullID']))
2009-03-22 05:37:11 +00:00
if object_properties . has_key ( ' PCode ' ) :
# this is an avatar
if object_properties [ ' PCode ' ] == 47 :
#if self.settings.LOG_VERBOSE and self.settings.ENABLE_OBJECT_LOGGING: log(DEBUG, "Creating a new avatar and storing their attributes. LocalID = %s" % (object_properties['LocalID']))
_object = Object ( )
2009-04-30 06:52:08 +00:00
_object . _update_properties ( object_properties )
2009-03-22 05:37:11 +00:00
self . store_avatar ( _object )
else :
self . update_prim_properties ( object_properties )
2009-03-20 06:15:22 +00:00
else :
2009-03-22 05:37:11 +00:00
self . update_prim_properties ( object_properties )
def update_prim_properties ( self , prim_properties ) :
_object = self . get_object_from_store ( FullID = prim_properties [ ' FullID ' ] )
if _object == None :
#if self.settings.LOG_VERBOSE and self.settings.ENABLE_OBJECT_LOGGING: log(DEBUG, "Creating a new object and storing it's attributes. LocalID = %s" % (object_properties['LocalID']))
_object = Object ( )
2009-04-30 06:52:08 +00:00
_object . _update_properties ( prim_properties )
2009-03-22 05:37:11 +00:00
self . store_object ( _object )
else :
#if self.settings.LOG_VERBOSE and self.settings.ENABLE_OBJECT_LOGGING: log(DEBUG, "Updating an object's attributes. LocalID = %s" % (object_properties['LocalID']))
2009-04-30 06:52:08 +00:00
_object . _update_properties ( prim_properties )
2009-03-20 06:15:22 +00:00
2009-03-11 04:57:22 +00:00
def request_object_update ( self , ID = None , ID_list = None ) :
""" requests object updates from the simulator
2009-03-11 03:56:56 +00:00
2009-03-11 04:57:22 +00:00
accepts a tuple of ( ID , CacheMissType ) , or a list of such tuples
"""
2009-03-11 03:56:56 +00:00
2009-03-11 04:57:22 +00:00
packet = RequestMultipleObjectsPacket ( )
2009-04-27 22:48:01 +00:00
packet . AgentData [ ' AgentID ' ] = self . agent . agent_id
packet . AgentData [ ' SessionID ' ] = self . agent . session_id
2009-03-11 03:56:56 +00:00
2009-03-11 04:57:22 +00:00
if ID != None :
2009-03-11 03:56:56 +00:00
2009-03-11 04:57:22 +00:00
ObjectData = { }
2009-03-14 00:09:15 +00:00
ObjectData [ ' CacheMissType ' ] = ID [ 1 ]
ObjectData [ ' ID ' ] = ID [ 0 ]
2009-03-11 03:56:56 +00:00
2009-03-11 04:57:22 +00:00
packet . ObjectDataBlocks . append ( ObjectData )
2009-03-11 03:56:56 +00:00
2009-03-11 04:57:22 +00:00
else :
2009-03-11 03:56:56 +00:00
for ID in ID_list :
ObjectData = { }
2009-03-14 00:09:15 +00:00
ObjectData [ ' CacheMissType ' ] = ID [ 1 ]
ObjectData [ ' ID ' ] = ID [ 0 ]
2009-03-11 03:56:56 +00:00
packet . ObjectDataBlocks . append ( ObjectData )
2009-03-11 04:57:22 +00:00
# enqueue the message, send as reliable
self . region . enqueue_message ( packet ( ) , True )
2009-04-27 22:48:01 +00:00
def create_default_box ( self , GroupID = UUID ( ) , relative_position = ( 1 , 0 , 0 ) ) :
2009-03-11 04:57:22 +00:00
""" creates the default box, defaulting as 1m to the east, with an option GroupID to set the prim to """
# self.agent.Position holds where we are. we need to add this tuple to the incoming tuple (vector to a vector)
2009-03-24 23:01:16 +00:00
location_to_rez_x = self . agent . Position . X + relative_position [ 0 ]
location_to_rez_y = self . agent . Position . Y + relative_position [ 1 ]
location_to_rez_z = self . agent . Position . Z + relative_position [ 2 ]
2009-03-11 04:57:22 +00:00
location_to_rez = ( location_to_rez_x , location_to_rez_y , location_to_rez_z )
# not sure what RayTargetID is, send as uuid of zeros
2009-04-27 22:48:01 +00:00
RayTargetID = UUID ( )
2009-03-11 04:57:22 +00:00
self . object_add ( GroupID = GroupID , PCode = 9 , 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 )
2009-04-27 22:48:01 +00:00
def object_add ( self , 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 ( ) ) :
2009-03-11 04:57:22 +00:00
'''
ObjectAdd - create new object in the world
Simulator will assign ID and send message back to signal
object actually created .
AddFlags ( see also ObjectUpdate )
0x01 - use physics
0x02 - create selected
GroupID defaults to ( No group active )
'''
packet = ObjectAddPacket ( )
# build the AgentData block
2009-04-27 22:48:01 +00:00
packet . AgentData [ ' AgentID ' ] = self . agent . agent_id
packet . AgentData [ ' SessionID ' ] = self . agent . session_id
packet . AgentData [ ' GroupID ' ] = GroupID
2009-03-11 04:57:22 +00:00
2009-03-20 06:15:22 +00:00
# build the ObjectData block (it's a Single)
2009-03-11 04:57:22 +00:00
packet . ObjectData [ ' PCode ' ] = PCode
packet . ObjectData [ ' Material ' ] = Material
packet . ObjectData [ ' AddFlags ' ] = AddFlags
packet . ObjectData [ ' PathCurve ' ] = PathCurve
packet . ObjectData [ ' ProfileCurve ' ] = ProfileCurve
packet . ObjectData [ ' PathBegin ' ] = PathBegin
packet . ObjectData [ ' PathEnd ' ] = PathEnd
packet . ObjectData [ ' PathScaleX ' ] = PathScaleX
packet . ObjectData [ ' PathScaleY ' ] = PathScaleY
packet . ObjectData [ ' PathShearX ' ] = PathShearX
packet . ObjectData [ ' PathShearY ' ] = PathShearY
packet . ObjectData [ ' PathTwist ' ] = PathTwist
packet . ObjectData [ ' PathTwistBegin ' ] = PathTwistBegin
packet . ObjectData [ ' PathRadiusOffset ' ] = PathRadiusOffset
packet . ObjectData [ ' PathTaperX ' ] = PathTaperX
packet . ObjectData [ ' PathTaperY ' ] = PathTaperY
packet . ObjectData [ ' PathRevolutions ' ] = PathRevolutions
packet . ObjectData [ ' PathSkew ' ] = PathSkew
packet . ObjectData [ ' ProfileBegin ' ] = ProfileBegin
packet . ObjectData [ ' ProfileEnd ' ] = ProfileEnd
packet . ObjectData [ ' ProfileHollow ' ] = ProfileHollow
packet . ObjectData [ ' BypassRaycast ' ] = BypassRaycast
packet . ObjectData [ ' RayStart ' ] = RayStart
packet . ObjectData [ ' RayEnd ' ] = RayEnd
2009-04-27 22:48:01 +00:00
packet . ObjectData [ ' RayTargetID ' ] = RayTargetID
2009-03-11 04:57:22 +00:00
packet . ObjectData [ ' RayEndIsIntersection ' ] = RayEndIsIntersection
packet . ObjectData [ ' Scale ' ] = Scale
packet . ObjectData [ ' Rotation ' ] = Rotation
packet . ObjectData [ ' State ' ] = State
self . region . enqueue_message ( packet ( ) , True )
2009-04-06 21:29:17 +00:00
def onObjectUpdate ( self , packet ) :
""" populates an Object instance and adds it to the Objects() store """
object_list = [ ]
# ToDo: handle these 2 variables properly
2009-06-05 21:02:59 +00:00
_RegionHandle = packet . blocks [ ' RegionData ' ] [ 0 ] . get_variable ( ' RegionHandle ' ) . data
_TimeDilation = packet . blocks [ ' RegionData ' ] [ 0 ] . get_variable ( ' TimeDilation ' ) . data
2009-04-06 21:29:17 +00:00
2009-06-05 21:02:59 +00:00
for ObjectData_block in packet . blocks [ ' ObjectData ' ] :
2009-04-06 21:29:17 +00:00
object_properties = { }
object_properties [ ' LocalID ' ] = ObjectData_block . get_variable ( ' ID ' ) . data
object_properties [ ' State ' ] = ObjectData_block . get_variable ( ' State ' ) . data
object_properties [ ' FullID ' ] = ObjectData_block . get_variable ( ' FullID ' ) . data
object_properties [ ' CRC ' ] = ObjectData_block . get_variable ( ' CRC ' ) . data
object_properties [ ' PCode ' ] = ObjectData_block . get_variable ( ' PCode ' ) . data
object_properties [ ' Material ' ] = ObjectData_block . get_variable ( ' Material ' ) . data
object_properties [ ' ClickAction ' ] = ObjectData_block . get_variable ( ' ClickAction ' ) . data
object_properties [ ' Scale ' ] = ObjectData_block . get_variable ( ' Scale ' ) . data
object_properties [ ' ObjectData ' ] = ObjectData_block . get_variable ( ' ObjectData ' ) . data
object_properties [ ' ParentID ' ] = ObjectData_block . get_variable ( ' ParentID ' ) . data
object_properties [ ' UpdateFlags ' ] = ObjectData_block . get_variable ( ' UpdateFlags ' ) . data
object_properties [ ' PathCurve ' ] = ObjectData_block . get_variable ( ' PathCurve ' ) . data
object_properties [ ' ProfileCurve ' ] = ObjectData_block . get_variable ( ' ProfileCurve ' ) . data
object_properties [ ' PathBegin ' ] = ObjectData_block . get_variable ( ' PathBegin ' ) . data
object_properties [ ' PathEnd ' ] = ObjectData_block . get_variable ( ' PathEnd ' ) . data
object_properties [ ' PathScaleX ' ] = ObjectData_block . get_variable ( ' PathScaleX ' ) . data
object_properties [ ' PathScaleY ' ] = ObjectData_block . get_variable ( ' PathScaleY ' ) . data
object_properties [ ' PathShearX ' ] = ObjectData_block . get_variable ( ' PathShearX ' ) . data
object_properties [ ' PathShearY ' ] = ObjectData_block . get_variable ( ' PathShearY ' ) . data
object_properties [ ' PathTwist ' ] = ObjectData_block . get_variable ( ' PathTwist ' ) . data
object_properties [ ' PathTwistBegin ' ] = ObjectData_block . get_variable ( ' PathTwistBegin ' ) . data
object_properties [ ' PathRadiusOffset ' ] = ObjectData_block . get_variable ( ' PathRadiusOffset ' ) . data
object_properties [ ' PathTaperX ' ] = ObjectData_block . get_variable ( ' PathTaperX ' ) . data
object_properties [ ' PathTaperY ' ] = ObjectData_block . get_variable ( ' PathTaperY ' ) . data
object_properties [ ' PathRevolutions ' ] = ObjectData_block . get_variable ( ' PathRevolutions ' ) . data
object_properties [ ' PathSkew ' ] = ObjectData_block . get_variable ( ' PathSkew ' ) . data
object_properties [ ' ProfileBegin ' ] = ObjectData_block . get_variable ( ' ProfileBegin ' ) . data
object_properties [ ' ProfileEnd ' ] = ObjectData_block . get_variable ( ' ProfileEnd ' ) . data
object_properties [ ' ProfileHollow ' ] = ObjectData_block . get_variable ( ' ProfileHollow ' ) . data
object_properties [ ' TextureEntry ' ] = ObjectData_block . get_variable ( ' TextureEntry ' ) . data
object_properties [ ' TextureAnim ' ] = ObjectData_block . get_variable ( ' TextureAnim ' ) . data
object_properties [ ' NameValue ' ] = ObjectData_block . get_variable ( ' NameValue ' ) . data
object_properties [ ' Data ' ] = ObjectData_block . get_variable ( ' Data ' ) . data
object_properties [ ' Text ' ] = ObjectData_block . get_variable ( ' Text ' ) . data
object_properties [ ' TextColor ' ] = ObjectData_block . get_variable ( ' TextColor ' ) . data
object_properties [ ' MediaURL ' ] = ObjectData_block . get_variable ( ' MediaURL ' ) . data
object_properties [ ' PSBlock ' ] = ObjectData_block . get_variable ( ' PSBlock ' ) . data
object_properties [ ' ExtraParams ' ] = ObjectData_block . get_variable ( ' ExtraParams ' ) . data
object_properties [ ' Sound ' ] = ObjectData_block . get_variable ( ' Sound ' ) . data
object_properties [ ' OwnerID ' ] = ObjectData_block . get_variable ( ' OwnerID ' ) . data
object_properties [ ' Gain ' ] = ObjectData_block . get_variable ( ' Gain ' ) . data
object_properties [ ' Flags ' ] = ObjectData_block . get_variable ( ' Flags ' ) . data
object_properties [ ' Radius ' ] = ObjectData_block . get_variable ( ' Radius ' ) . data
object_properties [ ' JointType ' ] = ObjectData_block . get_variable ( ' JointType ' ) . data
object_properties [ ' JointPivot ' ] = ObjectData_block . get_variable ( ' JointPivot ' ) . data
object_properties [ ' JointAxisOrAnchor ' ] = ObjectData_block . get_variable ( ' JointAxisOrAnchor ' ) . data
# deal with the data stored in _ObjectData
# see http://wiki.secondlife.com/wiki/ObjectUpdate#ObjectData_Format for details
object_properties [ ' FootCollisionPlane ' ] = None
object_properties [ ' Position ' ] = None
object_properties [ ' Velocity ' ] = None
object_properties [ ' Acceleration ' ] = None
object_properties [ ' Rotation ' ] = None
object_properties [ ' AngularVelocity ' ] = None
if len ( object_properties [ ' ObjectData ' ] ) == 76 :
# Foot collision plane. LLVector4.
# Angular velocity is ignored and set to 0. Falls through to 60 bytes parser.
object_properties [ ' FootCollisionPlane ' ] = Quaternion ( object_properties [ ' ObjectData ' ] , 0 )
object_properties [ ' Position ' ] = Vector3 ( object_properties [ ' ObjectData ' ] , 16 )
object_properties [ ' Velocity ' ] = Vector3 ( object_properties [ ' ObjectData ' ] , 28 )
object_properties [ ' Acceleration ' ] = Vector3 ( object_properties [ ' ObjectData ' ] , 40 )
object_properties [ ' Rotation ' ] = Vector3 ( object_properties [ ' ObjectData ' ] , 52 )
object_properties [ ' AngularVelocity ' ] = Vector3 ( object_properties [ ' ObjectData ' ] , 60 )
elif len ( object_properties [ ' ObjectData ' ] ) == 60 :
# 32 bit precision update.
object_properties [ ' Position ' ] = Vector3 ( object_properties [ ' ObjectData ' ] , 0 )
object_properties [ ' Velocity ' ] = Vector3 ( object_properties [ ' ObjectData ' ] , 12 )
object_properties [ ' Acceleration ' ] = Vector3 ( object_properties [ ' ObjectData ' ] , 24 )
object_properties [ ' Rotation ' ] = Vector3 ( object_properties [ ' ObjectData ' ] , 36 )
object_properties [ ' AngularVelocity ' ] = Vector3 ( object_properties [ ' ObjectData ' ] , 48 )
elif len ( object_properties [ ' ObjectData ' ] ) == 48 :
# Foot collision plane. LLVector4
# Falls through to 32 bytes parser.
log ( WARNING , " 48 bit ObjectData precision not implemented " )
elif len ( object_properties [ ' ObjectData ' ] ) == 32 :
# 32 bit precision update.
# Position. U16Vec3.
# Velocity. U16Vec3.
# Acceleration. U16Vec3.
# Rotation. U16Rot(4xU16).
# Angular velocity. LLVector3.
log ( WARNING , " 32 bit ObjectData precision not implemented " )
elif len ( object_properties [ ' ObjectData ' ] ) == 16 :
# 8 bit precision update.
# Position. U8Vec3.
# Velocity. U8Vec3.
# Acceleration. U8Vec3.
# Rotation. U8Rot(4xU8).
# Angular velocity. U8Vec3
log ( WARNING , " 16 bit ObjectData precision not implemented " )
object_list . append ( object_properties )
self . update_multiple_objects_properties ( object_list )
def onObjectUpdateCached ( self , packet ) :
""" borrowing from libomv, we ' ll request object data for all data coming in via ObjectUpdateCached """
# ToDo: handle these 2 variables properly
2009-06-05 21:02:59 +00:00
_RegionHandle = packet . blocks [ ' RegionData ' ] [ 0 ] . get_variable ( ' RegionHandle ' ) . data
_TimeDilation = packet . blocks [ ' RegionData ' ] [ 0 ] . get_variable ( ' TimeDilation ' ) . data
2009-04-06 21:29:17 +00:00
_request_list = [ ]
2009-06-05 21:02:59 +00:00
for ObjectData_block in packet . blocks [ ' ObjectData ' ] :
2009-04-06 21:29:17 +00:00
LocalID = ObjectData_block . get_variable ( ' ID ' ) . data
_CRC = ObjectData_block . get_variable ( ' CRC ' ) . data
_UpdateFlags = ObjectData_block . get_variable ( ' UpdateFlags ' ) . data
# Objects.request_object_update() expects a tuple of (_ID, CacheMissType)
# see if we have the object stored already
2009-04-27 22:48:01 +00:00
_object = self . get_object_from_store ( LocalID = LocalID )
2009-04-06 21:29:17 +00:00
if _object == None or _object == [ ] :
CacheMissType = 1
else :
CacheMissType = 0
_request_list . append ( ( LocalID , CacheMissType ) )
# ask the simulator for updates
self . request_object_update ( ID_list = _request_list )
def onObjectUpdateCompressed ( self , packet ) :
object_list = [ ]
# ToDo: handle these 2 variables properly
2009-06-05 21:02:59 +00:00
_RegionHandle = packet . blocks [ ' RegionData ' ] [ 0 ] . get_variable ( ' RegionHandle ' ) . data
_TimeDilation = packet . blocks [ ' RegionData ' ] [ 0 ] . get_variable ( ' TimeDilation ' ) . data
2009-04-06 21:29:17 +00:00
2009-06-05 21:02:59 +00:00
for ObjectData_block in packet . blocks [ ' ObjectData ' ] :
2009-04-06 21:29:17 +00:00
object_properties = { }
object_properties [ ' UpdateFlags ' ] = ObjectData_block . get_variable ( ' UpdateFlags ' ) . data
object_properties [ ' Data ' ] = ObjectData_block . get_variable ( ' Data ' ) . data
_Data = object_properties [ ' Data ' ]
pos = 0 # position in the binary string
object_properties [ ' FullID ' ] = UUID ( bytes = _Data , offset = 0 ) # LLUUID
pos + = 16
object_properties [ ' LocalID ' ] = struct . unpack ( " <I " , _Data [ pos : pos + 4 ] ) [ 0 ]
pos + = 4
object_properties [ ' PCode ' ] = struct . unpack ( " >B " , _Data [ pos : pos + 1 ] ) [ 0 ]
pos + = 1
if object_properties [ ' PCode ' ] != 9 : # if it is not a prim, stop.
log ( WARNING , ' Fix Me!! Skipping parsing of ObjectUpdateCompressed packet when it is not a prim. ' )
# we ought to parse it and make sense of the data...
continue
object_properties [ ' State ' ] = struct . unpack ( " >B " , _Data [ pos : pos + 1 ] ) [ 0 ]
pos + = 1
object_properties [ ' CRC ' ] = struct . unpack ( " <I " , _Data [ pos : pos + 4 ] ) [ 0 ]
pos + = 4
object_properties [ ' Material ' ] = struct . unpack ( " >B " , _Data [ pos : pos + 1 ] ) [ 0 ]
pos + = 1
object_properties [ ' ClickAction ' ] = struct . unpack ( " >B " , _Data [ pos : pos + 1 ] ) [ 0 ]
pos + = 1
object_properties [ ' Scale ' ] = Vector3 ( _Data , pos )
pos + = 12
object_properties [ ' Position ' ] = Vector3 ( _Data , pos )
pos + = 12
object_properties [ ' Rotation ' ] = Vector3 ( _Data , pos )
pos + = 12
object_properties [ ' Flags ' ] = struct . unpack ( " >B " , _Data [ pos : pos + 1 ] ) [ 0 ]
pos + = 1
2009-04-27 22:48:01 +00:00
object_properties [ ' OwnerID ' ] = UUID ( bytes = _Data , offset = pos )
2009-04-06 21:29:17 +00:00
pos + = 16
# Placeholder vars, to be populated via flags if present
object_properties [ ' AngularVelocity ' ] = Vector3 ( )
object_properties [ ' ParentID ' ] = UUID ( )
object_properties [ ' Text ' ] = ' '
object_properties [ ' TextColor ' ] = None
object_properties [ ' MediaURL ' ] = ' '
object_properties [ ' Sound ' ] = UUID ( )
object_properties [ ' Gain ' ] = 0
object_properties [ ' Flags ' ] = 0
object_properties [ ' Radius ' ] = 0
object_properties [ ' NameValue ' ] = ' '
object_properties [ ' ExtraParams ' ] = None
if object_properties [ ' Flags ' ] != 0 :
log ( WARNING , " FixMe! Quiting parsing an ObjectUpdateCompressed packet with flags due to incomplete implemention. Storing a partial representation of an object with uuid of %s " % ( _FullID ) )
# the commented code is not working right, we need to figure out why!
# ExtraParams in particular seemed troublesome
'''
print ' Flags: ' , Flags
if ( Flags & CompressedUpdateFlags . contains_AngularVelocity ) != 0 :
_AngularVelocity = Vector3 ( _Data , pos )
pos + = 12
print ' AngularVelocity: ' , _AngularVelocity
else :
_AngularVelocity = None
if ( Flags & CompressedUpdateFlags . contains_Parent ) != 0 :
_ParentID = UUID ( _Data , pos )
pos + = 16
print ' ParentID: ' , _ParentID
else :
_ParentID = None
if ( Flags & CompressedUpdateFlags . Tree ) != 0 :
# skip it, only iterate the position
pos + = 1
print ' Tree '
if ( Flags & CompressedUpdateFlags . ScratchPad ) != 0 :
# skip it, only iterate the position
size = struct . unpack ( " >B " , _Data [ pos : pos + 1 ] ) [ 0 ]
pos + = 1
pos + = size
print ' Scratchpad size '
if ( Flags & CompressedUpdateFlags . contains_Text ) != 0 :
# skip it, only iterate the position
_Text = ' '
while struct . unpack ( " >B " , _Data [ pos : pos + 1 ] ) [ 0 ] != 0 :
pos + = 1
pos + = 1
_TextColor = struct . unpack ( " <I " , _Data [ pos : pos + 4 ] ) [ 0 ]
pos + = 4
print ' _TextColor: ' , _TextColor
if ( Flags & CompressedUpdateFlags . MediaURL ) != 0 :
# skip it, only iterate the position
_MediaURL = ' '
while struct . unpack ( " >B " , _Data [ pos : pos + 1 ] ) [ 0 ] != 0 :
pos + = 1
pos + = 1
print ' _MediaURL: ' , _MediaURL
if ( Flags & CompressedUpdateFlags . contains_Particles ) != 0 :
# skip it, only iterate the position
ParticleData = _Data [ pos : pos + 86 ]
pos + = 86
print ' Particles '
# parse ExtraParams
# ToDo: finish this up, for now we are just incrementing the position and not dealing with the data
_Flexible = None
_Light = None
_Sculpt = None
num_extra_params = struct . unpack ( " >b " , _Data [ pos : pos + 1 ] ) [ 0 ]
print ' Number of extra params: ' , num_extra_params
pos + = 1
for i in range ( num_extra_params ) :
# ExtraParam type
extraparam_type = struct . unpack ( " <H " , _Data [ pos : pos + 2 ] ) [ 0 ]
pos + = 2
datalength = struct . unpack ( " <I " , _Data [ pos : pos + 4 ] ) [ 0 ]
print ' ExtraParams type: %s length: %s ' % ( extraparam_type , datalength )
pos + = 4
pos + = int ( datalength )
# ToDo: Deal with extra parameters
#log(WARNING, "Incomplete implementation in onObjectUpdateCompressed when flags are present. Skipping parsing this object...")
#continue
if ( Flags & CompressedUpdateFlags . contains_Sound ) != 0 :
# skip it, only iterate the position
2009-04-27 22:48:01 +00:00
#_Sound = UUID(bytes = _Data[pos:pos+16])
2009-04-06 21:29:17 +00:00
pos + = 16
print ' Sound '
#_Gain = struct.unpack(">f", _Data[pos:pos+4])[0]
pos + = 4
#_Flags = stuct.unpack(">B", _Data[pos:pos+1])[0]
pos + = 1
#_Radius = struct.unpack(">f", _Data[pos:pos+4])[0]
pos + = 4
if ( Flags & CompressedUpdateFlags . contains_NameValues ) != 0 :
# skip it, only iterate the position
_NameValue = ' '
while _Data [ pos : pos + 1 ] != 0 :
#_NameValue += struct.unpack(">c", _Data[pos:pos+1])[0]
pos + = 1
pos + = 1
'''
object_properties [ ' PathCurve ' ] = None
object_properties [ ' PathBegin ' ] = None
object_properties [ ' PathEnd ' ] = None
object_properties [ ' PathScaleX ' ] = None
object_properties [ ' PathScaleY ' ] = None
object_properties [ ' PathShearX ' ] = None
object_properties [ ' PathShearY ' ] = None
object_properties [ ' PathTwist ' ] = None
object_properties [ ' PathTwistBegin ' ] = None
object_properties [ ' PathRadiusOffset ' ] = None
object_properties [ ' PathTaperX ' ] = None
object_properties [ ' PathTaperY ' ] = None
object_properties [ ' PathRevolutions ' ] = None
object_properties [ ' PathSkew ' ] = None
object_properties [ ' ProfileCurve ' ] = None
object_properties [ ' ProfileBegin ' ] = None
object_properties [ ' ProfileEnd ' ] = None
object_properties [ ' ProfileHollow ' ] = None
object_properties [ ' TextureEntry ' ] = None
object_properties [ ' TextureAnim ' ] = None
object_properties [ ' TextureAnim ' ] = None
else :
object_properties [ ' PathCurve ' ] = struct . unpack ( " >B " , _Data [ pos : pos + 1 ] ) [ 0 ]
pos + = 1
object_properties [ ' PathBegin ' ] = struct . unpack ( " <H " , _Data [ pos : pos + 2 ] ) [ 0 ]
pos + = 2
object_properties [ ' PathEnd ' ] = struct . unpack ( " <H " , _Data [ pos : pos + 2 ] ) [ 0 ]
pos + = 2
object_properties [ ' PathScaleX ' ] = struct . unpack ( " >B " , _Data [ pos : pos + 1 ] ) [ 0 ]
pos + = 1
object_properties [ ' PathScaleY ' ] = struct . unpack ( " >B " , _Data [ pos : pos + 1 ] ) [ 0 ]
pos + = 1
object_properties [ ' PathShearX ' ] = struct . unpack ( " >B " , _Data [ pos : pos + 1 ] ) [ 0 ]
pos + = 1
object_properties [ ' PathShearY ' ] = struct . unpack ( " >B " , _Data [ pos : pos + 1 ] ) [ 0 ]
pos + = 1
object_properties [ ' PathTwist ' ] = struct . unpack ( " >B " , _Data [ pos : pos + 1 ] ) [ 0 ]
pos + = 1
object_properties [ ' PathTwistBegin ' ] = struct . unpack ( " >B " , _Data [ pos : pos + 1 ] ) [ 0 ]
pos + = 1
object_properties [ ' PathRadiusOffset ' ] = struct . unpack ( " >B " , _Data [ pos : pos + 1 ] ) [ 0 ]
pos + = 1
object_properties [ ' PathTaperX ' ] = struct . unpack ( " >B " , _Data [ pos : pos + 1 ] ) [ 0 ]
pos + = 1
object_properties [ ' PathTaperY ' ] = struct . unpack ( " >B " , _Data [ pos : pos + 1 ] ) [ 0 ]
pos + = 1
object_properties [ ' PathRevolutions ' ] = struct . unpack ( " >B " , _Data [ pos : pos + 1 ] ) [ 0 ]
pos + = 1
object_properties [ ' PathSkew ' ] = struct . unpack ( " >B " , _Data [ pos : pos + 1 ] ) [ 0 ]
pos + = 1
object_properties [ ' ProfileCurve ' ] = struct . unpack ( " >B " , _Data [ pos : pos + 1 ] ) [ 0 ]
pos + = 1
object_properties [ ' ProfileBegin ' ] = struct . unpack ( " >B " , _Data [ pos : pos + 1 ] ) [ 0 ]
pos + = 1
object_properties [ ' ProfileEnd ' ] = struct . unpack ( " >B " , _Data [ pos : pos + 1 ] ) [ 0 ]
pos + = 1
object_properties [ ' ProfileHollow ' ] = struct . unpack ( " >B " , _Data [ pos : pos + 1 ] ) [ 0 ]
pos + = 1
# Texture handling
size = struct . unpack ( " <H " , _Data [ pos : pos + 2 ] ) [ 0 ]
pos + = 2
object_properties [ ' TextureEntry ' ] = _Data [ pos : pos + size ]
pos + = size
if ( object_properties [ ' Flags ' ] & CompressedUpdateFlags . TextureAnim ) != 0 :
object_properties [ ' TextureAnim ' ] = struct . unpack ( " <H " , _Data [ pos : pos + 2 ] ) [ 0 ]
pos + = 2
else :
object_properties [ ' TextureAnim ' ] = None
object_list . append ( object_properties )
self . update_multiple_objects_properties ( object_list )
def onKillObject ( self , packet ) :
2009-06-05 21:02:59 +00:00
_KillID = packet . blocks [ ' ObjectData ' ] [ 0 ] . get_variable ( ' ID ' ) . data
2009-04-06 21:29:17 +00:00
self . remove_object_from_store ( _KillID )
def onObjectProperties ( self , packet ) :
object_list = [ ]
2009-06-05 21:02:59 +00:00
for ObjectData_block in packet . blocks [ ' ObjectData ' ] :
2009-04-06 21:29:17 +00:00
object_properties = { }
object_properties [ ' FullID ' ] = ObjectData_block . get_variable ( ' ObjectID ' ) . data
object_properties [ ' CreatorID ' ] = ObjectData_block . get_variable ( ' CreatorID ' ) . data
object_properties [ ' OwnerID ' ] = ObjectData_block . get_variable ( ' OwnerID ' ) . data
object_properties [ ' GroupID ' ] = ObjectData_block . get_variable ( ' GroupID ' ) . data
object_properties [ ' CreationDate ' ] = ObjectData_block . get_variable ( ' CreationDate ' ) . data
object_properties [ ' BaseMask ' ] = ObjectData_block . get_variable ( ' BaseMask ' ) . data
object_properties [ ' OwnerMask ' ] = ObjectData_block . get_variable ( ' OwnerMask ' ) . data
object_properties [ ' GroupMask ' ] = ObjectData_block . get_variable ( ' GroupMask ' ) . data
object_properties [ ' EveryoneMask ' ] = ObjectData_block . get_variable ( ' EveryoneMask ' ) . data
object_properties [ ' NextOwnerMask ' ] = ObjectData_block . get_variable ( ' NextOwnerMask ' ) . data
object_properties [ ' OwnershipCost ' ] = ObjectData_block . get_variable ( ' OwnershipCost ' ) . data
#object_properties['TaxRate'] = ObjectData_block.get_variable('TaxRate').data
object_properties [ ' SaleType ' ] = ObjectData_block . get_variable ( ' SaleType ' ) . data
object_properties [ ' SalePrice ' ] = ObjectData_block . get_variable ( ' SalePrice ' ) . data
object_properties [ ' AggregatePerms ' ] = ObjectData_block . get_variable ( ' AggregatePerms ' ) . data
object_properties [ ' AggregatePermTextures ' ] = ObjectData_block . get_variable ( ' AggregatePermTextures ' ) . data
object_properties [ ' AggregatePermTexturesOwner ' ] = ObjectData_block . get_variable ( ' AggregatePermTexturesOwner ' ) . data
object_properties [ ' Category ' ] = ObjectData_block . get_variable ( ' Category ' ) . data
object_properties [ ' InventorySerial ' ] = ObjectData_block . get_variable ( ' InventorySerial ' ) . data
object_properties [ ' ItemID ' ] = ObjectData_block . get_variable ( ' ItemID ' ) . data
object_properties [ ' FolderID ' ] = ObjectData_block . get_variable ( ' FolderID ' ) . data
object_properties [ ' FromTaskID ' ] = ObjectData_block . get_variable ( ' FromTaskID ' ) . data
object_properties [ ' LastOwnerID ' ] = ObjectData_block . get_variable ( ' LastOwnerID ' ) . data
object_properties [ ' Name ' ] = ObjectData_block . get_variable ( ' Name ' ) . data
object_properties [ ' Description ' ] = ObjectData_block . get_variable ( ' Description ' ) . data
object_properties [ ' TouchName ' ] = ObjectData_block . get_variable ( ' TouchName ' ) . data
object_properties [ ' SitName ' ] = ObjectData_block . get_variable ( ' SitName ' ) . data
object_properties [ ' TextureID ' ] = ObjectData_block . get_variable ( ' TextureID ' ) . data
object_list . append ( object_properties )
self . update_multiple_objects_properties ( object_list )
2009-03-04 07:27:56 +00:00
class Object ( object ) :
2009-03-14 00:09:15 +00:00
""" represents an Object
2009-03-12 20:48:26 +00:00
2009-03-14 00:09:15 +00:00
Initialize the Object class instance
>> > object = Object ( )
2009-03-05 21:50:23 +00:00
2009-03-14 00:09:15 +00:00
Sample implementations : objects . py
Tests : tests / test_objects . py
"""
2009-03-22 05:37:11 +00:00
def __init__ ( self , LocalID = None , State = None , FullID = None , CRC = None , PCode = None , Material = None , ClickAction = None , Scale = None , ObjectData = None , ParentID = None , UpdateFlags = None , PathCurve = None , ProfileCurve = None , PathBegin = None , PathEnd = None , PathScaleX = None , PathScaleY = None , PathShearX = None , PathShearY = None , PathTwist = None , PathTwistBegin = None , PathRadiusOffset = None , PathTaperX = None , PathTaperY = None , PathRevolutions = None , PathSkew = None , ProfileBegin = None , ProfileEnd = None , ProfileHollow = None , TextureEntry = None , TextureAnim = None , NameValue = None , Data = None , Text = None , TextColor = None , MediaURL = None , PSBlock = None , ExtraParams = None , Sound = None , OwnerID = None , Gain = None , Flags = None , Radius = None , JointType = None , JointPivot = None , JointAxisOrAnchor = None , FootCollisionPlane = None , Position = None , Velocity = None , Acceleration = None , Rotation = None , AngularVelocity = None ) :
2009-03-20 06:15:22 +00:00
""" set up the object attributes """
2009-03-14 00:09:15 +00:00
2009-03-22 05:37:11 +00:00
self . LocalID = LocalID # U32
2009-03-14 00:09:15 +00:00
self . State = State # U8
2009-03-22 05:37:11 +00:00
self . FullID = FullID # LLUUID
2009-03-14 00:09:15 +00:00
self . CRC = CRC # U32 // TEMPORARY HACK FOR JAMES
self . PCode = PCode # U8
self . Material = Material # U8
self . ClickAction = ClickAction # U8
self . Scale = Scale # LLVector3
self . ObjectData = ObjectData # Variable 1
self . ParentID = ParentID # U32
self . UpdateFlags = UpdateFlags # U32 // U32, see object_flags.h
self . PathCurve = PathCurve # U8
self . ProfileCurve = ProfileCurve # U8
self . PathBegin = PathBegin # U16 // 0 to 1, quanta = 0.01
self . PathEnd = PathEnd # U16 // 0 to 1, quanta = 0.01
self . PathScaleX = PathScaleX # U8 // 0 to 1, quanta = 0.01
self . PathScaleY = PathScaleY # U8 // 0 to 1, quanta = 0.01
self . PathShearX = PathShearX # U8 // -.5 to .5, quanta = 0.01
self . PathShearY = PathShearY # U8 // -.5 to .5, quanta = 0.01
self . PathTwist = PathTwist # S8 // -1 to 1, quanta = 0.01
self . PathTwistBegin = PathTwistBegin # S8 // -1 to 1, quanta = 0.01
self . PathRadiusOffset = PathRadiusOffset # S8 // -1 to 1, quanta = 0.01
self . PathTaperX = PathTaperX # S8 // -1 to 1, quanta = 0.01
self . PathTaperY = PathTaperY # S8 // -1 to 1, quanta = 0.01
self . PathRevolutions = PathRevolutions # U8 // 0 to 3, quanta = 0.015
self . PathSkew = PathSkew # S8 // -1 to 1, quanta = 0.01
self . ProfileBegin = ProfileBegin # U16 // 0 to 1, quanta = 0.01
self . ProfileEnd = ProfileEnd # U16 // 0 to 1, quanta = 0.01
self . ProfileHollow = ProfileHollow # U16 // 0 to 1, quanta = 0.01
self . TextureEntry = TextureEntry # Variable 2
self . TextureAnim = TextureAnim # Variable 1
self . NameValue = NameValue # Variable 2
self . Data = Data # Variable 2
self . Text = Text # Variable 1 // llSetText() hovering text
self . TextColor = TextColor # Fixed 4 // actually, a LLColor4U
self . MediaURL = MediaURL # Variable 1 // URL for web page, movie, etc.
self . PSBlock = PSBlock # Variable 1
self . ExtraParams = ExtraParams # Variable 1
2009-03-22 05:37:11 +00:00
self . Sound = Sound # LLUUID
self . OwnerID = OwnerID # LLUUID // HACK object's owner id, only set if non-null sound, for muting
2009-03-14 00:09:15 +00:00
self . Gain = Gain # F32
self . Flags = Flags # U8
self . Radius = Radius # F32 // cutoff radius
self . JointType = JointType # U8
self . JointPivot = JointPivot # LLVector3
self . JointAxisOrAnchor = JointAxisOrAnchor # LLVector3
2009-03-24 23:01:16 +00:00
# from ObjectUpdateCompressed
2009-03-18 21:32:21 +00:00
self . FootCollisionPlane = FootCollisionPlane
self . Position = Position
self . Velocity = Velocity
self . Acceleration = Acceleration
self . Rotation = Rotation
self . AngularVelocity = AngularVelocity
2009-03-24 23:01:16 +00:00
# from ObjectProperties
self . CreatorID = None
self . GroupID = None
self . CreationDate = None
self . BaseMask = None
self . OwnerMask = None
self . GroupMask = None
self . EveryoneMask = None
self . NextOwnerMask = None
self . OwnershipCost = None
# TaxRate
self . SaleType = None
self . SalePrice = None
self . AggregatePerms = None
self . AggregatePermTextures = None
self . AggregatePermTexturesOwner = None
self . Category = None
self . InventorySerial = None
self . ItemID = None
self . FolderID = None
self . FromTaskID = None
self . LastOwnerID = None
self . Name = None
self . Description = None
self . TouchName = None
self . SitName = None
self . TextureID = None
2009-03-14 00:09:15 +00:00
def update_object_permissions ( self , agent , Field , Set , Mask , Override = False ) :
""" update permissions for a list of objects
This will update a specific bit to a specific value .
"""
packet = ObjectPermissionsPacket ( )
# build the AgentData block
2009-04-27 22:48:01 +00:00
packet . AgentData [ ' AgentID ' ] = agent . agent_id
packet . AgentData [ ' SessionID ' ] = agent . session_id
2009-03-14 00:09:15 +00:00
packet . HeaderData [ ' Override ' ] = Override # BOOL, God-bit.
ObjectData = { }
2009-03-22 05:37:11 +00:00
ObjectData [ ' ObjectLocalID ' ] = self . LocalID
2009-03-14 00:09:15 +00:00
ObjectData [ ' Field ' ] = Field # U32
ObjectData [ ' Set ' ] = Set # U8
ObjectData [ ' Mask ' ] = Mask # S32
packet . ObjectDataBlocks . append ( ObjectData )
2009-03-17 04:24:08 +00:00
agent . region . enqueue_message ( packet ( ) )
2009-03-14 00:09:15 +00:00
2009-03-26 02:02:29 +00:00
def set_object_full_permissions ( self , agent ) :
"""
Set Next Owner Permissions Copy , Modify , Transfer
This is also called ' full permissions ' .
"""
self . update_object_permissions ( agent , PermissionsTarget . NextOwner , 1 , PermissionsMask . Copy )
self . update_object_permissions ( agent , PermissionsTarget . NextOwner , 1 , PermissionsMask . Modify )
self . update_object_permissions ( agent , PermissionsTarget . NextOwner , 1 , PermissionsMask . Transfer )
def set_object_copy_mod_permissions ( self , agent ) :
"""
Set Next Owner Permissions to Copy / Mod
This is a common permission set for attachements .
"""
self . update_object_permissions ( agent , PermissionsTarget . NextOwner , 1 , PermissionsMask . Copy )
self . update_object_permissions ( agent , PermissionsTarget . NextOwner , 1 , PermissionsMask . Modify )
self . update_object_permissions ( agent , PermissionsTarget . NextOwner , 0 , PermissionsMask . Transfer )
def set_object_mod_transfer_permissions ( self , agent ) :
"""
Set Next Owner Permissions to Mod / Transfer
This is a common permission set for clothing .
"""
self . update_object_permissions ( agent , PermissionsTarget . NextOwner , 0 , PermissionsMask . Copy )
self . update_object_permissions ( agent , PermissionsTarget . NextOwner , 1 , PermissionsMask . Modify )
self . update_object_permissions ( agent , PermissionsTarget . NextOwner , 1 , PermissionsMask . Transfer )
def set_object_transfer_only_permissions ( self , agent ) :
"""
Set Next Owner Permissions to Transfer Only
This is the most restrictive set of permissions allowed .
"""
self . update_object_permissions ( agent , PermissionsTarget . NextOwner , 0 , PermissionsMask . Copy )
self . update_object_permissions ( agent , PermissionsTarget . NextOwner , 0 , PermissionsMask . Modify )
self . update_object_permissions ( agent , PermissionsTarget . NextOwner , 1 , PermissionsMask . Transfer )
def set_object_copy_transfer_permissions ( self , agent ) :
"""
Set Next Owner Permissions to Copy / Transfer
"""
self . update_object_permissions ( agent , PermissionsTarget . NextOwner , 1 , PermissionsMask . Copy )
self . update_object_permissions ( agent , PermissionsTarget . NextOwner , 0 , PermissionsMask . Modify )
self . update_object_permissions ( agent , PermissionsTarget . NextOwner , 1 , PermissionsMask . Transfer )
def set_object_copy_only_permissions ( self , agent ) :
"""
Set Next Owner Permissions to Copy Only
"""
self . update_object_permissions ( agent , PermissionsTarget . NextOwner , 1 , PermissionsMask . Copy )
self . update_object_permissions ( agent , PermissionsTarget . NextOwner , 0 , PermissionsMask . Modify )
self . update_object_permissions ( agent , PermissionsTarget . NextOwner , 0 , PermissionsMask . Transfer )
2009-03-14 00:09:15 +00:00
def set_object_name ( self , agent , Name ) :
2009-03-17 04:24:08 +00:00
""" update the name of an object
2009-03-14 00:09:15 +00:00
"""
2009-03-05 21:50:23 +00:00
2009-03-24 23:21:47 +00:00
packet = ObjectNamePacket ( )
2009-03-05 21:50:23 +00:00
2009-03-14 00:09:15 +00:00
# build the AgentData block
2009-04-27 22:48:01 +00:00
packet . AgentData [ ' AgentID ' ] = agent . agent_id
packet . AgentData [ ' SessionID ' ] = agent . session_id
2009-03-05 21:50:23 +00:00
2009-03-14 00:09:15 +00:00
ObjectData = { }
2009-03-22 05:37:11 +00:00
ObjectData [ ' LocalID ' ] = self . LocalID
2009-03-14 00:09:15 +00:00
ObjectData [ ' Name ' ] = Name
2009-03-05 21:50:23 +00:00
2009-03-14 00:09:15 +00:00
packet . ObjectDataBlocks . append ( ObjectData )
2009-03-05 21:50:23 +00:00
2009-03-17 04:24:08 +00:00
agent . region . enqueue_message ( packet ( ) )
2009-03-14 00:09:15 +00:00
def set_object_description ( self , agent , Description ) :
2009-03-17 04:24:08 +00:00
""" update the description of an objects
2009-03-05 21:50:23 +00:00
2009-03-14 00:09:15 +00:00
"""
2009-03-05 21:50:23 +00:00
2009-03-24 23:21:47 +00:00
packet = ObjectDescriptionPacket ( )
2009-03-14 00:09:15 +00:00
# build the AgentData block
2009-04-27 22:48:01 +00:00
packet . AgentData [ ' AgentID ' ] = agent . agent_id
packet . AgentData [ ' SessionID ' ] = agent . session_id
2009-03-05 21:50:23 +00:00
2009-03-14 00:09:15 +00:00
ObjectData = { }
2009-03-22 05:37:11 +00:00
ObjectData [ ' LocalID ' ] = self . LocalID
2009-03-14 00:09:15 +00:00
ObjectData [ ' Description ' ] = Description
2009-03-05 21:50:23 +00:00
2009-03-14 00:09:15 +00:00
packet . ObjectDataBlocks . append ( ObjectData )
2009-03-17 04:24:08 +00:00
agent . region . enqueue_message ( packet ( ) )
2009-04-03 22:00:50 +00:00
def derez ( self , agent , destination , destinationID , transactionID , GroupID ) :
""" derez an object, specifying the destination """
packet = DeRezObjectPacket ( )
# build the AgentData block
2009-04-27 22:48:01 +00:00
packet . AgentData [ ' AgentID ' ] = agent . agent_id
packet . AgentData [ ' SessionID ' ] = agent . session_id
2009-04-03 22:00:50 +00:00
2009-04-27 22:48:01 +00:00
packet . AgentBlock [ ' GroupID ' ] = GroupID
2009-04-03 22:00:50 +00:00
packet . AgentBlock [ ' Destination ' ] = destination
2009-04-27 22:48:01 +00:00
packet . AgentBlock [ ' DestinationID ' ] = destinationID
packet . AgentBlock [ ' TransactionID ' ] = transactionID
2009-04-03 22:00:50 +00:00
# fix me: faking these values
packet . AgentBlock [ ' PacketCount ' ] = 1
packet . AgentBlock [ ' PacketNumber ' ] = 0
ObjectData = { }
ObjectData [ ' ObjectLocalID ' ] = self . LocalID
packet . ObjectDataBlocks . append ( ObjectData )
agent . region . enqueue_message ( packet ( ) )
def take ( self , agent ) :
""" take object into inventory """
parent_folder = self . FolderID
# Check if we have inventory turned on
if not ( parent_folder and agent . settings . ENABLE_INVENTORY_MANAGEMENT ) :
log ( WARNING , " Inventory not available, please enable settings.ENABLE_INVENTORY_MANAGEMENT " )
return
if not ( parent_folder ) :
# locate Object folder
objects_folder = [ folder for folder in agent . inventory . folders if folder . Name == ' Objects ' ]
if objects_folder :
parent_folder = objects_folder [ 0 ] . FolderID
else :
log ( ERROR , " Unable to locate top-level Objects folder to take item into inventory. " )
return
self . derez ( agent , 4 , parent_folder , uuid . uuid4 ( ) , agent . ActiveGroupID )
2009-03-17 04:24:08 +00:00
def select ( self , agent ) :
""" select an object
2009-03-18 21:32:21 +00:00
2009-03-17 04:24:08 +00:00
"""
packet = ObjectSelectPacket ( )
# build the AgentData block
2009-04-27 22:48:01 +00:00
packet . AgentData [ ' AgentID ' ] = agent . agent_id
packet . AgentData [ ' SessionID ' ] = agent . session_id
2009-03-17 04:24:08 +00:00
ObjectData = { }
2009-03-22 05:37:11 +00:00
ObjectData [ ' ObjectLocalID ' ] = self . LocalID
2009-03-17 04:24:08 +00:00
packet . ObjectDataBlocks . append ( ObjectData )
agent . region . enqueue_message ( packet ( ) )
def deselect ( self , agent ) :
""" deselect an object
"""
packet = ObjectDeselectPacket ( )
# build the AgentData block
2009-04-27 22:48:01 +00:00
packet . AgentData [ ' AgentID ' ] = agent . agent_id
packet . AgentData [ ' SessionID ' ] = agent . session_id
2009-03-17 04:24:08 +00:00
ObjectData = { }
2009-03-22 05:37:11 +00:00
ObjectData [ ' ObjectLocalID ' ] = self . LocalID
2009-03-17 04:24:08 +00:00
packet . ObjectDataBlocks . append ( ObjectData )
agent . region . enqueue_message ( packet ( ) )
2009-04-30 06:52:08 +00:00
def _update_properties ( self , properties ) :
2009-03-20 06:15:22 +00:00
""" takes a dictionary of attribute:value and makes it so """
for attribute in properties :
2009-03-22 05:37:11 +00:00
setattr ( self , attribute , properties [ attribute ] )
2009-03-20 06:15:22 +00:00
2009-04-27 22:48:01 +00:00
"""
Contributors can be viewed at :
http : / / svn . secondlife . com / svn / linden / projects / 2008 / pyogp / CONTRIBUTORS . txt
$ LicenseInfo : firstyear = 2008 & license = apachev2 $
Copyright 2009 , Linden Research , Inc .
Licensed under the Apache License , Version 2.0 ( the " License " ) .
You may obtain a copy of the License at :
http : / / www . apache . org / licenses / LICENSE - 2.0
or in
http : / / svn . secondlife . com / svn / linden / projects / 2008 / pyogp / LICENSE . txt
$ / LicenseInfo $
"""