root/projects/2008/pyogp/pyogp.lib.base/trunk/pyogp/lib/base/datatypes.py

Revision 2493, 5.9 kB (checked in by joshua.linden, 5 months ago)

* Use the PCode enum instead of magic numbers
* Watch out for "None" values when applying ObjectUpdates? to agent
* Add AgentDynamicsUpdate? app event
* Handle 48-, 32-, and 16-byte ObjectUpdates?
* Add basic sit/stand/fly methods to agent, with associated enums

Not reviewed

Line 
1 # standard python libs
2 from logging import getLogger, CRITICAL, ERROR, WARNING, INFO, DEBUG
3 import uuid
4 import struct
5 import math
6
7 # pyogp
8 from pyogp.lib.base.exc import DataParsingError
9
10 # pyogp messaging
11
12 # initialize logging
13 logger = getLogger('pyogp.lib.base.datatypes')
14 log = logger.log
15
16 class Vector3(object):
17     """ represents a vector as a tuple"""
18
19     def __init__(self, bytes = None, offset = 0, X = 0.0, Y = 0.0, Z = 0.0):
20
21         if bytes != None:
22
23             self.unpack_from_bytes(bytes, offset)
24
25         else:
26
27             if type(X) != float:
28                 self.X = float(X)
29             else:
30                 self.X = X
31             if type(Y) != float:
32                 self.Y = float(Y)
33             else:
34                 self.Y = Y
35             if type(Z) != float:
36                 self.Z = float(Z)
37             else:
38                 self.Z = Z
39
40     def unpack_from_bytes(self, bytes, offset):
41         """ unpack floats from binary """
42
43         # unpack from binary as Little Endian
44         self.X = struct.unpack("<f", bytes[offset:offset+4])[0]
45         self.Y = struct.unpack("<f", bytes[offset+4:offset+8])[0]
46         self.Z = struct.unpack("<f", bytes[offset+8:offset+12])[0]
47
48     def get_bytes(self):
49         """ get bytes """
50
51         return struct.pack("<3f", self.X, self.Y, self.Z)
52
53     def data(self):
54
55         return ((self.X, self.Y, self.Z))
56
57     def copy(self):
58         return Vector3( X = self.X, Y = self.Y, Z = self.Z )
59
60     def __repr__(self):
61         """ represent a vector as a string """
62
63         return str((self.X, self.Y, self.Z))
64
65     def __call__(self):
66         """ represent a vector as a tuple """
67
68         return ((self.X, self.Y, self.Z))
69
70     def dist_squared(a, b):
71         x = a.X - b.X
72         y = a.Y - b.Y
73         z = a.Z - b.Z
74         return x*x + y*y + z*z
75     dist_squared = staticmethod(dist_squared)
76    
77
78 class Quaternion(object):
79     """ represents a quaternion as a tuple"""
80
81     def __init__(self, bytes = None, offset = 0, length = 4, X = 0.0, Y = 0.0, Z = 0.0, W = 0.0):
82
83         if bytes != None:
84
85             self.unpack_from_bytes(bytes, offset, length)
86
87         else:
88
89             if type(X) != float:
90                 self.X = float(X)
91             else:
92                 self.X = X
93             if type(Y) != float:
94                 self.Y = float(Y)
95             else:
96                 self.Y = Y           
97             if type(Z) != float:
98                 self.Z = float(Z)
99             else:
100                 self.Z = Z
101             if type(W) != float:
102                 self.W = float(W)
103             else:
104                 self.W = W
105
106     def unpack_from_bytes(self, bytes, offset, length=4):
107         """ unpack floats from binary """
108
109         # unpack from binary as Little Endian
110         self.X = struct.unpack("<f", bytes[offset:offset+4])[0]
111         self.Y = struct.unpack("<f", bytes[offset+4:offset+8])[0]
112         self.Z = struct.unpack("<f", bytes[offset+8:offset+12])[0]
113
114         if length == 4:
115             self.W = struct.unpack("<f", bytes[offset+12:offset+16])[0]
116
117         else:
118             # Unpack from vector3
119             t = 1.0 - (self.X*self.X + self.Y*self.Y + self.Z*self.Z)
120             if t > 0:
121                 self.W = math.sqrt(t)
122             else:
123                 # Avoid sqrt(-episilon)
124                 self.W = 0           
125
126     def get_bytes(self):
127         """ get bytes """
128
129         return struct.pack("<4f", self.X, self.Y, self.Z, self.W)
130
131     def data(self):
132
133         return ((self.X, self.Y, self.Z, self.W))
134
135     def copy(self):
136         return Quaternion(X=self.X, Y=self.Y, Z=self.Z, W=self.W)
137
138     def __repr__(self):
139         """ represent a quaternion as a string """
140
141         return str((self.X, self.Y, self.Z, self.W))
142
143     def __call__(self):
144         """ represent a quaternion as a tuple """
145
146         return ((self.X, self.Y, self.Z, self.W))
147
148 class UUID(object):
149     """ represents a uuid as, well, a uuid
150
151     inbound LLUUID data from packets is already UUID(), they are
152     already the same 'datatype'
153     """
154
155     def __init__(self, string = '00000000-0000-0000-0000-000000000000', bytes = None, offset = 0):
156
157         if bytes != None:
158
159             self.unpack_from_bytes(bytes, offset)
160
161         else:
162
163             self.uuid = uuid.UUID(string)
164
165     def random(self):
166
167         if str(self.uuid) == '00000000-0000-0000-0000-000000000000':
168             self.uuid = uuid.uuid4()
169             return self.uuid
170
171         else:
172             log(WARNING, "Attempted to overwrite a stored uuid %s with a random, that is a bad idea..." % (str(self.uuid)))
173
174     def unpack_from_bytes(self, bytes, offset):
175         """ unpack uuid from binary """
176
177         # unpack from binary
178         self.uuid = uuid.UUID(bytes = bytes[offset:offset+16])
179
180     def get_bytes(self):
181         """ get bytes """
182
183         return str(self.uuid.bytes)
184
185     def data(self):
186         """ represent a uuid as, well, a uuid """
187
188         return self.uuid
189
190     def copy(self):
191         return UUID(string=str(self.uuid))
192
193     def __repr__(self):
194         """ represent a uuid as a string """
195
196         return str(self.uuid)
197
198     def __call__(self):
199         """ represent a uuid as, well, a uuid """
200
201         return self.uuid
202
203
204     def __eq__(self, other):
205         if hasattr(other,'uuid'):
206             return self.uuid == other.uuid
207         else:
208             return False
209    
210
211     def __xor__(self, arg):
212         """ the xor of two UUIDs """
213         temp = self.uuid.int ^ arg.uuid.int
214         result = uuid.UUID(int = temp)
215         return UUID(result.__str__())
216        
217
218 """
219 Contributors can be viewed at:
220 http://svn.secondlife.com/svn/linden/projects/2008/pyogp/CONTRIBUTORS.txt
221
222 $LicenseInfo:firstyear=2008&license=apachev2$
223
224 Copyright 2009, Linden Research, Inc.
225
226 Licensed under the Apache License, Version 2.0 (the "License").
227 You may obtain a copy of the License at:
228     http://www.apache.org/licenses/LICENSE-2.0
229 or in
230     http://svn.secondlife.com/svn/linden/projects/2008/pyogp/LICENSE.txt
231
232 $/LicenseInfo$
233 """
234
Note: See TracBrowser for help on using the browser.