diff --git a/docs/source/conf.py b/docs/source/conf.py index e9f4b43..ca6063d 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -40,8 +40,8 @@ master_doc = 'index' # General information about the project. -project = u'PyGLy' -copyright = u'Adam Griffiths' +project = 'PyGLy' +copyright = 'Adam Griffiths' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -183,8 +183,8 @@ # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ - ('index', 'PyGLy.tex', u'PyGLy Documentation', - u'Adam Griffiths', 'manual'), + ('index', 'PyGLy.tex', 'PyGLy Documentation', + 'Adam Griffiths', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of @@ -213,8 +213,8 @@ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ - ('index', 'pygly', u'PyGLy Documentation', - [u'Adam Griffiths'], 1) + ('index', 'pygly', 'PyGLy Documentation', + ['Adam Griffiths'], 1) ] # If true, show URL addresses after external links. @@ -227,8 +227,8 @@ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - ('index', 'PyGLy', u'PyGLy Documentation', - u'Adam Griffiths', 'PyGLy', 'Pure Python OpenGL framework.', + ('index', 'PyGLy', 'PyGLy Documentation', + 'Adam Griffiths', 'PyGLy', 'Pure Python OpenGL framework.', 'Miscellaneous'), ] diff --git a/pygly/__init__.py b/pygly/__init__.py index e095f97..c0aaa1b 100644 --- a/pygly/__init__.py +++ b/pygly/__init__.py @@ -3,7 +3,7 @@ # the version of software # this is used by the setup.py script -from version import __version__ +from .version import __version__ # make 'from module import *' work dynamically. # otherwise we have to manually update the __all__ list. diff --git a/pygly/camera_node.py b/pygly/camera_node.py index 775cff9..ac556ca 100755 --- a/pygly/camera_node.py +++ b/pygly/camera_node.py @@ -1,41 +1,41 @@ -import math - -from pyrr import quaternion -from pyrr import matrix44 -from pyrr import ray - -from scene_node import SceneNode - - -class CameraNode( SceneNode ): - """A Scene Graph based camera. - """ - - - def __init__( self, name, projection_matrix ): - """Creates a CameraNode object. - - :param string name: The name to give to the node. - :param ProjectionMatrix projection_matrix: The camera's projection matrix. - """ - super( CameraNode, self ).__init__( name ) - - #: the camer's view matrix - self.projection_matrix = projection_matrix - - @property - def model_view( self ): - """Property for the camera's model view matrix. - - This is the inverse of the camera's world matrix - and is used as the initial matrix for the model view - matrix. - - This is an @property decorated method. - - :rtype: numpy.array - :return: A matrix set to the camera's model view - matrix. - """ - # return the inverse of our world matrix - return matrix44.inverse( self.world_transform.matrix ) +import math + +from pyrr import quaternion +from pyrr import matrix44 +from pyrr import ray + +from .scene_node import SceneNode + + +class CameraNode( SceneNode ): + """A Scene Graph based camera. + """ + + + def __init__( self, name, projection_matrix ): + """Creates a CameraNode object. + + :param string name: The name to give to the node. + :param ProjectionMatrix projection_matrix: The camera's projection matrix. + """ + super( CameraNode, self ).__init__( name ) + + #: the camer's view matrix + self.projection_matrix = projection_matrix + + @property + def model_view( self ): + """Property for the camera's model view matrix. + + This is the inverse of the camera's world matrix + and is used as the initial matrix for the model view + matrix. + + This is an @property decorated method. + + :rtype: numpy.array + :return: A matrix set to the camera's model view + matrix. + """ + # return the inverse of our world matrix + return matrix44.inverse( self.world_transform.matrix ) diff --git a/pygly/cocos2d/layer.py b/pygly/cocos2d/layer.py index d172602..6bd0414 100644 --- a/pygly/cocos2d/layer.py +++ b/pygly/cocos2d/layer.py @@ -46,7 +46,7 @@ def draw(self, *args, **kwargs): This is called by Cocos2D Director. """ - print 'layer draw' + print('layer draw') super( PyGLyLayer, self ).draw( *args, **kwargs ) # render the scene diff --git a/pygly/examples/application.py b/pygly/examples/application.py index 0156700..da15c2b 100644 --- a/pygly/examples/application.py +++ b/pygly/examples/application.py @@ -1,4 +1,4 @@ -from fps_monitor import FPS_Monitor +from .fps_monitor import FPS_Monitor class BaseApplication( object ): diff --git a/pygly/examples/application_glut.py b/pygly/examples/application_glut.py index 0931c80..d3d9148 100644 --- a/pygly/examples/application_glut.py +++ b/pygly/examples/application_glut.py @@ -5,7 +5,7 @@ import OpenGL.GL as GL import OpenGL.GLUT as GLUT -from application import BaseApplication +from .application import BaseApplication class Application( BaseApplication ): @@ -74,7 +74,7 @@ def on_key_released( self, key, x, y ): def on_special_key_pressed( self, key, x, y ): if key in self.keys: self.scene.on_key_pressed( self.keys[ key ] ) - print self.keys[ key ] + print(self.keys[ key ]) def on_special_key_released( self, key, x, y ): if key in self.keys: diff --git a/pygly/examples/application_pyglet.py b/pygly/examples/application_pyglet.py index 38dc70e..b0c1a6f 100644 --- a/pygly/examples/application_pyglet.py +++ b/pygly/examples/application_pyglet.py @@ -3,7 +3,7 @@ import pygly.gl import pygly.pyglet_monkey_patch -from application import BaseApplication +from .application import BaseApplication # disable the shadow window # this uses a legacy profile and causes issues diff --git a/pygly/examples/application_pyglfw.py b/pygly/examples/application_pyglfw.py index df28443..de9d417 100644 --- a/pygly/examples/application_pyglfw.py +++ b/pygly/examples/application_pyglfw.py @@ -4,7 +4,7 @@ import glfw import OpenGL.GL as GL -from application import BaseApplication +from .application import BaseApplication class Application( BaseApplication ): diff --git a/pygly/examples/fps_monitor.py b/pygly/examples/fps_monitor.py index b6974e1..ec5d4d1 100644 --- a/pygly/examples/fps_monitor.py +++ b/pygly/examples/fps_monitor.py @@ -17,6 +17,6 @@ def increment_frame( self ): new_time = time() diff = new_time - self.time if diff > self.print_time: - print "FPS:",float(self.frame_count) / diff + print("FPS:",float(self.frame_count) / diff) self.time = new_time self.frame_count = 0 diff --git a/pygly/examples/run_demo.py b/pygly/examples/run_demo.py index 1c3d429..cb7dda2 100644 --- a/pygly/examples/run_demo.py +++ b/pygly/examples/run_demo.py @@ -25,19 +25,19 @@ def parse_arguments(): ) parser.add_argument( "-g", "--opengl_profile", - choices = profiles.keys(), + choices = list(profiles.keys()), default = "core", help = "The OpenGL profile to use. (default: core)", ) parser.add_argument( "-p", "--platform", - choices = applications.keys(), + choices = list(applications.keys()), default = "pyglet", help = "The windowing platform to use. (default: pyglet)", ) parser.add_argument( "-d", "--demo", - choices = demos.keys(), + choices = list(demos.keys()), default = "basic", help = "The demo to run. (default: basic)", ) @@ -46,9 +46,9 @@ def parse_arguments(): def run_demo( args ): global profiles, applications, demos - print "Windowing system:\t", args.platform - print "OpenGL profile:\t", args.opengl_profile - print "Scene:\t", args.demo + print("Windowing system:\t", args.platform) + print("OpenGL profile:\t", args.opengl_profile) + print("Scene:\t", args.demo) is_core = profiles[ args.opengl_profile ] diff --git a/pygly/examples/scene_basic.py b/pygly/examples/scene_basic.py index e07317a..0b086d7 100644 --- a/pygly/examples/scene_basic.py +++ b/pygly/examples/scene_basic.py @@ -7,8 +7,8 @@ import pygly.gl import pygly.viewport -import scene -import renderable_triangle +from . import scene +from . import renderable_triangle class Scene( scene.Scene ): diff --git a/pygly/examples/scene_multiple_viewports.py b/pygly/examples/scene_multiple_viewports.py index 91f2566..43d926a 100644 --- a/pygly/examples/scene_multiple_viewports.py +++ b/pygly/examples/scene_multiple_viewports.py @@ -7,7 +7,7 @@ from pygly.scene_node import SceneNode from pygly.camera_node import CameraNode -import scene_scene_graph +from . import scene_scene_graph class Scene( scene_scene_graph.Scene ): @@ -69,7 +69,7 @@ def update_viewports(): height = height ) - print self.viewport, self.viewport2 + print(self.viewport, self.viewport2) def update_cameras(): # update the projection matrix diff --git a/pygly/examples/scene_orthographic.py b/pygly/examples/scene_orthographic.py index 8ce5cf5..baae302 100644 --- a/pygly/examples/scene_orthographic.py +++ b/pygly/examples/scene_orthographic.py @@ -1,7 +1,7 @@ import pyrr.rectangle import pyrr.matrix44 -import scene_scene_graph +from . import scene_scene_graph class Scene( scene_scene_graph.Scene ): diff --git a/pygly/examples/scene_scene_graph.py b/pygly/examples/scene_scene_graph.py index 09b8007..0d57ede 100644 --- a/pygly/examples/scene_scene_graph.py +++ b/pygly/examples/scene_scene_graph.py @@ -10,8 +10,8 @@ from pygly.scene_node import SceneNode from pygly.camera_node import CameraNode -import scene -import renderable_cube +from . import scene +from . import renderable_cube class Scene( scene.Scene ): diff --git a/pygly/examples/scene_sorting.py b/pygly/examples/scene_sorting.py index fecc3c0..dd08bd9 100644 --- a/pygly/examples/scene_sorting.py +++ b/pygly/examples/scene_sorting.py @@ -12,8 +12,8 @@ from pygly.camera_node import CameraNode import pygly.sort -import scene -import renderable_colour_cube +from . import scene +from . import renderable_colour_cube class Scene( scene.Scene ): diff --git a/pygly/examples/scene_texture.py b/pygly/examples/scene_texture.py index 3ccbb7f..09ea061 100644 --- a/pygly/examples/scene_texture.py +++ b/pygly/examples/scene_texture.py @@ -10,8 +10,8 @@ import pygly.viewport from pygly.texture import Texture2D -import scene -import renderable_textured_quad +from . import scene +from . import renderable_textured_quad class Scene( scene.Scene ): @@ -54,7 +54,7 @@ def initialise( self ): self.generate_random_textures() def load_texture_directory( self, directory ): - print 'Loading images from', directory + print('Loading images from', directory) extensions = [ '.png', @@ -72,12 +72,12 @@ def load_texture_directory( self, directory ): continue try: - print filename, + print(filename, end=' ') full_path = '%s/%s' % (directory, filename) texture = Texture2D.from_file(full_path) self.textures.append((filename, texture)) except Exception as e: - print 'Exception:', e + print('Exception:', e) # ensure we unbound our textures GL.glBindTexture( GL.GL_TEXTURE_2D, 0 ) @@ -167,14 +167,14 @@ def on_key_pressed( self, key ): self.current_texture %= len( self.textures ) name, texture = self.textures[ self.current_texture ] - print name, texture.internal_format + print(name, texture.internal_format) elif key == "left": self.current_texture -= 1 if self.current_texture < 0: self.current_texture = len( self.textures ) - 1 name, texture = self.textures[ self.current_texture ] - print name, texture.internal_format + print(name, texture.internal_format) def on_window_resized( self, width, height ): # update the viewport diff --git a/pygly/gl.py b/pygly/gl.py index 95e5bf4..ac096e4 100644 --- a/pygly/gl.py +++ b/pygly/gl.py @@ -42,7 +42,7 @@ def _generate_enum_map( enum_names ): OpenGL implementations. """ map = {} - for (key, value) in enum_names.items(): + for (key, value) in list(enum_names.items()): try: map[ getattr(GL, key) ] = value except AttributeError: @@ -114,11 +114,11 @@ def is_core(): def print_gl_info(): """Prints common OpenGL version information. """ - print "OpenGL Information:" + print("OpenGL Information:") for prop in ["GL_VENDOR", "GL_RENDERER", "GL_VERSION", "GL_SHADING_LANGUAGE_VERSION"]: type = getattr( GL, prop ) value = GL.glGetString( type ) - print "\t%s = %s" % (prop, value) + print("\t%s = %s" % (prop, value)) def string_to_type( type ): """Converts an OpenGL type from a string to an actual type. diff --git a/pygly/numpy_utils.py b/pygly/numpy_utils.py index 6ae09e6..0c36105 100644 --- a/pygly/numpy_utils.py +++ b/pygly/numpy_utils.py @@ -2,6 +2,7 @@ """ import numpy +from functools import reduce def dtype_stride( dtype, name = None ): diff --git a/pygly/render_callback_node.py b/pygly/render_callback_node.py index 2245cb2..9db6499 100755 --- a/pygly/render_callback_node.py +++ b/pygly/render_callback_node.py @@ -1,47 +1,47 @@ -from render_node import RenderNode - - -class RenderCallbackNode( RenderNode ): - """A RenderNode that takes an initialisation and a - render function as callbacks to perform rendering. - """ - - - def __init__( self, name, initialise_callback, render_callback ): - """Initialises the node with the specified callbacks. - - Args: - name: The name to give the node. - initialise_callback: The function to call when the - node is to be initialised. - The function must accept a pointer to this object. - render_callback: The function to call when the - node is to be rendered. - The function must accept a pointer to this object. - It must also accept a **kwargs parameter which will - be passed from the render() method. - Raises: - ValueError: Raised if the render callback == None. - """ - super( RenderCallbackNode, self ).__init__( name ) - - if render_callback == None: - raise ValueError( - "RenderNode render_callback cannot be None" - ) - - self.initialise_callback = initialise_callback - self.render_callback = render_callback - - # initialise the mesh now - if self.initialise_callback != None: - self.initialise_callback( self ) - - def on_context_lost( self ): - # re-create any data for the mesh - if self.initialise_callback != None: - self.initialise_callback( self ) - - def render( self, **kwargs ): - self.render_callback( self, **kwargs ) - +from .render_node import RenderNode + + +class RenderCallbackNode( RenderNode ): + """A RenderNode that takes an initialisation and a + render function as callbacks to perform rendering. + """ + + + def __init__( self, name, initialise_callback, render_callback ): + """Initialises the node with the specified callbacks. + + Args: + name: The name to give the node. + initialise_callback: The function to call when the + node is to be initialised. + The function must accept a pointer to this object. + render_callback: The function to call when the + node is to be rendered. + The function must accept a pointer to this object. + It must also accept a **kwargs parameter which will + be passed from the render() method. + Raises: + ValueError: Raised if the render callback == None. + """ + super( RenderCallbackNode, self ).__init__( name ) + + if render_callback == None: + raise ValueError( + "RenderNode render_callback cannot be None" + ) + + self.initialise_callback = initialise_callback + self.render_callback = render_callback + + # initialise the mesh now + if self.initialise_callback != None: + self.initialise_callback( self ) + + def on_context_lost( self ): + # re-create any data for the mesh + if self.initialise_callback != None: + self.initialise_callback( self ) + + def render( self, **kwargs ): + self.render_callback( self, **kwargs ) + diff --git a/pygly/render_node.py b/pygly/render_node.py index 825a445..96d24e8 100755 --- a/pygly/render_node.py +++ b/pygly/render_node.py @@ -1,28 +1,28 @@ -from scene_node import SceneNode - - -class RenderNode( SceneNode ): - """Base class for render functionality in a Scene Graph. - - Over-ride the :meth:`~pygly.render_node.RenderNode.render_mesh` - method to implement render functionality. - """ - - - def __init__( self, name ): - super( RenderNode, self ).__init__( name ) - - def on_context_lost( self ): - """Called when the graphic device context is lost. - - This method is a stub and is intended to be over-ridden. - """ - pass - - def render( self, **kwargs ): - """Called to render the mesh. - - This method is a stub and is intended to be over-ridden. - """ - pass - +from .scene_node import SceneNode + + +class RenderNode( SceneNode ): + """Base class for render functionality in a Scene Graph. + + Over-ride the :meth:`~pygly.render_node.RenderNode.render_mesh` + method to implement render functionality. + """ + + + def __init__( self, name ): + super( RenderNode, self ).__init__( name ) + + def on_context_lost( self ): + """Called when the graphic device context is lost. + + This method is a stub and is intended to be over-ridden. + """ + pass + + def render( self, **kwargs ): + """Called to render the mesh. + + This method is a stub and is intended to be over-ridden. + """ + pass + diff --git a/pygly/scene_node.py b/pygly/scene_node.py index dcdce5a..6be566f 100755 --- a/pygly/scene_node.py +++ b/pygly/scene_node.py @@ -1,61 +1,61 @@ -''' -.. todo:: rotate by matrix -.. todo:: rotate by eulers -.. todo:: rotate_about_axis( axis, radians ) -.. todo:: look_at_world -.. todo:: look_at_local -.. todo:: look_at_inertial -''' - -import weakref - -import numpy -from pydispatch import dispatcher - -from pyrr import quaternion -from pyrr import matrix33 -from pyrr import matrix44 -from tree_node import TreeNode -from transform import Transform -from world_transform import WorldTransform - - -class SceneNode( TreeNode ): - """Base class for Scene Graph objects. - """ - - def __init__( self, name ): - """Creates a SceneNode object with the specified name. - """ - super( SceneNode, self ).__init__() - - #: The name of the node. - self.name = name - - #: The local transform of the node. - self.transform = Transform() - #: The world transform of the node. - self.world_transform = WorldTransform( self.transform ) - - # listen for new parents and children - dispatcher.connect( - self._on_parent_changed, - TreeNode.on_parent_changed, - self - ) - - def _on_parent_changed( self, old_parent, new_parent ): - """Event handler for TreeNode's parent events. - - Manages the addition and removal of our world - transform from our parent. - """ - if old_parent != None: - old_parent.world_transform.remove_child( - self.world_transform - ) - if new_parent != None: - new_parent.world_transform.add_child( - self.world_transform - ) - +''' +.. todo:: rotate by matrix +.. todo:: rotate by eulers +.. todo:: rotate_about_axis( axis, radians ) +.. todo:: look_at_world +.. todo:: look_at_local +.. todo:: look_at_inertial +''' + +import weakref + +import numpy +from pydispatch import dispatcher + +from pyrr import quaternion +from pyrr import matrix33 +from pyrr import matrix44 +from .tree_node import TreeNode +from .transform import Transform +from .world_transform import WorldTransform + + +class SceneNode( TreeNode ): + """Base class for Scene Graph objects. + """ + + def __init__( self, name ): + """Creates a SceneNode object with the specified name. + """ + super( SceneNode, self ).__init__() + + #: The name of the node. + self.name = name + + #: The local transform of the node. + self.transform = Transform() + #: The world transform of the node. + self.world_transform = WorldTransform( self.transform ) + + # listen for new parents and children + dispatcher.connect( + self._on_parent_changed, + TreeNode.on_parent_changed, + self + ) + + def _on_parent_changed( self, old_parent, new_parent ): + """Event handler for TreeNode's parent events. + + Manages the addition and removal of our world + transform from our parent. + """ + if old_parent != None: + old_parent.world_transform.remove_child( + self.world_transform + ) + if new_parent != None: + new_parent.world_transform.add_child( + self.world_transform + ) + diff --git a/pygly/shader.py b/pygly/shader.py index 92e60c8..d30a1cd 100644 --- a/pygly/shader.py +++ b/pygly/shader.py @@ -451,10 +451,10 @@ def _print_shader_errors( self, buffer ): for error in errors: line, desc = error - print( "Error compiling shader type: %s" % enum_to_string( self.type ) ) - print( "\tLine: %i" % line ) - print( "\tDescription: %s" % desc ) - print( "\tCode: %s" % lines[ line - 1 ] ) + print(( "Error compiling shader type: %s" % enum_to_string( self.type ) )) + print(( "\tLine: %i" % line )) + print(( "\tDescription: %s" % desc )) + print(( "\tCode: %s" % lines[ line - 1 ] )) def __str__( self ): string = "%s(type=%s)" % ( @@ -551,8 +551,8 @@ def attach_shader( self, shader ): # attach the shader GL.glAttachShader( self.handle, shader.handle ) except Exception as e: - print( "Error attaching shader type: %s" % enum_to_string( shader.type ) ) - print( "\tException: %s" % str(e) ) + print(( "Error attaching shader type: %s" % enum_to_string( shader.type ) )) + print(( "\tException: %s" % str(e) )) # chain the exception raise @@ -602,7 +602,7 @@ def _print_shader_errors( self, buffer ): error buffer converted to a Python String. """ print( "Error linking shader:" ) - print( "\tDescription: %s" % ( buffer ) ) + print(( "\tDescription: %s" % ( buffer ) )) # print the log to the console errors = parse_shader_errors( buffer ) @@ -611,7 +611,7 @@ def _print_shader_errors( self, buffer ): line, desc = error print( "Error linking shader" ) - print( "\tDescription: %s" % ( desc ) ) + print(( "\tDescription: %s" % ( desc ) )) @property def linked( self ): @@ -727,10 +727,10 @@ def program( self ): return self._program def __iter__( self ): - return self.next() + return next(self) - def next( self ): - for uniform in self.all().values(): + def __next__( self ): + for uniform in list(self.all().values()): yield uniform def _on_program_linked( self ): @@ -964,7 +964,7 @@ def __init__( self ): def _set_data( self, program, name, type ): # ensure we have the right uniform type - print( "Uniform '%s' not specified in ShaderProgram" % name ) + print(( "Uniform '%s' not specified in ShaderProgram" % name )) @property def value( self ): @@ -1233,10 +1233,10 @@ def _on_program_linked( self ): ) def __iter__( self ): - return self.next() + return next(self) - def next( self ): - for attribute in self.all().values(): + def __next__( self ): + for attribute in list(self.all().values()): yield attribute def all( self ): @@ -1347,11 +1347,11 @@ def _register_uniforms(): Calling this multiple times will not do any harm. """ - Uniforms.register_uniform_class( UniformFloat, UniformFloat.types.keys() ) - Uniforms.register_uniform_class( UniformInt, UniformInt.types.keys() ) - Uniforms.register_uniform_class( UniformUint, UniformUint.types.keys() ) - Uniforms.register_uniform_class( UniformFloatMatrix, UniformFloatMatrix.types.keys() ) - Uniforms.register_uniform_class( UniformSampler, UniformSampler.types.keys() ) + Uniforms.register_uniform_class( UniformFloat, list(UniformFloat.types.keys()) ) + Uniforms.register_uniform_class( UniformInt, list(UniformInt.types.keys()) ) + Uniforms.register_uniform_class( UniformUint, list(UniformUint.types.keys()) ) + Uniforms.register_uniform_class( UniformFloatMatrix, list(UniformFloatMatrix.types.keys()) ) + Uniforms.register_uniform_class( UniformSampler, list(UniformSampler.types.keys()) ) _register_uniforms() diff --git a/pygly/test/test_tree_node.py b/pygly/test/test_tree_node.py index 6f235d5..6a22935 100644 --- a/pygly/test/test_tree_node.py +++ b/pygly/test/test_tree_node.py @@ -60,14 +60,14 @@ def test_node_dfs( self ): dfs = [ node for node in a1.dfs() ] for node in dfs: - print node.name + print(node.name) try: dfs = a1.dfs() - child = dfs.next() + child = next(dfs) while child: - print child.name - child = dfs.next() + print(child.name) + child = next(dfs) except StopIteration: pass @@ -75,33 +75,33 @@ def test_node_dfs( self ): # first match should be tier2 self.assertTrue( - dfs.next() in tier2, + next(dfs) in tier2, "First DFS incorrect" ) # second match should be tier3 self.assertTrue( - dfs.next() in tier3, + next(dfs) in tier3, "Second DFS incorrect" ) # third match should be tier3 self.assertTrue( - dfs.next() in tier3, + next(dfs) in tier3, "Third DFS incorrect" ) # fourth match should be tier 2 self.assertTrue( - dfs.next() in tier2, + next(dfs) in tier2, "Fourth DFS incorrect" ) # fifth match should be tier 3 self.assertTrue( - dfs.next() in tier3, + next(dfs) in tier3, "Fifth DFS incorrect" ) # sixth match should be tier3 self.assertTrue( - dfs.next() in tier3, + next(dfs) in tier3, "Sixth DFS incorrect" ) diff --git a/pygly/texture.py b/pygly/texture.py index f5da02f..6dace82 100644 --- a/pygly/texture.py +++ b/pygly/texture.py @@ -18,8 +18,8 @@ import numpy from pyrr.utils import parameters_as_numpy_arrays -import numpy_utils -import gl +from . import numpy_utils +from . import gl def active_unit(): @@ -56,7 +56,7 @@ def active_texture(target, unit): return handle def format(format): - if isinstance(format, basestring): + if isinstance(format, str): # TODO pass else: @@ -298,7 +298,7 @@ def allocate(self, shape, data_type, internal_format=None, **kwargs): if isinstance(data_type, numpy.dtype): # numpy dtype data_type = numpy_utils.dtype_gl_enum(data_type) - elif isinstance(data_type, basestring): + elif isinstance(data_type, str): # numpy dtype string data_type = numpy_utils.dtype_gl_enum(numpy.dtype(data_type)) @@ -322,7 +322,7 @@ def set_swizzle(swizzle): # only available on OpenGL Core if isinstance(swizzle, (list, tuple)): swizzle = (GL.GLint * len(swizzle))(*swizzle) - elif isinstance(swizzle, basestring): + elif isinstance(swizzle, str): result = [ Texture.channels[channel] for channel in swizzle.lower() diff --git a/pygly/transform.py b/pygly/transform.py index baf8b1b..5fda68d 100644 --- a/pygly/transform.py +++ b/pygly/transform.py @@ -1,183 +1,183 @@ -import sys - -import numpy -from pydispatch import dispatcher - -from pyrr import quaternion -from pyrr import matrix33 -from pyrr import matrix44 - -from object_space import ObjectSpace -from inertial_space import InertialSpace - - -class Transform( object ): - """Provides translation and orientation information and - methods for manipulating them. - - .. seealso:: - Class :py:class:`pygly.inertial_space.InertialSpace` - Documentation of the - :py:class:`pygly.inertial_space.InertialSpace` - class. - - Class :py:class:`pygly.object_space.ObjectSpace` - Documentation of the - :py:class:`pygly.object_space.ObjectSpace` - class. - """ - - on_transform_changed = "on_transform_changed" - - - def __init__( self ): - """Constructs a transform object. - """ - super( Transform, self ).__init__() - - self._orientation = quaternion.create_identity() - self._translation = numpy.zeros( 3, dtype = numpy.float ) - self._scale = numpy.ones( 3, dtype = numpy.float ) - self._matrix = None - - @property - def object( self ): - """Returns an ObjectSpace object for manipulating - the transform in object space co-ordinates. - - .. seealso:: - Class :py:class:`pygly.object_space.ObjectSpace` - Documentation of the - :py:class:`pygly.object_space.ObjectSpace` - class. - """ - return ObjectSpace( self ) - - @property - def inertial( self ): - """Returns an InertialSpace object for manipulating - the transform in inertial space co-ordinates. - - .. seealso:: - Class :py:class:`pygly.inertial_space.InertialSpace` - Documentation of the - :py:class:`pygly.inertial_space.InertialSpace` - class. - """ - return InertialSpace( self ) - - @property - def scale( self ): - """The scale of the transform. - - .. note:: Changing this value will dispatch an - 'on_transform_changed' event. - - .. note:: The is an @property decorated method which allows - retrieval and assignment of the scale value. - """ - return self._scale - - @scale.setter - def scale( self, scale ): - # don't check if the value hasn't changed - # using -= or += will cause this to fail - # due to python calling, getter, obj +, setter - # which would look as if the value hasn't changed - - self._scale[:] = scale - - # mark our matrix as dirty - self._matrix = None - - # notify others of our change - dispatcher.send( Transform.on_transform_changed, self ) - - @property - def orientation( self ): - """The orientation of the transform. - - Changing this value will dispatch an - 'on_transform_changed' event. - - The is an @property decorated method which allows - retrieval and assignment of the scale value. - """ - return self._orientation - - @orientation.setter - def orientation( self, orientation ): - # don't check if the value hasn't changed - # using -= or += will cause this to fail - # due to python calling, getter, obj +, setter - # which would look as if the value hasn't changed - - self._orientation[:] = orientation - - # mark our matrix as dirty - self._matrix = None - - # notify others of our change - dispatcher.send( Transform.on_transform_changed, self ) - - @property - def translation( self ): - """The translation of the transform. - - This is in inertial space. - - Changing this value will dispatch an - 'on_transform_changed' event. - - The is an @property decorated method which allows - retrieval and assignment of the scale value. - """ - return self._translation - - @translation.setter - def translation( self, vector ): - # don't check if the value hasn't changed - # using -= or += will cause this to fail - # due to python calling, getter, obj +, setter - # which would look as if the value hasn't changed - - self._translation[:] = vector - - # mark our matrix as dirty - self._matrix = None - - # notify others of our change - dispatcher.send( Transform.on_transform_changed, self ) - - @property - def matrix( self ): - """A matrix representing the transform's translation, - orientation and scale. - - The is an @property decorated method which allows - retrieval and assignment of the scale value. - """ - if self._matrix == None: - # matrix transformations must be done in order - # scaling - # rotation - # translation - - # apply our scale - self._matrix = matrix44.create_from_scale( self.scale ) - - # apply our quaternion - self._matrix = matrix44.multiply( - self._matrix, - matrix44.create_from_quaternion( self.orientation ) - ) - - # apply our translation - # we MUST do this after the orientation - self._matrix = matrix44.multiply( - self._matrix, - matrix44.create_from_translation( self.translation ) - ) - - return self._matrix - +import sys + +import numpy +from pydispatch import dispatcher + +from pyrr import quaternion +from pyrr import matrix33 +from pyrr import matrix44 + +from .object_space import ObjectSpace +from .inertial_space import InertialSpace + + +class Transform( object ): + """Provides translation and orientation information and + methods for manipulating them. + + .. seealso:: + Class :py:class:`pygly.inertial_space.InertialSpace` + Documentation of the + :py:class:`pygly.inertial_space.InertialSpace` + class. + + Class :py:class:`pygly.object_space.ObjectSpace` + Documentation of the + :py:class:`pygly.object_space.ObjectSpace` + class. + """ + + on_transform_changed = "on_transform_changed" + + + def __init__( self ): + """Constructs a transform object. + """ + super( Transform, self ).__init__() + + self._orientation = quaternion.create_identity() + self._translation = numpy.zeros( 3, dtype = numpy.float ) + self._scale = numpy.ones( 3, dtype = numpy.float ) + self._matrix = None + + @property + def object( self ): + """Returns an ObjectSpace object for manipulating + the transform in object space co-ordinates. + + .. seealso:: + Class :py:class:`pygly.object_space.ObjectSpace` + Documentation of the + :py:class:`pygly.object_space.ObjectSpace` + class. + """ + return ObjectSpace( self ) + + @property + def inertial( self ): + """Returns an InertialSpace object for manipulating + the transform in inertial space co-ordinates. + + .. seealso:: + Class :py:class:`pygly.inertial_space.InertialSpace` + Documentation of the + :py:class:`pygly.inertial_space.InertialSpace` + class. + """ + return InertialSpace( self ) + + @property + def scale( self ): + """The scale of the transform. + + .. note:: Changing this value will dispatch an + 'on_transform_changed' event. + + .. note:: The is an @property decorated method which allows + retrieval and assignment of the scale value. + """ + return self._scale + + @scale.setter + def scale( self, scale ): + # don't check if the value hasn't changed + # using -= or += will cause this to fail + # due to python calling, getter, obj +, setter + # which would look as if the value hasn't changed + + self._scale[:] = scale + + # mark our matrix as dirty + self._matrix = None + + # notify others of our change + dispatcher.send( Transform.on_transform_changed, self ) + + @property + def orientation( self ): + """The orientation of the transform. + + Changing this value will dispatch an + 'on_transform_changed' event. + + The is an @property decorated method which allows + retrieval and assignment of the scale value. + """ + return self._orientation + + @orientation.setter + def orientation( self, orientation ): + # don't check if the value hasn't changed + # using -= or += will cause this to fail + # due to python calling, getter, obj +, setter + # which would look as if the value hasn't changed + + self._orientation[:] = orientation + + # mark our matrix as dirty + self._matrix = None + + # notify others of our change + dispatcher.send( Transform.on_transform_changed, self ) + + @property + def translation( self ): + """The translation of the transform. + + This is in inertial space. + + Changing this value will dispatch an + 'on_transform_changed' event. + + The is an @property decorated method which allows + retrieval and assignment of the scale value. + """ + return self._translation + + @translation.setter + def translation( self, vector ): + # don't check if the value hasn't changed + # using -= or += will cause this to fail + # due to python calling, getter, obj +, setter + # which would look as if the value hasn't changed + + self._translation[:] = vector + + # mark our matrix as dirty + self._matrix = None + + # notify others of our change + dispatcher.send( Transform.on_transform_changed, self ) + + @property + def matrix( self ): + """A matrix representing the transform's translation, + orientation and scale. + + The is an @property decorated method which allows + retrieval and assignment of the scale value. + """ + if self._matrix == None: + # matrix transformations must be done in order + # scaling + # rotation + # translation + + # apply our scale + self._matrix = matrix44.create_from_scale( self.scale ) + + # apply our quaternion + self._matrix = matrix44.multiply( + self._matrix, + matrix44.create_from_quaternion( self.orientation ) + ) + + # apply our translation + # we MUST do this after the orientation + self._matrix = matrix44.multiply( + self._matrix, + matrix44.create_from_translation( self.translation ) + ) + + return self._matrix + diff --git a/pygly/vertex_buffer.py b/pygly/vertex_buffer.py index 25514fc..9421010 100644 --- a/pygly/vertex_buffer.py +++ b/pygly/vertex_buffer.py @@ -236,7 +236,7 @@ def __getitem__( self, index ): return self.attributes[ index ] def set( self, enable = True ): - for name, attribute in self.attributes.items(): + for name, attribute in list(self.attributes.items()): attribute.set( enable ) def push_attributes( self ): @@ -267,7 +267,7 @@ class BufferAttribute( object ): @classmethod def from_dtype( cls, buffer, dtype, name, offset = 0, **kwargs ): - import numpy_utils + from . import numpy_utils args = { 'buffer': buffer, diff --git a/pygly/weak_method_reference.py b/pygly/weak_method_reference.py index 7d2568b..bcd743f 100755 --- a/pygly/weak_method_reference.py +++ b/pygly/weak_method_reference.py @@ -1,134 +1,134 @@ -''' -Provides an implementation of a WeakMethodReference -for weak references to functions and methods. - -The standard weakref module in Python cannot store -references to non-bound functions and should not -be used to perform this task. - -Code borrowed from the following places: -http://code.activestate.com/recipes/81253/ -http://stackoverflow.com/questions/3942303/how-does-a-python-set-check-if-two-objects-are-equal-what-methods-does-an-o -''' - -import weakref -import new - - -class WeakMethodReference( object ): - """Provides the ability to store a weak pointer to - class members on top of the existing weakref functionality - provided by python. - - This class also provides comparison operators to - allow proper usage in containers such as set([]). - - The ability to change the weak reference is not - supported to prevent mutability. This is important - for container support as the object hash would - change after storing it. - """ - - def __init__(self, function = None ): - """Initialises the weak reference with - a function or class method. - - Args: - function: The object to store a weak reference to. - This can be a class, object, method or function. - """ - super( WeakMethodReference, self ).__init__() - - try: - if function.im_self is not None: - # bound method - self._obj = weakref.ref( function.im_self ) - else: - # unbound method - self._obj = None - self._func = function.im_func - self._class = function.im_class - except AttributeError: - # not a method - self._obj = None - self._func = function - self._class = None - - def __call__( self ): - """ - Returns: - Returns a new bound-method like the original, or - the original function if refers just to a function or - unbound method. - Returns None if the original object doesn't exist - """ - if self.is_dead(): - return None - if self._obj is not None: - # we have an instance: return a bound method - return new.instancemethod( - self._func, - self._obj(), - self._class - ) - else: - # we don't have an instance: return just the - # function - return self._func - - def is_dead( self ): - """Check if the referenced object is invalid. - - Returns: - True if the referenced callable was a bound method and - the instance no longer exists. Otherwise, return False. - """ - if self._obj is None and self._func is not None: - return False - if self._obj is not None and self._obj() is None: - return True - return False - - def is_alive( self ): - """Check if the referenced object is valid. - - The equivalent to 'not is_dead()' - Make a positive method call because double negatives suck - """ - return not self.is_dead() - - def __eq__( self, other ): - """Provides an 'equal' operator. - - .. note:: - Enables comparison between different weak - pointer objects that point to the same - object based on the contents instead of the - object pointer. - """ - return ( - isinstance(other, self.__class__ ) \ - and self.__dict__ == other.__dict__ - ) - - def __ne__( self, other ): - """Provides a 'not-equal' operator. - - .. note:: - Enables comparison between different weak - pointer objects that point to the same - object based on the contents instead of the - object pointer. - """ - return not self.__eq__(other) - - def __hash__( self ): - """Generates a hash value for the stored reference. - - .. note:: - This method is provided to allow comparison of - references inside of containers like set([]) - http://stackoverflow.com/questions/3942303/how-does-a-python-set-check-if-two-objects-are-equal-what-methods-does-an-o - """ - return hash( (self._obj, self._func, self._class) ) - +''' +Provides an implementation of a WeakMethodReference +for weak references to functions and methods. + +The standard weakref module in Python cannot store +references to non-bound functions and should not +be used to perform this task. + +Code borrowed from the following places: +http://code.activestate.com/recipes/81253/ +http://stackoverflow.com/questions/3942303/how-does-a-python-set-check-if-two-objects-are-equal-what-methods-does-an-o +''' + +import weakref +import new + + +class WeakMethodReference( object ): + """Provides the ability to store a weak pointer to + class members on top of the existing weakref functionality + provided by python. + + This class also provides comparison operators to + allow proper usage in containers such as set([]). + + The ability to change the weak reference is not + supported to prevent mutability. This is important + for container support as the object hash would + change after storing it. + """ + + def __init__(self, function = None ): + """Initialises the weak reference with + a function or class method. + + Args: + function: The object to store a weak reference to. + This can be a class, object, method or function. + """ + super( WeakMethodReference, self ).__init__() + + try: + if function.__self__ is not None: + # bound method + self._obj = weakref.ref( function.__self__ ) + else: + # unbound method + self._obj = None + self._func = function.__func__ + self._class = function.__self__.__class__ + except AttributeError: + # not a method + self._obj = None + self._func = function + self._class = None + + def __call__( self ): + """ + Returns: + Returns a new bound-method like the original, or + the original function if refers just to a function or + unbound method. + Returns None if the original object doesn't exist + """ + if self.is_dead(): + return None + if self._obj is not None: + # we have an instance: return a bound method + return new.instancemethod( + self._func, + self._obj(), + self._class + ) + else: + # we don't have an instance: return just the + # function + return self._func + + def is_dead( self ): + """Check if the referenced object is invalid. + + Returns: + True if the referenced callable was a bound method and + the instance no longer exists. Otherwise, return False. + """ + if self._obj is None and self._func is not None: + return False + if self._obj is not None and self._obj() is None: + return True + return False + + def is_alive( self ): + """Check if the referenced object is valid. + + The equivalent to 'not is_dead()' + Make a positive method call because double negatives suck + """ + return not self.is_dead() + + def __eq__( self, other ): + """Provides an 'equal' operator. + + .. note:: + Enables comparison between different weak + pointer objects that point to the same + object based on the contents instead of the + object pointer. + """ + return ( + isinstance(other, self.__class__ ) \ + and self.__dict__ == other.__dict__ + ) + + def __ne__( self, other ): + """Provides a 'not-equal' operator. + + .. note:: + Enables comparison between different weak + pointer objects that point to the same + object based on the contents instead of the + object pointer. + """ + return not self.__eq__(other) + + def __hash__( self ): + """Generates a hash value for the stored reference. + + .. note:: + This method is provided to allow comparison of + references inside of containers like set([]) + http://stackoverflow.com/questions/3942303/how-does-a-python-set-check-if-two-objects-are-equal-what-methods-does-an-o + """ + return hash( (self._obj, self._func, self._class) ) + diff --git a/pygly/world_transform.py b/pygly/world_transform.py index 44ca392..586aff0 100644 --- a/pygly/world_transform.py +++ b/pygly/world_transform.py @@ -1,191 +1,191 @@ -''' -Created on 11/06/2012 - -@author: adam -''' - -import sys - -import numpy -from pydispatch import dispatcher - -from pyrr import quaternion -from pyrr import matrix33 -from pyrr import matrix44 - -from object_space import ObjectSpace -from inertial_space import InertialSpace -from tree_node import TreeNode -from transform import Transform - - -class WorldTransform( TreeNode ): - - - def __init__( self, transform ): - super( WorldTransform, self ).__init__() - - self.set_dirty() - - # the local transform - self._transform = transform - - # register our event handlers - # listen for transform changes from local transform - dispatcher.connect( - self._on_transform_changed, - Transform.on_transform_changed, - self._transform - ) - - # listen for new parents and children - dispatcher.connect( - self._on_parent_changed, - TreeNode.on_parent_changed, - self - ) - - def set_dirty( self ): - self._orientation = None - self._translation = None - self._scale = None - self._matrix = None - - def _on_parent_changed( self, old_parent, new_parent ): - # mark ourself as dirty - self.set_dirty() - - # unregister from our old parent's events - if old_parent != None: - dispatcher.disconnect( - self._on_transform_changed, - Transform.on_transform_changed, - old_parent - ) - - # register to our new parent's events - if new_parent != None: - dispatcher.connect( - self._on_transform_changed, - Transform.on_transform_changed, - new_parent - ) - - - def _on_transform_changed( self ): - """ - .. note:: - Changing this value will dispatch an - 'on_transform_changed' event. - """ - # mark ourself as dirty - self.set_dirty() - - # notify others of our change - dispatcher.send( Transform.on_transform_changed, self ) - - @property - def object( self ): - return ObjectSpace( self ) - - @property - def inertial( self ): - return InertialSpace( self ) - - @property - def scale( self ): - if self._scale == None: - if self.parent == None: - # we don't have a parent - # so just use our current local scale - self._scale = self._transform.scale.copy() - else: - # apply our parents scale to our local scale - self._scale = self._transform.scale * self.parent.scale - - return self._scale - - @scale.setter - def scale( self, scale ): - # don't check if the value hasn't changed - # using -= or += will cause this to fail - # due to python calling, getter, obj +, setter - # which would look as if the value hasn't changed - - # determine the correct scale to - # modify our parents to make our scale - # == to the passed in value - self._transform.scale = scale / self.parent.scale - - @property - def orientation( self ): - if self._orientation == None: - if self.parent == None: - # we don't have a parent - # so just use our current local orientation - self._orientation = self._transform.orientation.copy() - else: - # multiply our rotation by our parents - # order is important, our quaternion should - # be the second parameter - self._orientation = quaternion.cross( - self.parent.orientation, - self._transform.orientation - ) - # ensure the quaternion is normalised - self._orientation = quaternion.normalise( self._orientation ) - - return self._orientation - - @orientation.setter - def orientation( self, quaternion ): - # don't check if the value hasn't changed - # using -= or += will cause this to fail - # due to python calling, getter, obj +, setter - # which would look as if the value hasn't changed - raise NotImplementedError - - @property - def translation( self ): - if self._translation == None: - if self.parent == None: - # we don't have a parent - # so just use our current local translation - self._translation = self._transform.translation.copy() - else: - # rotate our translation by our parent's - # world orientation - # this will include our parent's world translation - self._translation = matrix44.apply_to_vector( - self.parent.matrix, - self._transform.translation - ) - - return self._translation - - @translation.setter - def translation( self, translation ): - # don't check if the value hasn't changed - # using -= or += will cause this to fail - # due to python calling, getter, obj +, setter - # which would look as if the value hasn't changed - raise NotImplementedError - - @property - def matrix( self ): - """ - Returns a matrix representing the node's - object translation, orientation and - scale. - """ - if self._matrix == None: - if self.parent == None: - self._matrix = self._transform.matrix.copy() - else: - self._matrix = matrix44.multiply( - self._transform.matrix, - self.parent.matrix - ) - - return self._matrix - +''' +Created on 11/06/2012 + +@author: adam +''' + +import sys + +import numpy +from pydispatch import dispatcher + +from pyrr import quaternion +from pyrr import matrix33 +from pyrr import matrix44 + +from .object_space import ObjectSpace +from .inertial_space import InertialSpace +from .tree_node import TreeNode +from .transform import Transform + + +class WorldTransform( TreeNode ): + + + def __init__( self, transform ): + super( WorldTransform, self ).__init__() + + self.set_dirty() + + # the local transform + self._transform = transform + + # register our event handlers + # listen for transform changes from local transform + dispatcher.connect( + self._on_transform_changed, + Transform.on_transform_changed, + self._transform + ) + + # listen for new parents and children + dispatcher.connect( + self._on_parent_changed, + TreeNode.on_parent_changed, + self + ) + + def set_dirty( self ): + self._orientation = None + self._translation = None + self._scale = None + self._matrix = None + + def _on_parent_changed( self, old_parent, new_parent ): + # mark ourself as dirty + self.set_dirty() + + # unregister from our old parent's events + if old_parent != None: + dispatcher.disconnect( + self._on_transform_changed, + Transform.on_transform_changed, + old_parent + ) + + # register to our new parent's events + if new_parent != None: + dispatcher.connect( + self._on_transform_changed, + Transform.on_transform_changed, + new_parent + ) + + + def _on_transform_changed( self ): + """ + .. note:: + Changing this value will dispatch an + 'on_transform_changed' event. + """ + # mark ourself as dirty + self.set_dirty() + + # notify others of our change + dispatcher.send( Transform.on_transform_changed, self ) + + @property + def object( self ): + return ObjectSpace( self ) + + @property + def inertial( self ): + return InertialSpace( self ) + + @property + def scale( self ): + if self._scale == None: + if self.parent == None: + # we don't have a parent + # so just use our current local scale + self._scale = self._transform.scale.copy() + else: + # apply our parents scale to our local scale + self._scale = self._transform.scale * self.parent.scale + + return self._scale + + @scale.setter + def scale( self, scale ): + # don't check if the value hasn't changed + # using -= or += will cause this to fail + # due to python calling, getter, obj +, setter + # which would look as if the value hasn't changed + + # determine the correct scale to + # modify our parents to make our scale + # == to the passed in value + self._transform.scale = scale / self.parent.scale + + @property + def orientation( self ): + if self._orientation == None: + if self.parent == None: + # we don't have a parent + # so just use our current local orientation + self._orientation = self._transform.orientation.copy() + else: + # multiply our rotation by our parents + # order is important, our quaternion should + # be the second parameter + self._orientation = quaternion.cross( + self.parent.orientation, + self._transform.orientation + ) + # ensure the quaternion is normalised + self._orientation = quaternion.normalise( self._orientation ) + + return self._orientation + + @orientation.setter + def orientation( self, quaternion ): + # don't check if the value hasn't changed + # using -= or += will cause this to fail + # due to python calling, getter, obj +, setter + # which would look as if the value hasn't changed + raise NotImplementedError + + @property + def translation( self ): + if self._translation == None: + if self.parent == None: + # we don't have a parent + # so just use our current local translation + self._translation = self._transform.translation.copy() + else: + # rotate our translation by our parent's + # world orientation + # this will include our parent's world translation + self._translation = matrix44.apply_to_vector( + self.parent.matrix, + self._transform.translation + ) + + return self._translation + + @translation.setter + def translation( self, translation ): + # don't check if the value hasn't changed + # using -= or += will cause this to fail + # due to python calling, getter, obj +, setter + # which would look as if the value hasn't changed + raise NotImplementedError + + @property + def matrix( self ): + """ + Returns a matrix representing the node's + object translation, orientation and + scale. + """ + if self._matrix == None: + if self.parent == None: + self._matrix = self._transform.matrix.copy() + else: + self._matrix = matrix44.multiply( + self._transform.matrix, + self.parent.matrix + ) + + return self._matrix + diff --git a/setup.py b/setup.py index 321b1a2..7f23231 100644 --- a/setup.py +++ b/setup.py @@ -6,7 +6,7 @@ # get pygly's version but don't import it # or we'll need our dependencies already installed # https://github.com/todddeluca/happybase/commit/63573cdaefe3a2b98ece87e19d9ceb18f00bc0d9 -execfile('pygly/version.py') +exec(compile(open('pygly/version.py').read(), 'pygly/version.py', 'exec')) setup( name = 'pygly',