"""Helper functions for wrapping array-using operations
These are functions intended to be used in wrapping
GL functions that deal with OpenGL array data-types.
"""
import OpenGL
from OpenGL import contextdata,error,wrapper,constants,converters
from OpenGL.arrays import arraydatatype
import logging
log = logging.getLogger( 'OpenGL.arrays.arrayhelpers' )
from OpenGL import acceleratesupport
AsArrayTypedSizeChecked = None
if acceleratesupport.ACCELERATE_AVAILABLE:
try:
from OpenGL_accelerate.arraydatatype import AsArrayTypedSizeChecked
from OpenGL_accelerate.wrapper import returnPyArgumentIndex
from OpenGL_accelerate.arraydatatype import (
AsArrayOfType,AsArrayTyped,AsArrayTypedSize
)
except ImportError, err:
log.warn(
"Unable to load arrayhelpers accelerator from OpenGL_accelerate"
)
if AsArrayTypedSizeChecked is None:
def returnPointer( result,baseOperation,pyArgs,cArgs, ):
"""Return the converted object as result of function
Note: this is a hack that always returns pyArgs[0]!
"""
return pyArgs[0]
class AsArrayOfType( converters.PyConverter ):
"""Given arrayName and typeName coerce arrayName to array of type typeName
TODO: It should be possible to drop this if ERROR_ON_COPY,
as array inputs always have to be the final objects in that
case.
"""
argNames = ( 'arrayName','typeName' )
indexLookups = (
('arrayIndex', 'arrayName','pyArgIndex'),
('typeIndex', 'typeName','pyArgIndex'),
)
def __init__( self, arrayName='pointer', typeName='type' ):
self.arrayName = arrayName
self.typeName = typeName
def __call__( self, arg, wrappedOperation, args):
"""Get the arg as an array of the appropriate type"""
type = args[ self.typeIndex ]
arrayType = arraydatatype.GL_CONSTANT_TO_ARRAY_TYPE[ type ]
return arrayType.asArray( arg )
class AsArrayTyped( converters.PyConverter ):
"""Given arrayName and arrayType, convert arrayName to array of type
TODO: It should be possible to drop this if ERROR_ON_COPY,
as array inputs always have to be the final objects in that
case.
"""
argNames = ( 'arrayName','arrayType' )
indexLookups = (
('arrayIndex', 'arrayName','pyArgIndex'),
)
def __init__( self, arrayName='pointer', arrayType=None ):
self.arrayName = arrayName
self.arrayType = arrayType
def __call__( self, arg, wrappedOperation, args):
"""Get the arg as an array of the appropriate type"""
return self.arrayType.asArray( arg )
class AsArrayTypedSize( converters.CConverter ):
"""Given arrayName and arrayType, determine size of arrayName
"""
argNames = ( 'arrayName','arrayType' )
indexLookups = (
('arrayIndex', 'arrayName','pyArgIndex'),
)
def __init__( self, arrayName='pointer', arrayType=None ):
self.arrayName = arrayName
self.arrayType = arrayType
def __call__( self, pyArgs, index, wrappedOperation ):
"""Get the arg as an array of the appropriate type"""
return self.arrayType.arraySize( pyArgs[self.arrayIndex ] )
else:
returnPointer = returnPyArgumentIndex( 0 )
if not OpenGL.ERROR_ON_COPY:
def asArrayType( typ, size=None ):
"""Create PyConverter to get first argument as array of type"""
return converters.CallFuncPyConverter( typ.asArray )
else:
def asArrayType( typ, size=None ):
"""No converter required"""
return None
if not OpenGL.ARRAY_SIZE_CHECKING:
asArrayTypeSize = asArrayType
else:
if AsArrayTypedSizeChecked:
asArrayTypeSize = AsArrayTypedSizeChecked
else:
def asArrayTypeSize( typ, size ):
"""Create PyConverter function to get array as type and check size
Produces a raw function, not a PyConverter instance
"""
asArray = typ.asArray
dataType = typ.typeConstant
arraySize = typ.arraySize
def asArraySize( incoming, function, args ):
handler = typ.getHandler( incoming )
result = handler.asArray( incoming, dataType )
actualSize = handler.arraySize(result, dataType)
if actualSize != size:
raise ValueError(
"""Expected %r item array, got %r item array"""%(
size,
actualSize,
),
incoming,
)
return result
return asArraySize
if not OpenGL.ERROR_ON_COPY:
def asVoidArray( ):
"""Create PyConverter returning incoming as an array of any type"""
from OpenGL.arrays import ArrayDatatype
return converters.CallFuncPyConverter( ArrayDatatype.asArray )
else:
def asVoidArray( ):
"""If there's no copying allowed, we can use default passing"""
return None
class storePointerType( object ):
"""Store named pointer value in context indexed by constant
pointerName -- named pointer argument
constant -- constant used to index in the context storage
Note: OpenGL.STORE_POINTERS can be set with ERROR_ON_COPY
to ignore this storage operation.
Stores the pyArgs (i.e. result of pyConverters) for the named
pointer argument...
"""
def __init__( self, pointerName, constant ):
self.pointerName = pointerName
self.constant = constant
def finalise( self, wrapper ):
self.pointerIndex = wrapper.pyArgIndex( self.pointerName )
def __call__( self, result, baseOperation, pyArgs, cArgs ):
contextdata.setValue( self.constant, pyArgs[self.pointerIndex] )
if not OpenGL.ERROR_ON_COPY:
def setInputArraySizeType( baseOperation, size, type, argName=0 ):
"""Decorate function with vector-handling code for a single argument
if OpenGL.ERROR_ON_COPY is False, then we return the
named argument, converting to the passed array type,
optionally checking that the array matches size.
if OpenGL.ERROR_ON_COPY is True, then we will dramatically
simplify this function, only wrapping if size is True, i.e.
only wrapping if we intend to do a size check on the array.
"""
function = wrapper.wrapper( baseOperation )
if not hasattr( function, 'returnValues' ):
if isinstance( argName, (str,unicode)):
function.setReturnValues( converters.returnPyArgument(argName) )
else:
raise TypeError(
"""Argname should be a string/unicode: %s"""%(type(argName))
)
if size is not None:
function.setPyConverter( argName, asArrayTypeSize(type, size) )
else:
function.setPyConverter( argName, asArrayType(type) )
function.setCConverter( argName, converters.getPyArgsName( argName ) )
return function
else:
def setInputArraySizeType( baseOperation, size, type, argName=0 ):
"""Decorate function with vector-handling code for a single argument
if OpenGL.ERROR_ON_COPY is False, then we return the
named argument, converting to the passed array type,
optionally checking that the array matches size.
if OpenGL.ERROR_ON_COPY is True, then we will dramatically
simplify this function, only wrapping if size is True, i.e.
only wrapping if we intend to do a size check on the array.
"""
if size is not None:
function = wrapper.wrapper( baseOperation )
# return value is always the source array...
function.setPyConverter( argName, asArrayTypeSize(type, size) )
function.setCConverter( argName,
converters.getPyArgsName( argName )
)
else:
function = baseOperation
return function
def arraySizeOfFirstType( typ, default ):
unitSize = typ.unitSize
def arraySizeOfFirst( pyArgs, index, baseOperation ):
"""Return the array size of the first argument"""
array = pyArgs[0]
if array is None:
return default
else:
return unitSize( array )
return arraySizeOfFirst
|