From bbe9777df6b5f7b36100804f233671c6bd940d63 Mon Sep 17 00:00:00 2001 From: "enus.linden" Date: Tue, 24 Mar 2009 23:01:16 +0000 Subject: [PATCH] updating some objects methods, adding more attributes to Object(), and a new script --- .../examples/sample_object_create_edit.py | 167 ++++++++++++++++++ pyogp/lib/base/objects.py | 67 +++++-- pyogp/lib/base/utilities/helpers.py | 35 +++- setup.py | 1 + 4 files changed, 255 insertions(+), 15 deletions(-) create mode 100644 pyogp/lib/base/examples/sample_object_create_edit.py diff --git a/pyogp/lib/base/examples/sample_object_create_edit.py b/pyogp/lib/base/examples/sample_object_create_edit.py new file mode 100644 index 0000000..07da5aa --- /dev/null +++ b/pyogp/lib/base/examples/sample_object_create_edit.py @@ -0,0 +1,167 @@ +#!/usr/bin/python +""" +@file sample_object_create_edit.py +@date 2009-03-05 +Contributors can be viewed at: +http://svn.secondlife.com/svn/linden/projects/2008/pyogp/CONTRIBUTORS.txt + +$LicenseInfo:firstyear=2008&license=apachev2$ + +Copyright 2008, 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$ +""" + +# standard +import re +import getpass, sys, logging +from optparse import OptionParser +import time + +# related +from eventlet import api + +# pyogp +from pyogp.lib.base.agent import Agent +from pyogp.lib.base.settings import Settings + +# pyogp utilites +from pyogp.lib.base.utilities.helpers import Wait + + +def login(): + """ login an to a login endpoint """ + + parser = OptionParser() + + logger = logging.getLogger("pyogp.lib.base.example") + + parser.add_option("-l", "--loginuri", dest="loginuri", default="https://login.aditi.lindenlab.com/cgi-bin/login.cgi", + help="specified the target loginuri") + parser.add_option("-r", "--region", dest="region", default=None, + help="specifies the region (regionname/x/y/z) to connect to") + parser.add_option("-q", "--quiet", dest="verbose", default=True, action="store_false", + help="enable verbose mode") + + + (options, args) = parser.parse_args() + + if options.verbose: + console = logging.StreamHandler() + console.setLevel(logging.DEBUG) # seems to be a no op, set it for the logger + formatter = logging.Formatter('%(asctime)-30s%(name)-30s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + # setting the level for the handler above seems to be a no-op + # it needs to be set for the logger, here the root logger + # otherwise it is NOTSET(=0) which means to log nothing. + logging.getLogger('').setLevel(logging.DEBUG) + else: + print "Attention: This script will print nothing if you use -q. So it might be boring to use it like that ;-)" + + # example from a pure agent perspective + + #grab a password! + password = getpass.getpass() + + # let's disable inventory handling for this example + settings = Settings() + settings.ENABLE_INVENTORY_MANAGEMENT = False + settings.ENABLE_EQ_LOGGING = False + settings.ENABLE_CAPS_LOGGING = False + + #First, initialize the agent + client = Agent(settings = settings) + + # Now let's log it in + api.spawn(client.login, options.loginuri, args[0], args[1], password, start_location = options.region, connect_region = True) + + # wait for the agent to connect to it's region + while client.connected == False: + api.sleep(0) + + while client.region.connected == False: + api.sleep(0) + + # do sample script specific stuff here + # in this case we create a box + + waiter = Wait(5) + + client.region.objects.create_default_box(GroupID = client.ActiveGroupID) + + waiter = Wait(5) + + # let's see what's nearby + objects_nearby = client.region.objects.find_objects_within_radius(20) + + for item in objects_nearby: + item.select(client) + + waiter = Wait(15) + + my_objects = client.region.objects.my_objects() + + print 'Hey! Will try to set object names' + + for item in my_objects: + print ' for LocalID %s' % item.LocalID + item.set_object_name(client, 'Pyogp is teh K00l') + + # print matches + + while client.running: + api.sleep(0) + + print '' + print '' + print 'At this point, we have an Agent object, Inventory dirs, and with a Region attribute' + print 'Agent attributes:' + for attr in client.__dict__: + print attr, ':\t\t\t', client.__dict__[attr] + print '' + print '' + print 'Objects being tracked: %s' % len(client.region.objects.object_store) + print '' + print '' + states = {} + for _object in client.region.objects.object_store: + if _object.State == 0: + #items = _object.__dict__.items() + #items.sort() + print 'Object attributes' + for attr in _object.__dict__: + print '\t\t%s:\t\t%s' % (attr, _object.__dict__[attr]) + print '' + else: + if states.has_key(_object.State): + states[_object.State]+=1 + else: + states[_object.State] = 1 + print '' + print 'Object states I don\'t care about atm' + for state in states: + print '\t State: ', state, '\tFrequency: ', states[state] + print '' + print '' + for _avatar in client.region.objects.avatar_store: + print 'LocalID:', _avatar.LocalID, '\tUUID: ', _avatar.FullID , '\tNameValue: ', _avatar.NameValue, '\tPosition: ', _avatar.Position + print '' + print '' + print 'Region attributes:' + for attr in client.region.__dict__: + print attr, ':\t\t\t', client.region.__dict__[attr] + +def main(): + return login() + +if __name__=="__main__": + main() diff --git a/pyogp/lib/base/objects.py b/pyogp/lib/base/objects.py index 8595d43..f31b726 100644 --- a/pyogp/lib/base/objects.py +++ b/pyogp/lib/base/objects.py @@ -134,13 +134,13 @@ class Objects(object): self.object_store[index[0]] = _object - if self.settings.LOG_VERBOSE: log(DEBUG, 'Updating a stored object: %s in region \'%s\'' % (_object.FullID, self.region.SimName)) + #if self.settings.LOG_VERBOSE: log(DEBUG, 'Updating a stored object: %s in region \'%s\'' % (_object.FullID, self.region.SimName)) else: self.object_store.append(_object) - if self.settings.LOG_VERBOSE: log(DEBUG, 'Stored a new object: %s in region \'%s\'' % (_object.LocalID, self.region.SimName)) + #if self.settings.LOG_VERBOSE: log(DEBUG, 'Stored a new object: %s in region \'%s\'' % (_object.LocalID, self.region.SimName)) def store_avatar(self, _objectdata): @@ -159,13 +159,13 @@ class Objects(object): self.avatar_store[index[0]] = _objectdata - if self.settings.LOG_VERBOSE: log(DEBUG, 'Replacing a stored avatar: %s in region \'%s\'' % (_objectdata.LocalID, self.region.SimName)) + #if self.settings.LOG_VERBOSE: log(DEBUG, 'Replacing a stored avatar: %s in region \'%s\'' % (_objectdata.LocalID, self.region.SimName)) else: self.avatar_store.append(_objectdata) - if self.settings.LOG_VERBOSE: log(DEBUG, 'Stored a new avatar: %s in region \'%s\'' % (_objectdata.LocalID, self.region.SimName)) + #if self.settings.LOG_VERBOSE: log(DEBUG, 'Stored a new avatar: %s in region \'%s\'' % (_objectdata.LocalID, self.region.SimName)) def get_object_from_store(self, LocalID = None, FullID = None): """ searches the store and returns object if stored, None otherwise """ @@ -187,12 +187,18 @@ class Objects(object): if LocalID != None: _avatar = [_avatar for _avatar in self.avatar_store if _avatar.LocalID == LocalID] - return _avatar elif FullID != None: _avatar = [_avatar for _avatar in self.avatar_store if _avatar.FullID == FullID] - return _avatar - else: + + if _avatar == []: return None + else: + return _avatar[0] + + def my_objects(self): + """ returns a list of known objects where the calling client is the owner """ + + return [_object for _object in self.object_store if str(_object.OwnerID) == str(self.agent.agent_id)] def find_objects_by_name(self, Name): """ searches the store for known objects by name @@ -225,13 +231,17 @@ class Objects(object): def remove_object_from_store(self, ID = None): + victim = self.get_object_from_store(LocalID = ID) + if victim == None: + victim = self.get_avatar_from_store(LocalID = ID) + # this is an avatar - if _object.PCode == 47: + if _victim.PCode == 47: self.kill_stored_avatar(ID) # this is a Primitive - elif _object.PCode == 9: + elif _victim.PCode == 9: self.kill_stored_object(ID) @@ -258,7 +268,7 @@ class Objects(object): def update_multiple_objects_properties(self, object_list): """ update the attributes of objects """ - if self.settings.LOG_VERBOSE and self.settings.ENABLE_OBJECT_LOGGING: log(DEBUG, "Processing multiple object properties updates: %s" % (len(object_list))) + #if self.settings.LOG_VERBOSE and self.settings.ENABLE_OBJECT_LOGGING: log(DEBUG, "Processing multiple object properties updates: %s" % (len(object_list))) for object_properties in object_list: @@ -272,7 +282,7 @@ class Objects(object): If not, we create a new object """ - if self.settings.LOG_VERBOSE and self.settings.ENABLE_OBJECT_LOGGING: log(DEBUG, "Processing object properties update for FullID: %s" % (object_properties['FullID'])) + #if self.settings.LOG_VERBOSE and self.settings.ENABLE_OBJECT_LOGGING: log(DEBUG, "Processing object properties update for FullID: %s" % (object_properties['FullID'])) if object_properties.has_key('PCode'): # this is an avatar @@ -341,9 +351,9 @@ class Objects(object): """ 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) - location_to_rez_x = self.agent.Position[0] + relative_position[0] - location_to_rez_y = self.agent.Position[1] + relative_position[1] - location_to_rez_z = self.agent.Position[2] + relative_position[2] + 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] location_to_rez = (location_to_rez_x, location_to_rez_y, location_to_rez_z) @@ -465,6 +475,7 @@ class Object(object): self.JointPivot = JointPivot # LLVector3 self.JointAxisOrAnchor = JointAxisOrAnchor # LLVector3 + # from ObjectUpdateCompressed self.FootCollisionPlane = FootCollisionPlane self.Position = Position self.Velocity = Velocity @@ -472,6 +483,34 @@ class Object(object): self.Rotation = Rotation self.AngularVelocity = AngularVelocity + # 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 + def update_object_permissions(self, agent, Field, Set, Mask, Override = False): """ update permissions for a list of objects diff --git a/pyogp/lib/base/utilities/helpers.py b/pyogp/lib/base/utilities/helpers.py index 2328b27..8eca093 100644 --- a/pyogp/lib/base/utilities/helpers.py +++ b/pyogp/lib/base/utilities/helpers.py @@ -20,9 +20,11 @@ $/LicenseInfo$ # standard python libs from logging import getLogger, CRITICAL, ERROR, WARNING, INFO, DEBUG +import time # related from indra.base import llsd +from eventlet import api # pyogp from pyogp.lib.base.exc import DataParsingError, DeserializationFailed @@ -91,7 +93,6 @@ class Helpers(object): pass - class ListLLSDSerializer(object): """adapter for serializing a list to LLSD @@ -206,3 +207,35 @@ class LLSDDeserializer(object): data = fp.read() return self.deserialize_string(data) +class Wait(object): + """ a simple timer that blocks a calling routine for the specified number of seconds + + done since we were writing timing loops in test scripts repeatedly + returns True when it's done + """ + + def __init__(self, duration): + + self.duration = int(duration) + + # let's be nice and enabled a kill switch + self.enabled = False + + self.run() + + def run(self): + + now = time.time() + start = now + self.enabled = True + + while self.enabled and now - start < self.duration: + + api.sleep() + now = time.time() + + return True + + def stop(self): + + self.enabled = False diff --git a/setup.py b/setup.py index 60db72e..8abac57 100644 --- a/setup.py +++ b/setup.py @@ -60,6 +60,7 @@ setup(name='pyogp.lib.base', 'inventory_handling = pyogp.lib.base.examples.sample_inventory_handling:main', 'object_tracking = pyogp.lib.base.examples.sample_object_tracking:main', 'object_creation = pyogp.lib.base.examples.sample_object_creation:main', + 'object_create_edit = pyogp.lib.base.examples.sample_object_create_edit:main', 'object_properties = pyogp.lib.base.examples.sample_object_properties:main', 'chat_and_instant_messaging = pyogp.lib.base.examples.sample_chat_and_instant_messaging:main', 'group_creation = pyogp.lib.base.examples.sample_group_creation:main'