mirror of https://github.com/kivy/kivy.git
support canvas.after
This commit is contained in:
parent
c80d74c554
commit
a179d04a6f
|
@ -37,13 +37,28 @@ cdef class GraphicContext
|
|||
cdef class GraphicInstruction
|
||||
|
||||
cdef Canvas _active_canvas = None
|
||||
cdef int _active_canvas_after = 0
|
||||
|
||||
cdef class CanvasAfter:
|
||||
cdef Canvas canvas
|
||||
def __init__(self, canvas):
|
||||
self.canvas = canvas
|
||||
|
||||
def __enter__(self):
|
||||
self.canvas.__enter__(after=1)
|
||||
|
||||
def __exit__(self, extype, value, traceback):
|
||||
self.canvas.__exit__(extype, value, traceback, after=1)
|
||||
|
||||
|
||||
cdef class Canvas:
|
||||
cdef GraphicContext _context
|
||||
cdef VBO vertex_buffer
|
||||
cdef list texture_map
|
||||
cdef list _batch
|
||||
cdef list _batch_after
|
||||
cdef list _children
|
||||
cdef CanvasAfter _canvas_after
|
||||
|
||||
#move to graphics compiler?:
|
||||
cdef int _need_compile
|
||||
|
@ -52,9 +67,11 @@ cdef class Canvas:
|
|||
|
||||
def __cinit__(self):
|
||||
self._context = GraphicContext.instance()
|
||||
self._canvas_after = CanvasAfter(self)
|
||||
self.vertex_buffer = VBO()
|
||||
self.texture_map = []
|
||||
self._batch = []
|
||||
self._batch_after = []
|
||||
self._children = []
|
||||
|
||||
self._need_compile = 1
|
||||
|
@ -77,16 +94,24 @@ cdef class Canvas:
|
|||
def __get__(self):
|
||||
return self._batch
|
||||
|
||||
property after:
|
||||
def __get__(self):
|
||||
return self._canvas_after
|
||||
|
||||
cpdef trigger(self):
|
||||
self._context.trigger()
|
||||
|
||||
cpdef __enter__(self):
|
||||
global _active_canvas
|
||||
def __enter__(self, after=0):
|
||||
global _active_canvas, _active_canvas_after
|
||||
if _active_canvas:
|
||||
raise Exception('Cannot stack canvas usage.')
|
||||
_active_canvas = self
|
||||
_active_canvas_after = after
|
||||
|
||||
cpdef __exit__(self, extype, value, traceback):
|
||||
global _active_canvas
|
||||
def __exit__(self, extype, value, traceback, after=0):
|
||||
global _active_canvas, _active_canvas_after
|
||||
_active_canvas = None
|
||||
_active_canvas_after = after
|
||||
|
||||
cpdef add_canvas(self, Canvas canvas):
|
||||
if not canvas in self._children:
|
||||
|
@ -100,43 +125,62 @@ cdef class Canvas:
|
|||
|
||||
cdef add(self, GraphicInstruction instruction):
|
||||
self.need_compile = 1
|
||||
self._batch.append(instruction)
|
||||
if _active_canvas_after:
|
||||
self._batch_after.append(instruction)
|
||||
else:
|
||||
self._batch.append(instruction)
|
||||
|
||||
cdef remove(self, GraphicInstruction instruction):
|
||||
self.need_compile = 1
|
||||
if _active_canvas_after:
|
||||
self._batch_after.remove(instruction)
|
||||
else:
|
||||
self._batch.remove(instruction)
|
||||
|
||||
cdef update(self, instruction):
|
||||
''' called by graphic instructions taht are part of the canvas,
|
||||
when they have been changed in some way '''
|
||||
self.need_compile = 1
|
||||
|
||||
cdef remove(self, element):
|
||||
self.need_compile = 1
|
||||
pass
|
||||
|
||||
cdef compile(self):
|
||||
with self:
|
||||
self.compile_run()
|
||||
|
||||
cdef compile_init(self):
|
||||
cdef GraphicInstruction x
|
||||
self.texture_map = []
|
||||
self.batch_slices = []
|
||||
|
||||
# to prevent to regenerate object from previous compilation
|
||||
# remove all the object flagged as GI_COMPILER
|
||||
self._batch = [x for x in self._batch if not (x.code & GI_COMPILER)]
|
||||
self._batch = self.compile_strip_compiler(self._batch)
|
||||
self._batch_after = self.compile_strip_compiler(self._batch_after)
|
||||
|
||||
cdef list compile_strip_compiler(self, list batch):
|
||||
cdef GraphicInstruction x
|
||||
return [x for x in batch if not (x.code & GI_COMPILER)]
|
||||
|
||||
cdef compile_run(self):
|
||||
cdef compile(self):
|
||||
Logger.trace('GCanvas: start compilation')
|
||||
|
||||
self.compile_init()
|
||||
with self:
|
||||
self.compile_batch(self._batch)
|
||||
self.compile_children()
|
||||
with self.after:
|
||||
self.compile_batch(self._batch_after)
|
||||
|
||||
cdef compile_batch(self, list batch):
|
||||
cdef GraphicInstruction item
|
||||
cdef int slice_start = -1
|
||||
cdef int slice_stop = -1
|
||||
cdef int i, code
|
||||
cdef int i, code, batch_len
|
||||
|
||||
self.compile_init()
|
||||
# care about the batch. since we adding instruction, the size can change
|
||||
# while we are iterating.
|
||||
batch_len = len(batch)
|
||||
|
||||
Logger.trace('GCanvas: start compilation')
|
||||
# always start with binding vbo
|
||||
if batch_len:
|
||||
self.batch_slices.append(('bind', None))
|
||||
|
||||
for i in xrange(len(self._batch)):
|
||||
item = self._batch[i]
|
||||
for i in xrange(batch_len):
|
||||
item = batch[i]
|
||||
code = item.code
|
||||
# the instruction modifies the context, so we cant combine the drawing
|
||||
# calls before and after it
|
||||
|
@ -145,7 +189,7 @@ cdef class Canvas:
|
|||
#from slice_start to slice_stop. (using compile_slice() )
|
||||
#add the context modifying instruction to batch_slices
|
||||
#reset slice start/stop index
|
||||
self.compile_slice('draw', slice_start, slice_stop)
|
||||
self.compile_slice('draw', batch, slice_start, slice_stop)
|
||||
self.batch_slices.append(('instruction', item))
|
||||
slice_start = slice_stop = -1
|
||||
|
||||
|
@ -159,10 +203,7 @@ cdef class Canvas:
|
|||
slice_start = i
|
||||
|
||||
# maybe we ended on an slice of vartex data, whcih we didnt push yet
|
||||
self.compile_slice('draw', slice_start, slice_stop)
|
||||
|
||||
# draw children!
|
||||
self.compile_children()
|
||||
self.compile_slice('draw', batch, slice_start, slice_stop)
|
||||
|
||||
cdef compile_children(self):
|
||||
cdef Canvas child
|
||||
|
@ -172,10 +213,11 @@ cdef class Canvas:
|
|||
instr.code |= GI_COMPILER
|
||||
self.batch_slices.append(('instruction', instr))
|
||||
|
||||
cdef compile_slice(self, str command, slice_start, slice_end):
|
||||
cdef compile_slice(self, str command, list batch, slice_start, slice_end):
|
||||
Logger.trace('Canvas: compiling slice: %s' % str((
|
||||
slice_start, slice_end, command)))
|
||||
cdef VertexDataInstruction item
|
||||
cdef GraphicInstruction item
|
||||
cdef VertexDataInstruction vdi
|
||||
cdef Buffer b = Buffer(sizeof(GLint))
|
||||
cdef int v, i
|
||||
cdef GraphicInstruction instr
|
||||
|
@ -184,12 +226,14 @@ cdef class Canvas:
|
|||
if slice_start == -1:
|
||||
return
|
||||
|
||||
# loop pver all the whole slice, and combine all instructions
|
||||
for item in self._batch[slice_start:slice_end+1]:
|
||||
# add the vertex indices to be drawn from this item
|
||||
for i in range(item.num_elements):
|
||||
v = item.element_data[i]
|
||||
b.add(&v, NULL, 1)
|
||||
# loop over all the whole slice, and combine all instructions
|
||||
for item in batch[slice_start:slice_end+1]:
|
||||
if isinstance(item, VertexDataInstruction):
|
||||
vdi = item
|
||||
# add the vertex indices to be drawn from this item
|
||||
for i in range(vdi.num_elements):
|
||||
v = vdi.element_data[i]
|
||||
b.add(&v, NULL, 1)
|
||||
|
||||
# handle textures (should go somewhere else?,
|
||||
# maybe set GI_CONTEXT_MOD FLAG ALSO?)
|
||||
|
@ -221,15 +265,15 @@ cdef class Canvas:
|
|||
self.compile()
|
||||
self.need_compile = 0
|
||||
|
||||
self.vertex_buffer.bind()
|
||||
attr = VERTEX_ATTRIBUTES[0]
|
||||
glBindBuffer(GL_ARRAY_BUFFER, self.vertex_buffer.id)
|
||||
|
||||
for command, item in self.batch_slices:
|
||||
if command == 'instruction':
|
||||
if command == 'bind':
|
||||
self.vertex_buffer.bind()
|
||||
attr = VERTEX_ATTRIBUTES[0]
|
||||
glBindBuffer(GL_ARRAY_BUFFER, self.vertex_buffer.id)
|
||||
elif command == 'instruction':
|
||||
ci = item
|
||||
ci.apply()
|
||||
if command == 'draw':
|
||||
elif command == 'draw':
|
||||
b = item
|
||||
self.context.flush()
|
||||
glDrawElements(GL_TRIANGLES, b.count(), GL_UNSIGNED_INT, b.pointer())
|
||||
|
@ -1097,11 +1141,9 @@ cdef class Path(VertexDataInstruction):
|
|||
if abs(p.x-x) < 0.001 and abs(p.y-y) < 0.001:
|
||||
Logger("PATH: ignoring point(x,y)...already in list")
|
||||
return 0
|
||||
|
||||
|
||||
self.point_buffer.add(&v, &idx, 1)
|
||||
self.points.append(Point(x,y))
|
||||
|
||||
|
||||
return idx
|
||||
|
||||
cdef build_stroke(self):
|
||||
|
@ -1286,10 +1328,3 @@ cdef class PathStroke(PathInstruction):
|
|||
cdef class PathEnd(PathStroke):
|
||||
pass
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -201,7 +201,7 @@ class Parser(object):
|
|||
|
||||
# Two more level ?
|
||||
elif count == indent + 8:
|
||||
if current_property not in ('canvas', ):
|
||||
if current_property not in ('canvas', 'canvas.after'):
|
||||
raise ParserError(self, ln,
|
||||
'Invalid indentation, only allowed '
|
||||
'for canvas')
|
||||
|
@ -416,6 +416,9 @@ class BuilderBase(object):
|
|||
elif key == 'canvas':
|
||||
with widget.canvas:
|
||||
self.build_canvas(item, value)
|
||||
elif key == 'canvas.after':
|
||||
with widget.canvas.after:
|
||||
self.build_canvas(item, value)
|
||||
elif key == 'id':
|
||||
self.gidmap[value] = widget
|
||||
else:
|
||||
|
|
Loading…
Reference in New Issue