view src/parpg/bGrease/renderer/vector.py @ 150:3fc7cfa80771

Modified InventoryGrid to set a name for each slot containing the index. Added getSlot method to InventoryGrid. Renamed InventoryGUI class to CharacterGUI. Added InventoryGUI class which handles the inventory part of the CharacterGUI. An InventoryGUI instance is now created in CharacterGUI.
author KarstenBock@gmx.net
date Wed, 05 Oct 2011 12:59:22 +0200
parents 0f659c7675f6
children
line wrap: on
line source

#############################################################################
#
# Copyright (c) 2010 by Casey Duncan and contributors
# All Rights Reserved.
#
# This software is subject to the provisions of the MIT License
# A copy of the license should accompany this distribution.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
#
#############################################################################

__version__ = '$Id$'

__all__ = ('Vector',)

from parpg.bGrease.geometry import Vec2d
import ctypes
from math import sin, cos, radians
import pyglet


class Vector(object):
        """Renders shapes in a classic vector graphics style

        :param scale: Scaling factor applied to shape vertices when rendered.

        :param line_width: The line width provided to ``glLineWidth`` before rendering.
        	If not specified or None, ``glLineWidth`` is not called, and the line
        	width used is determined by the OpenGL state at the time of rendering.

        :param anti_alias: If ``True``, OpenGL blending and line smoothing is enabled.
        	This allows for fractional line widths as well. If ``False``, the blending
        	and line smoothing modes are unchanged.

        :param corner_fill: If true (the default), the shape corners will be filled
        	with round points when the ``line_width`` exceeds 2.0. This improves
        	the visual quality of the rendering at larger line widths at some
        	cost to performance. Has no effect if ``line_width`` is not specified.

        :param position_component: Name of :class:`grease.component.Position` 
        	component to use. Shapes rendered are offset by the entity positions.

        :param renderable_component: Name of :class:`grease.component.Renderable` 
        	component to use. This component specifies the entities to be 
        	rendered and their base color.

        :param shape_component: Name of :class:`grease.component.Shape` 
        	component to use. Source of the shape vertices for each entity.

        The entities rendered are taken from the intersection of he position,
        renderable and shape components each time :meth:`draw` is called.
        """

        CORNER_FILL_SCALE = 0.6
        CORNER_FILL_THRESHOLD = 2.0

        def __init__(self, scale=1.0, line_width=None, anti_alias=True, corner_fill=True,
                     position_component='position', 
                     renderable_component='renderable', 
                     shape_component='shape'):
                self.scale = float(scale)
                self.corner_fill = corner_fill
                self.line_width = line_width
                self.anti_alias = anti_alias
                self._max_line_width = None
                self.position_component = position_component
                self.renderable_component = renderable_component
                self.shape_component = shape_component

        def set_world(self, world):
                self.world = world

        def _generate_verts(self):
                """Generate vertex and index arrays for rendering"""
                vert_count = sum(len(shape.verts) + 1
                                 for shape, ignored, ignored in self.world.components.join(
                                         self.shape_component, self.position_component, self.renderable_component))
                v_array = (CVertColor * vert_count)()
                if vert_count > 65536:
                        i_array = (ctypes.c_uint * 2 * vert_count)()
                        i_size = pyglet.gl.GL_UNSIGNED_INT
                else:
                        i_array = (ctypes.c_ushort * (2 * vert_count))()
                        i_size = pyglet.gl.GL_UNSIGNED_SHORT
                v_index = 0
                i_index = 0
                scale = self.scale
                rot_vec = Vec2d(0, 0)
                for shape, position, renderable in self.world.components.join(
                        self.shape_component, self.position_component, self.renderable_component):
                        shape_start = v_index
                        angle = radians(-position.angle)
                        rot_vec.x = cos(angle)
                        rot_vec.y = sin(angle)
                        r = int(renderable.color.r * 255)
                        g = int(renderable.color.g * 255)
                        b = int(renderable.color.b * 255)
                        a = int(renderable.color.a * 255)
                        for vert in shape.verts:
                                vert = vert.cpvrotate(rot_vec) * scale + position.position
                                v_array[v_index].vert.x = vert.x
                                v_array[v_index].vert.y = vert.y
                                v_array[v_index].color.r = r
                                v_array[v_index].color.g = g
                                v_array[v_index].color.b = b
                                v_array[v_index].color.a = a
                                if v_index > shape_start:
                                        i_array[i_index] = v_index - 1
                                        i_index += 1
                                        i_array[i_index] = v_index
                                        i_index += 1
                                v_index += 1
                        if shape.closed and v_index - shape_start > 2:
                                i_array[i_index] = v_index - 1
                                i_index += 1
                                i_array[i_index] = shape_start
                                i_index += 1
                return v_array, i_size, i_array, i_index

        def draw(self, gl=pyglet.gl):
                vertices, index_size, indices, index_count = self._generate_verts()
                if index_count:
                        if self.anti_alias:
                                gl.glEnable(gl.GL_LINE_SMOOTH)
                                gl.glHint(gl.GL_LINE_SMOOTH_HINT, gl.GL_NICEST)
                                gl.glEnable(gl.GL_BLEND)
                                gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA)
                        gl.glPushClientAttrib(gl.GL_CLIENT_VERTEX_ARRAY_BIT)
                        gl.glEnableClientState(gl.GL_VERTEX_ARRAY)
                        gl.glEnableClientState(gl.GL_COLOR_ARRAY)
                        gl.glVertexPointer(
                                2, gl.GL_FLOAT, ctypes.sizeof(CVertColor), ctypes.pointer(vertices))
                        gl.glColorPointer(
                                4, gl.GL_UNSIGNED_BYTE, ctypes.sizeof(CVertColor), 
                                ctypes.pointer(vertices[0].color))
                        if self.line_width is not None:
                                gl.glLineWidth(self.line_width)
                                if self._max_line_width is None:
                                        range_out = (ctypes.c_float * 2)()
                                        gl.glGetFloatv(gl.GL_ALIASED_LINE_WIDTH_RANGE, range_out)
                                        self._max_line_width = float(range_out[1]) * self.CORNER_FILL_SCALE
                                if self.corner_fill and self.line_width > self.CORNER_FILL_THRESHOLD:
                                        gl.glEnable(gl.GL_POINT_SMOOTH)
                                        gl.glPointSize(
                                                min(self.line_width * self.CORNER_FILL_SCALE, self._max_line_width))
                                        gl.glDrawArrays(gl.GL_POINTS, 0, index_count)
                        gl.glDrawElements(gl.GL_LINES, index_count, index_size, ctypes.pointer(indices))
                        gl.glPopClientAttrib()


class CVert(ctypes.Structure):
        _fields_ = [("x", ctypes.c_float), ("y", ctypes.c_float)]

class CColor(ctypes.Structure):
        _fields_ = [
                ("r", ctypes.c_ubyte), 
                ("g", ctypes.c_ubyte), 
                ("b", ctypes.c_ubyte), 
                ("a", ctypes.c_ubyte),
        ]

class CVertColor(ctypes.Structure):
        _fields_ = [("vert", CVert), ("color", CColor)]