|
"""Selection-buffer handling code |
|
|
|
This code is resonsible for turning gluint * |
|
arrays into structured representations for use |
|
by Python-level code. |
|
""" |
|
from OpenGL._bytes import integer_types |
|
|
|
def uintToLong( value ): |
|
if value < 0: |
|
|
|
value = (value & 0x7fffffff) + 0x80000000 |
|
return value |
|
|
|
class GLSelectRecord( object ): |
|
"""Minimalist object for storing an OpenGL selection-buffer record |
|
|
|
Provides near and far as *float* values by dividing by |
|
self.DISTANCE_DIVISOR (2**32-1) |
|
From the spec: |
|
Depth values (which are in the range [0,1]) are multiplied by |
|
2^32 - 1, before being placed in the hit record. |
|
|
|
Names are unmodified, so normally are slices of the array passed in |
|
to GLSelectRecord.fromArray( array ) |
|
""" |
|
DISTANCE_DIVISOR = float((2**32)-1) |
|
__slots__ = ('near','far','names') |
|
def fromArray( cls, array, total ): |
|
"""Produce list with all records from the array""" |
|
result = [] |
|
index = 0 |
|
arrayLength = len(array) |
|
for item in range( total ): |
|
if index + 2 >= arrayLength: |
|
break |
|
count = array[index] |
|
near = array[index+1] |
|
far = array[index+2] |
|
names = [ uintToLong(v) for v in array[index+3:index+3+count]] |
|
result.append( cls( near, far, names ) ) |
|
index += 3+count |
|
return result |
|
fromArray = classmethod( fromArray ) |
|
|
|
def __init__( self, near, far, names ): |
|
"""Initialise/store the values""" |
|
self.near = self.convertDistance( near ) |
|
self.far = self.convertDistance( far ) |
|
self.names = names |
|
def convertDistance( self, value ): |
|
"""Convert a distance value from array uint to 0.0-1.0 range float""" |
|
return uintToLong( value ) / self.DISTANCE_DIVISOR |
|
def __getitem__( self, key ): |
|
"""Allow for treating the record as a three-tuple""" |
|
if isinstance( key, integer_types): |
|
return (self.near,self.far,self.names)[key] |
|
elif key in self.__slots__: |
|
try: |
|
return getattr( self, key ) |
|
except AttributeError as err: |
|
raise KeyError( """Don't have an index/key %r for %s instant"""%( |
|
key, self.__class__, |
|
)) |
|
|