Esempio n. 1
0
def widgetshot(widget, filename='output.png'):
    # detach the widget from the parent
    parent = widget.parent
    if parent:
        parent.remove_widget(widget)

    # put the widget canvas on a Fbo
    texture = Texture.create(size=widget.size, colorfmt='rgb')
    fbo = Fbo(size=widget.size, texture=texture)
    fbo.add(widget.canvas)

    # clear the fbo background
    fbo.bind()
    fbo.clear_buffer()
    fbo.release()

    # draw!
    fbo.draw()

    # get the fbo data
    fbo.bind()
    data = glReadPixels(0, 0, widget.size[0], widget.size[1], GL_RGBA,
                        GL_UNSIGNED_BYTE)
    fbo.release()

    # save to a file
    surf = pygame.image.fromstring(data, widget.size, 'RGBA', True)
    pygame.image.save(surf, filename)

    # reattach to the parent
    if parent:
        parent.add_widget(widget)

    return True
Esempio n. 2
0
def screenshot(path, root_widget=None):
    """
    Take screenshot of the current state of the app and save it under ``path``.

    The sleep- and mainthread-decorator ensure that the app shows the current state properly.
    """
    if root_widget is None:
        root_widget = MDApp.get_running_app().root

    fbo = Fbo(
        size=(root_widget.width, root_widget.height),
        with_stencilbuffer=True,
    )

    with fbo:
        ClearColor(*MDApp.get_running_app().theme_cls.bg_normal)
        ClearBuffers()
        Scale(1, -1, 1)
        Translate(-root_widget.x, -root_widget.y - root_widget.height, 0)

    fbo.add(root_widget.canvas)
    fbo.draw()
    img = KivyImage(fbo.texture)

    img.save(path)
Esempio n. 3
0
 def __init__(self, app):
     super(World, self).__init__()
     self.size_hint = None, None
     self.size = SIZE
     self.pos_hint = {'center': (.5, 5)}
     self.hive = None
     self.rocks = []
     self.add_ground()
     w, h = SIZE
     with self.canvas:
         ground_fbo = Fbo(size=self.size)
         Rectangle(pos=(0, 0),
                   size=(w * 2, h * 2),
                   texture=ground_fbo.texture)
         Rectangle(pos=(0, 0), size=(w * 2, h * 2), texture=app.texture)
         Rectangle(pos=(0, 0),
                   size=(w * 2, h * 2),
                   texture=app.returning_paths_texture)
     with ground_fbo:
         Color(*STONE_COLOR_FLOAT)
         Line(rectangle=[0, 0, w, h], width=4)
         for rock in self.rocks:
             Line(points=rock.points, close=False, width=4)
         ground_fbo.draw()
     turn_to_world_array(ground_fbo.texture.pixels)
     self.populate()
Esempio n. 4
0
def widgetshot(widget, filename='output.png'): 
# detach the widget from the parent 
    parent = widget.parent
    if parent:
        parent.remove_widget(widget)

    # put the widget canvas on a Fbo
    texture = Texture.create(size=widget.size, colorfmt='rgb')
    fbo = Fbo(size=widget.size, texture=texture)
    fbo.add(widget.canvas)

    # clear the fbo background
    fbo.bind()
    fbo.clear_buffer()
    fbo.release()

    # draw!
    fbo.draw()

    # get the fbo data
    fbo.bind()
    data = glReadPixels(0, 0, widget.size[0], widget.size[1], GL_RGBA, GL_UNSIGNED_BYTE)
    fbo.release()

    # save to a file
    surf = pygame.image.fromstring(data, widget.size, 'RGBA', True)
    pygame.image.save(surf, filename)

    # reattach to the parent
    if parent:
        parent.add_widget(widget)

    return True
Esempio n. 5
0
def texture_get_data(texture):
    size = texture.size
    fbo = Fbo(size=texture.size, texture=texture)
    fbo.draw()
    fbo.bind()
    data = glReadPixels(0, 0, size[0], size[1], GL_RGBA, GL_UNSIGNED_BYTE)
    fbo.release()
    return data
Esempio n. 6
0
def texture_to_pil_image(texture):
    size = texture.size
    fbo = Fbo(size=texture.size, texture=texture)
    fbo.draw()
    fbo.bind()
    data = glReadPixels(0, 0, size[0], size[1], GL_RGBA, GL_UNSIGNED_BYTE)
    fbo.release()
    im = PILImage.fromstring('RGBA', size, data)
    return im
Esempio n. 7
0
def merged_texture_from_zip(filename):
    textures_list = textures_list_from_zip(filename)
    fbo = Fbo(size=textures_list[0].size)
    fbo.bind()
    with fbo:
        for texture in textures_list:
            Rectangle(texture=texture)
    fbo.release()
    fbo.draw()
    return fbo.texture
Esempio n. 8
0
def texture_add_to_zip(texture, zip_object, entry_name):
    size = texture.size
    fbo = Fbo(size=texture.size, texture=texture)
    fbo.draw()
    fbo.bind()
    if format == 'BMP':
        data = glReadPixels(0, 0, size[0], size[1], GL_RGB, GL_UNSIGNED_BYTE)
    else:
        data = glReadPixels(0, 0, size[0], size[1], GL_RGBA, GL_UNSIGNED_BYTE)
    fbo.release()
    zip_object.writestr(entry_name, data)
Esempio n. 9
0
    def export(self, wid, *largs):

        fbo = Fbo(size=wid.size, with_stencilbuffer=True)

        with fbo:
            ClearColor(1, 1, 1, 1)
            ClearBuffers()
            #Scale(1, -1, 1)
            #Translate(-self.x, -self.y - self.height, 0)

        fbo.add(wid.canvas)
        fbo.draw()
        img = fbo.texture
        img.save('test.png')
        fbo.remove(wid.canvas)
Esempio n. 10
0
def texture_save(texture, filename, format=None):
    size = texture.size
    fbo = Fbo(size=texture.size, texture=texture)
    fbo.draw()
    fbo.bind()
    if format == 'BMP':
        data = glReadPixels(0, 0, size[0], size[1], GL_RGB, GL_UNSIGNED_BYTE)
    else:
        data = glReadPixels(0, 0, size[0], size[1], GL_RGBA, GL_UNSIGNED_BYTE)
    fbo.release()
    if format == 'BMP':
        im = PILImage.fromstring('RGB', size, data)
    else:
        im = PILImage.fromstring('RGBA', size, data)
    im = im.transpose(PILImage.FLIP_TOP_BOTTOM)
    im.save(filename)
Esempio n. 11
0
def widget_save_canvas(widget, filename, format):
    parent = widget.parent
    if parent:
        parent.remove_widget(widget)
    size = (int(widget.size[0]), int(widget.size[1]))
    texture = Texture.create(size=widget.size, colorfmt='rgba')
    fbo = Fbo(size=widget.size, texture=texture)
    fbo.add(widget.canvas)
    fbo.draw()
    fbo.bind()
    data = glReadPixels(0, 0, size[0], size[1], GL_RGBA, GL_UNSIGNED_BYTE)
    fbo.release()
    im = PILImage.fromstring('RGBA', size, data)
    im = im.transpose(PILImage.FLIP_TOP_BOTTOM)
    im.save(filename, format)
    if parent:
        parent.add_widget(widget)
    return True
Esempio n. 12
0
 def create_image(self):
     parent = self.parent
     if parent:
         canvas_parent_index = parent.canvas.indexof(self.canvas)
         if canvas_parent_index > -1:
             parent.canvas.remove(self.canvas)
     fbo = Fbo(size=self.size, with_stencilbuffer=True)
     with fbo:
         ClearColor(0, 0, 0, 0)
         ClearBuffers()
         Scale(1, -1, 1)
         Translate(-self.x, -self.y - self.height, 0)
     fbo.add(self.canvas)
     fbo.draw()
     image = Image.frombytes('RGBA', list(map(int, self.size)),
                             fbo.texture.pixels, 'raw', 'RGBA', 0, 1)
     fbo.remove(self.canvas)
     if parent is not None and canvas_parent_index > -1:
         parent.canvas.insert(canvas_parent_index, self.canvas)
     return image
Esempio n. 13
0
def screenshot(widget, filename='output.png', region=None):
    if widget.parent is not None:
        canvas_parent_index = widget.parent.canvas.indexof(widget.canvas)
        widget.parent.canvas.remove(widget.canvas)

    fbo = Fbo(size=widget.size)

    with fbo:
        ClearColor(0, 0, 0, 0)
        ClearBuffers()
        Translate(-widget.x, -widget.y, 0)

    fbo.add(widget.canvas)
    fbo.draw()
    fbo.texture.save(filename)
    fbo.remove(widget.canvas)

    if widget.parent is not None:
        widget.parent.canvas.insert(canvas_parent_index, widget.canvas)

    return True
Esempio n. 14
0
class Graph(Image):
    def __init__(self, colors=(Color(1, 0, 1)), *args, **kwargs):
        if 'height' not in kwargs:
            kwargs['height'] = 32
        self.fbo = Fbo()
        with self.fbo:
            Color(1, 1, 1)
            self.fboscrollrect = Rectangle(pos=(-1, 0))
            Color(0, 0, 0)
            self.fboclearrect = Rectangle()
            self.points = []
            self.colors = []
            for color in colors:
                self.colors.append(Color(*color.rgba))
                self.points.append(Point(points=(), pointsize=0.5))
        super().__init__(*args, **kwargs)

    @staticmethod
    def to2pow(x):
        return 1 << (int(x) - 1).bit_length()

    def on_size(self, instance, size):
        self.fbo.size = (*(self.to2pow(v) for v in size), )
        self.fboscrollrect.size = self.fbo.size
        self.fboclearrect.pos = (self.fbo.size[0] - 1, 0)
        self.fboclearrect.size = (1, self.fbo.size[1])
        # this quick call to draw while the old texture is still attached stretches the old image instead of
        # preserving it at the proper scale, but at least it keeps the old data visible in some manner
        self.fbo.draw()
        self.fboscrollrect.texture = self.fbo.texture
        self.fboscrollrect.tex_coords = self.fbo.texture.tex_coords
        self.texture = self.fbo.texture

    def add(self, *values):
        for point, value in zip(self.points, values):
            point.points = (self.fbo.size[0] - 0.5,
                            (value + 1) / 2 * self.fbo.size[1])
        self.fbo.draw()
        self.canvas.ask_update()
Esempio n. 15
0
def screenshot_texture(widget, factory_func):
    if widget.parent is not None:
        canvas_parent_index = widget.parent.canvas.indexof(widget.canvas)
        widget.parent.canvas.remove(widget.canvas)

    fbo = Fbo(size=widget.size)

    with fbo:
        ClearColor(0, 0, 0, 0)
        ClearBuffers()
        Translate(-widget.x, -widget.y, 0)

    fbo.add(widget.canvas)
    fbo.draw()

    result = factory_func(fbo.texture)

    fbo.remove(widget.canvas)

    if widget.parent is not None:
        widget.parent.canvas.insert(canvas_parent_index, widget.canvas)

    return result
Esempio n. 16
0
def texture_merge(texture1, texture2):
    fbo = Fbo(size=texture2.size, texture=texture2)
    fbo.add(Rectangle(pos=(0, 0), texture=texture1, size=texture1.size))
    fbo.draw()
    return fbo.texture
Esempio n. 17
0
class FboFloatLayout(Widget):

    texture = ObjectProperty(None, allownone=True)
    vertices = ListProperty([])

    fbo = None
    tmp_fbo = None

    def __init__(self, **kwargs):

        self.canvas = Canvas()

        with self.canvas:
            self.fbo = Fbo(size=self.size)

        super(FboFloatLayout, self).__init__(**kwargs)

    # --
    # preload FBO with background texture
    def initFbo(self):

        with self.fbo:
            ClearColor(0, 0, 0, 0)
            ClearBuffers()
            #Rectangle(source = 'data/background.jpg', size=self.size, pos=self.pos)

        self.texture = self.fbo.texture

    # --
    # add the content of the widget to the FBO
    # this will literally render the widget into the texture
    def render_widget(self, widget):

        # create an FBO to render the widget to
        self.tmp_fbo = Fbo(size=self.size)
        self.tmp_fbo.add(ClearColor(0, 0, 0, 0))
        self.tmp_fbo.add(ClearBuffers())
        self.tmp_fbo.add(widget.canvas)
        self.tmp_fbo.draw()

        # render a rectangle in the main fbo containing the content from the widget
        with self.fbo:
            Color(1, 1, 1, 1)
            Rectangle(texture=self.tmp_fbo.texture, size=self.tmp_fbo.size)

    #def add_widget(self, *largs):
    # trick to attach graphics instruction to fbo instead of canvas
    #	canvas = self.canvas
    #	self.canvas = self.fbo
    #	ret = super(FboFloatLayout, self).add_widget(*largs)
    #	self.canvas = canvas

    # remove widget after next frame, this makes sure that
    # we do not use the widget for more than one frame
    #Clock.schedule_once(lambda dt: self.remove_widget(*largs))

    #	return ret

    #def remove_widget(self, *largs):
    #	canvas = self.canvas
    #	self.canvas = self.fbo
    #	super(FboFloatLayout, self).remove_widget(*largs)
    #	self.canvas = canvas

    def on_size(self, instance, value):
        self.size = value

        self.fbo.size = value

        #self.fbo_rect.size = value
        #self.fbo_background.size = value
        #self.fbo_rect.texture = self.fbo.texture

        # setup simple quad mesh to be rendered
        # the quad is used for actual resizing
        self.vertices = []
        self.vertices.extend([0, 0, 0, 0])
        self.vertices.extend([0, self.height, 0, 1])
        self.vertices.extend([self.width, self.height, 1, 1])
        self.vertices.extend([self.width, 0, 1, 0])

        #self.updateFbo()
        self.initFbo()
Esempio n. 18
0
class FboFloatLayout(Widget):

	texture = ObjectProperty(None, allownone=True)
	vertices = ListProperty([])
	
	fbo = None
	tmp_fbo = None 
	
	def __init__(self, **kwargs):
		
		self.canvas = Canvas()
		
		with self.canvas:
			self.fbo = Fbo(size=self.size)
			
		super(FboFloatLayout, self).__init__(**kwargs)

	# --
	# preload FBO with background texture
	def initFbo(self):
		
		with self.fbo:
			ClearColor(0,0,0,0)
			ClearBuffers()
			#Rectangle(source = 'data/background.jpg', size=self.size, pos=self.pos)

		self.texture = self.fbo.texture
				
	# --
	# add the content of the widget to the FBO
	# this will literally render the widget into the texture
	def render_widget(self, widget):

		# create an FBO to render the widget to
		self.tmp_fbo = Fbo(size = self.size)
		self.tmp_fbo.add(ClearColor(0,0,0,0))
		self.tmp_fbo.add(ClearBuffers())
		self.tmp_fbo.add(widget.canvas)
		self.tmp_fbo.draw()

		# render a rectangle in the main fbo containing the content from the widget
		with self.fbo:
			Color(1,1,1,1)
			Rectangle(texture=self.tmp_fbo.texture, size=self.tmp_fbo.size)
					
	#def add_widget(self, *largs):
		# trick to attach graphics instruction to fbo instead of canvas
	#	canvas = self.canvas
	#	self.canvas = self.fbo
	#	ret = super(FboFloatLayout, self).add_widget(*largs)
	#	self.canvas = canvas
		
		# remove widget after next frame, this makes sure that 
		# we do not use the widget for more than one frame
		#Clock.schedule_once(lambda dt: self.remove_widget(*largs))

	#	return ret

	#def remove_widget(self, *largs):
	#	canvas = self.canvas
	#	self.canvas = self.fbo
	#	super(FboFloatLayout, self).remove_widget(*largs)
	#	self.canvas = canvas

	def on_size(self, instance, value):
		self.size = value 
		
		self.fbo.size = value
		
		#self.fbo_rect.size = value
		#self.fbo_background.size = value
		#self.fbo_rect.texture = self.fbo.texture
		
		# setup simple quad mesh to be rendered
		# the quad is used for actual resizing
		self.vertices = []
		self.vertices.extend([0,0,0,0])
		self.vertices.extend([0,self.height,0,1])
		self.vertices.extend([self.width,self.height,1,1])
		self.vertices.extend([self.width,0,1,0])

		#self.updateFbo()		
		self.initFbo()
Esempio n. 19
0
class FboFloatLayout(FloatLayout):

    texture = ObjectProperty(None, allownone=True)

    alpha_blending = BooleanProperty(False)

    def __init__(self, **kwargs):
        self.canvas = Canvas()
        with self.canvas.before:
            Callback(self._set_blend_func)
        #self.size
        self.fbo_texture = Texture.create(size=self.size, colorfmt='rgba')

        self.fbo_texture.mag_filter = 'linear'
        self.fbo_texture.min_filter = 'linear'

        with self.canvas:
            #self.cbs = Callback(self.prepare_canvas)
            self.fbo = Fbo(size=self.size, texture=self.fbo_texture)
            #Color(1, 1, 1, 0)
            #self.fbo_rect = Rectangle()

        with self.fbo:
            ClearColor(0.0, 0.0, 0.0, 0.0)
            ClearBuffers()
            self.fbo_rect = Rectangle(size=self.size)

        #self.fbo.shader.source = resource_find('./kivy3dgui/gles2.0/shaders/invert.glsl')
        #with self.fbo.after:
        #    self.cbr = Callback(self.reset_gl_context)
        #    PopMatrix()

        with self.canvas.before:
            Callback(self._set_blend_func)

        # wait that all the instructions are in the canvas to set texture

        self.texture = self.fbo.texture
        super(FboFloatLayout, self).__init__(**kwargs)

    def prepare_canvas(self, *args):
        glEnable(GL_BLEND)
        glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE,
                            GL_ONE)
        glEnable(GL_DEPTH_TEST)

    def _set_blend_func(self, instruction):
        # clobber the blend mode
        if self.alpha_blending:
            glBlendFunc(GL_ONE, GL_ZERO)
        else:
            glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)

        glDisable(GL_CULL_FACE)
        self.fbo.draw()

        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)

    def setup_gl_context(self, *args):
        glEnable(GL_BLEND)
        glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA)
        glEnable(GL_DEPTH_TEST)

    def reset_gl_context(self, *args):
        glDisable(GL_DEPTH_TEST)
        glDisable(GL_CULL_FACE)
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)

    def add_widget(self, *largs):
        # trick to attach kivy3dgui instructino to fbo instead of canvas
        canvas = self.canvas
        self.canvas = self.fbo
        ret = super(FboFloatLayout, self).add_widget(*largs)
        self.canvas = canvas
        return ret

    def remove_widget(self, *largs):
        canvas = self.canvas
        self.canvas = self.fbo
        super(FboFloatLayout, self).remove_widget(*largs)
        self.canvas = canvas

    def on_size(self, instance, value):
        self.fbo.size = value
        self.texture = self.fbo_texture
        self.fbo_rect.size = value

    def on_pos(self, instance, value):
        self.fbo_rect.pos = value

    def on_texture(self, instance, value):
        self.fbo_rect.texture = value

    def on_touch_down(self, touch):
        return super(FboFloatLayout, self).on_touch_down(touch)

    def on_touch_move(self, touch):
        return super(FboFloatLayout, self).on_touch_move(touch)

    """def on_touch_up(self, touch):
        return super(FboFloatLayout, self).on_touch_up(touch)"""

    def on_touch_up(self, touch):
        for e in self.children:
            if e.collide_point(touch.x, touch.y):
                return e.on_touch_up(touch)
Esempio n. 20
0
class FboFloatLayout(FloatLayout):

    texture = ObjectProperty(None, allownone=True)

    alpha_blending = BooleanProperty(False)

    def __init__(self, **kwargs):
        self.canvas = Canvas()
        with self.canvas.before:
            Callback(self._set_blend_func)

        self.fbo_texture = Texture.create(size=self.size,
                                                  colorfmt='rgba',)
        self.fbo_texture.mag_filter='nearest'

        with self.canvas:
            #self.cbs = Callback(self.prepare_canvas)
            self.fbo = Fbo(size=self.size, texture=self.fbo_texture)
            #Color(1, 1, 1, 0)
            #self.fbo_rect = Rectangle()


        with self.fbo:
            ClearColor(0.0, 0.0, 0.0, 0.0)
            ClearBuffers()
            self.fbo_rect = Rectangle(size=self.size)


        #self.fbo.shader.source = resource_find('./kivy3dgui/gles2.0/shaders/invert.glsl')
        #with self.fbo.after:
        #    self.cbr = Callback(self.reset_gl_context)
        #    PopMatrix()

        with self.canvas.before:
            Callback(self._set_blend_func)

        # wait that all the instructions are in the canvas to set texture

        self.texture = self.fbo.texture
        super(FboFloatLayout, self).__init__(**kwargs)

    def prepare_canvas(self, *args):
        glEnable(GL_BLEND)
        glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE)
        glEnable(GL_DEPTH_TEST)

    def _set_blend_func(self, instruction):
        # clobber the blend mode
        if self.alpha_blending:
            glBlendFunc(GL_ONE,
                        GL_ZERO)
        else:

        #glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA,GL_ONE,GL_ONE_MINUS_SRC_ALPHA)
            #glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE)
            #glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA)
            glBlendFunc(GL_SRC_ALPHA,
                    GL_ONE_MINUS_SRC_ALPHA)


        # draw the buffer, not the whole freakin canvas
        glDisable(GL_CULL_FACE)
        self.fbo.draw()
        # unclobber the buffer
        glBlendFunc(GL_SRC_ALPHA,
                    GL_ONE_MINUS_SRC_ALPHA)

    def setup_gl_context(self, *args):
        glEnable(GL_BLEND)
        glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA)
        glEnable(GL_DEPTH_TEST)

    def reset_gl_context(self, *args):
        glDisable(GL_DEPTH_TEST)
        glDisable(GL_CULL_FACE)
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)


    def add_widget(self, *largs):
        # trick to attach kivy3dgui instructino to fbo instead of canvas
        canvas = self.canvas
        self.canvas = self.fbo
        ret = super(FboFloatLayout, self).add_widget(*largs)
        self.canvas = canvas
        return ret

    def remove_widget(self, *largs):
        canvas = self.canvas
        self.canvas = self.fbo
        super(FboFloatLayout, self).remove_widget(*largs)
        self.canvas = canvas

    def on_size(self, instance, value):
        self.fbo.size = value
        self.texture = self.fbo_texture
        self.fbo_rect.size = value

    def on_pos(self, instance, value):
        self.fbo_rect.pos = value

    def on_texture(self, instance, value):
        self.fbo_rect.texture = value

    def on_touch_down(self, touch):
        return super(FboFloatLayout, self).on_touch_down(touch)

    def on_touch_move(self, touch):
        return super(FboFloatLayout, self).on_touch_move(touch)

    def on_touch_up(self, touch):
        return super(FboFloatLayout, self).on_touch_up(touch)
Esempio n. 21
0
    def generate_movie(self,
                       filename,
                       out_fmt='yuv420p',
                       codec='libx264',
                       lib_opts={'crf': '0'},
                       video_fmt='mp4',
                       start=None,
                       end=None,
                       canvas_size=(0, 0),
                       canvas_size_hint=(1, 1),
                       projector_pos=(0, 0),
                       projector_pos_hint=(None, None),
                       paint_funcs=(),
                       stimulation_transparency=1.,
                       lum=1.,
                       speed=1.,
                       hidden_shapes=None):
        from kivy.graphics import (Canvas, Translate, Fbo, ClearColor,
                                   ClearBuffers, Scale)
        from kivy.core.window import Window

        rate = float(self.view_controller.frame_rate)
        rate_int = int(rate)
        if rate != rate_int:
            raise ValueError('Frame rate should be integer')
        orig_w, orig_h = (self.view_controller.screen_width,
                          self.view_controller.screen_height)

        canvas_w, canvas_h = canvas_size
        cv_hint_w, cv_hint_h = canvas_size_hint
        w = int(canvas_w if cv_hint_w is None else orig_w * cv_hint_w)
        h = int(canvas_h if cv_hint_h is None else orig_h * cv_hint_h)

        projector_x, projector_y = projector_pos
        projector_hint_x, projector_hint_y = projector_pos_hint
        x = int(projector_x if projector_hint_x is None else orig_w *
                projector_hint_x)
        y = int(projector_y if projector_hint_y is None else orig_h *
                projector_hint_y)

        Window.size = w, h
        intensities = self.shapes_intensity

        n = len(intensities[next(iter(intensities.keys()))])
        if start is not None:
            start = int(start * rate)
            if start >= n:
                raise Exception('Start time is after the end of the data')
        else:
            start = 0

        if end is not None:
            end = int(math.ceil(end * rate)) + 1
            if end <= start:
                raise Exception('End time is before or at the start time')
        else:
            end = n

        stream = {
            'pix_fmt_in': 'rgba',
            'pix_fmt_out': out_fmt,
            'width_in': w,
            'height_in': h,
            'width_out': w,
            'height_out': h,
            'codec': codec,
            'frame_rate': (int(speed * rate_int), 1)
        }
        writer = MediaWriter(filename, [stream],
                             fmt=video_fmt,
                             lib_opts=lib_opts)

        fbo = Fbo(size=(w, h), with_stencilbuffer=True)
        with fbo:
            ClearColor(0, 0, 0, 1)
            ClearBuffers()
            Scale(1, -1, 1)
            Translate(0, -h, 0)

        config = {
            'canvas': fbo,
            'pos': (x, y),
            'size': (w, h),
            'orig_size': (orig_w, orig_h),
            'rate': rate
        }
        paint_funcs = [func(config) for func in paint_funcs]
        paint_funcs = [func for func in paint_funcs if func is not None]

        fbo.draw()
        img = Image(plane_buffers=[fbo.pixels], pix_fmt='rgba', size=(w, h))
        writer.write_frame(img, 0.)

        fbo.add(Translate(x, y))
        shape_views = self.stage_factory.get_shapes_gl_color_instructions(
            fbo, 'stage_replay')
        fbo.add(Translate(-x, -y))

        pbar = tqdm(total=(end - 1 - start) / rate,
                    file=sys.stdout,
                    unit='second',
                    unit_scale=1)

        # all shapes listed in intensities must be in shape_views. However,
        # we don't want to show shapes not given values in intensities or if
        # they are to be hidden
        unused_shapes = set(shape_views) - set(intensities)
        unused_shapes.update(set(hidden_shapes or []))
        for name in unused_shapes:
            if name in shape_views:
                shape_views[name].rgba = 0, 0, 0, 0

        for i in range(start, end):
            pbar.update(1 / rate)
            for name, intensity in intensities.items():
                r, g, b, a = intensity[i]
                if name in unused_shapes:
                    a = 0
                shape_views[name].rgba = \
                    r * lum, g * lum, b * lum, a * stimulation_transparency

            try:
                for func in paint_funcs:
                    func(i)
            except EndOfDataException:
                break

            fbo.draw()
            img = Image(plane_buffers=[fbo.pixels],
                        pix_fmt='rgba',
                        size=(w, h))
            writer.write_frame(img, (i - start + 1) / (rate * speed))
        pbar.close()
Esempio n. 22
0
class Renderer(Widget):
    
    texture = ObjectProperty(None, allownone=True)    
    
    def __init__(self, **kwargs):

        #self.canvas = RenderContext(compute_normal_mat=True)
        #self.canvas.shader.source = resource_find('simple.glsl')
        self.canvas = Canvas()
        self.scene = ObjFileLoader(resource_find("testnurbs.obj"))
        
        self.meshes = []
        
        with self.canvas:
            self.fbo = Fbo(size=self.size, with_depthbuffer=True, compute_normal_mat=True, clear_color=(0., 0., 0., 0.))
            self.viewport = Rectangle(size=self.size, pos=self.pos)
        self.fbo.shader.source = resource_find('simple.glsl')
        #self.texture = self.fbo.texture
        

        super(Renderer, self).__init__(**kwargs)

        with self.fbo:
            #ClearBuffers(clear_depth=True)
            
            self.cb = Callback(self.setup_gl_context)
            PushMatrix()
            self.setup_scene()
            PopMatrix()
            self.cb = Callback(self.reset_gl_context)

        
        Clock.schedule_interval(self.update_scene, 1 / 60.)
        
        self._touches = []

    def on_size(self, instance, value):
        self.fbo.size = value
        self.viewport.texture = self.fbo.texture
        self.viewport.size = value
        self.update_glsl()

    def on_pos(self, instance, value):
        self.viewport.pos = value

    def on_texture(self, instance, value):
        self.viewport.texture = value


    def setup_gl_context(self, *args):
        #clear_buffer
        glEnable(GL_DEPTH_TEST)
        self.fbo.clear_buffer()
        #glDepthMask(GL_FALSE);

    def reset_gl_context(self, *args):
        glDisable(GL_DEPTH_TEST)
        

    def update_glsl(self, *largs):
        asp = self.width / float(self.height)
        proj = Matrix().view_clip(-asp, asp, -1, 1, 1, 100, 1)
        self.fbo['projection_mat'] = proj

    def setup_scene(self):
        Color(1, 1, 1, 0)

        PushMatrix()
        Translate(0, 0, -5)
        # This Kivy native Rotation is used just for
        # enabling rotation scene like trackball
        self.rotx = Rotate(0, 1, 0, 0)
        self.roty = Rotate(-120, 0, 1, 0) # here just rotate scene for best view
        self.scale = Scale(1)
                
        UpdateNormalMatrix()
        
        self.draw_elements()
        
        PopMatrix()

    def draw_elements(self):
        """ Draw separately all objects on the scene
            to setup separate rotation for each object
        """
        def _draw_element(m):
            Mesh(
                vertices=m.vertices,
                indices=m.indices,
                fmt=m.vertex_format,
                mode='triangles',
            )
            
        def _set_color(*color, **kw):
            id_color = kw.pop('id_color', (0, 0, 0))
            return ChangeState(
                        Kd=color,
                        Ka=color,
                        Ks=(.3, .3, .3),
                        Tr=1., Ns=1.,
                        intensity=1.,
                        id_color=[i / 255. for i in id_color],
                    )
            
        # Draw sphere in the center
        sphere = self.scene.objects['Sphere']
        _set_color(0.7, 0.7, 0., id_color=(255, 255, 0))
        _draw_element(sphere)
        
        # Then draw other elements and totate it in different axis
        pyramid = self.scene.objects['Pyramid']
        PushMatrix()
        self.pyramid_rot = Rotate(0, 0, 0, 1)
        _set_color(0., 0., .7, id_color=(0., 0., 255))
        _draw_element(pyramid)
        PopMatrix()
        
        box = self.scene.objects['Box']
        PushMatrix()
        self.box_rot = Rotate(0, 0, 1, 0)
        _set_color(.7, 0., 0., id_color=(255, 0., 0))
        _draw_element(box)
        PopMatrix()

        cylinder = self.scene.objects['Cylinder']
        PushMatrix()
        self.cylinder_rot = Rotate(0, 1, 0, 0)
        _set_color(0.0, .7, 0., id_color=(0., 255, 0))
        _draw_element(cylinder)
        PopMatrix()
    

    def update_scene(self, *largs):
        self.pyramid_rot.angle += 0.5
        self.box_rot.angle += 0.5
        self.cylinder_rot.angle += 0.5
        
    
    # =============== All stuff after is for trackball implementation =============
        
    def define_rotate_angle(self, touch):
        x_angle = (touch.dx/self.width)*360
        y_angle = -1*(touch.dy/self.height)*360
        return x_angle, y_angle
    
    def on_touch_down(self, touch):
        self._touch = touch
        touch.grab(self)
        self._touches.append(touch)
        
    def on_touch_up(self, touch): 
        touch.ungrab(self)
        self._touches.remove(touch)
        self.fbo.shader.source = 'select_mode.glsl'
        self.fbo.ask_update()
        self.fbo.draw()
        print(self.fbo.get_pixel_color(touch.x, touch.y))
        self.fbo.shader.source = 'simple.glsl'
        self.fbo.ask_update()
        self.fbo.draw()
    
    def on_touch_move(self, touch): 

        self.update_glsl()
        if touch in self._touches and touch.grab_current == self:
            if len(self._touches) == 1:
                # here do just rotation        
                ax, ay = self.define_rotate_angle(touch)
                
                self.roty.angle += ax
                self.rotx.angle += ay

            elif len(self._touches) == 2: # scaling here
                #use two touches to determine do we need scal
                touch1, touch2 = self._touches 
                old_pos1 = (touch1.x - touch1.dx, touch1.y - touch1.dy)
                old_pos2 = (touch2.x - touch2.dx, touch2.y - touch2.dy)
                
                old_dx = old_pos1[0] - old_pos2[0]
                old_dy = old_pos1[1] - old_pos2[1]
                
                old_distance = (old_dx*old_dx + old_dy*old_dy)
                Logger.debug('Old distance: %s' % old_distance)
                
                new_dx = touch1.x - touch2.x
                new_dy = touch1.y - touch2.y
                
                new_distance = (new_dx*new_dx + new_dy*new_dy)
                
                Logger.debug('New distance: %s' % new_distance)
                SCALE_FACTOR = 0.01
                
                if new_distance > old_distance: 
                    scale = SCALE_FACTOR
                    Logger.debug('Scale up')
                elif new_distance == old_distance:
                    scale = 0
                else:
                    scale = -1*SCALE_FACTOR
                    Logger.debug('Scale down')
                    
                xyz = self.scale.xyz
                
                if scale:
                    self.scale.xyz = tuple(p + scale for p in xyz)
Esempio n. 23
0
class NSpect(Widget):
    
    texture = ObjectProperty(None, allownone=True)    
    
    def __init__(self, **kwargs):

        LOP, dm = initFiles()

        #self.canvas = RenderContext(compute_normal_mat=True)
        #self.canvas.shader.source = resource_find('simple.glsl')
        self.canvas = Canvas()
        self.scene = ObjFileLoader(resource_find("testnurbs.obj"))
        self.LOP = LOP
        self.dm = dm
        
        self.meshes = []

        self.panCamera = False # KEITH EDIT
        self.pause = True # KEITH EDIT
        
        with self.canvas:
            self.fbo = Fbo(size=self.size, with_depthbuffer=True, compute_normal_mat=True, clear_color=(0., 0., 0., 0.))
            self.viewport = Rectangle(size=self.size, pos=self.pos)
        self.fbo.shader.source = resource_find('simple.glsl')
        #self.texture = self.fbo.texture
        
        # *&Y*&Y*&YH*&Y*&Y*&Y*Y&*
        # Keith: This allows keyboard interaction
        # http://stackoverflow.com/questions/22137786/
        self._keyboard = Window.request_keyboard(None, self)
        if not self._keyboard:
            return
        self._keyboard.bind(on_key_down=self.on_keyboard_down)
        # *&Y*&Y*&YH*&Y*&Y*&Y*Y&*
        
        super(NSpect, self).__init__(**kwargs)

        with self.fbo:
            #ClearBuffers(clear_depth=True)
            
            self.cb = Callback(self.setup_gl_context)
            PushMatrix()
            self.setup_scene(self.LOP, dm)
            PopMatrix()
            self.cb = Callback(self.reset_gl_context)

        
        Clock.schedule_interval(self.update_scene, 1 / 60.)
        
        self._touches = []

    def on_size(self, instance, value):
        self.fbo.size = value
        self.viewport.texture = self.fbo.texture
        self.viewport.size = value
        self.update_glsl()

    def on_pos(self, instance, value):
        self.viewport.pos = value

    def on_texture(self, instance, value):
        self.viewport.texture = value


    def setup_gl_context(self, *args):
        #clear_buffer
        glEnable(GL_DEPTH_TEST)
        self.fbo.clear_buffer()
        #glDepthMask(GL_FALSE);

    def reset_gl_context(self, *args):
        glDisable(GL_DEPTH_TEST)
        

    def update_glsl(self, *largs):
        asp = self.width / float(self.height)
        proj = Matrix().view_clip(-asp, asp, -1, 1, 1, 100, 1)
        self.fbo['projection_mat'] = proj

    def setup_scene(self, LOP, dm):
        Color(1, 1, 1, 0)

        PushMatrix()
        Translate(0, 0, -5)
        # This Kivy native Rotation is used just for
        # enabling rotation scene like trackball
        self.rotx = Rotate(0, 1, 0, 0)
        self.roty = Rotate(-120, 0, 1, 0) # here just rotate scene for best view
        self.scale = Scale(1)
                
        UpdateNormalMatrix()
        
        self.draw_elements(LOP, dm)
        
        PopMatrix()

    def draw_elements(self, LOP, dm):
        """ Draw separately all objects on the scene
            to setup separate rotation for each object
        """
        def _draw_element(m):
            Mesh(
                vertices=m.vertices,
                indices=m.indices,
                fmt=m.vertex_format,
                mode='triangles',
            )
            
        def _set_color(*color, **kw):
            id_color = kw.pop('id_color', (0, 0, 0))
            return ChangeState(
                        Kd=color,
                        Ka=color,
                        Ks=(.3, .3, .3),
                        Tr=1., Ns=1.,
                        intensity=1.,
                        id_color=[i / 255. for i in id_color],
                    )
            
        def drawPoints():
            print self.scene.objects
            for i in range(len(self.LOP)):
                PushMatrix()
                point = self.LOP[i]
                point.shape = self.scene.objects['Sphere']
                point.color = _set_color(i/10., (i+1)/10., 0., id_color=(int(255/(1+i)), int(255/(1+i)), 255))
                point.shape.scale = Scale((i+1)/10.0,(i+1)/10.0,(i+1)/10.0)
                self.LOP[i] = point
                print point.shape
                _draw_element(point.shape)
                point.shape.scale.origin =  (point.loc[0],point.loc[1],point.loc[2])
                PopMatrix()
                
        drawPoints()

    def update_scene(self, *largs):
        def randLoc(point):
            newLoc = (0.1*random.random(),0.1*random.random(),0.1*random.random())
            oldLoc = point.shape.scale.origin
            newLoc = ( newLoc[0]-0.05+oldLoc[0], newLoc[1]-0.05+oldLoc[1], newLoc[2]-0.05+oldLoc[2] )
            return newLoc 
        def updateLocs(self):        
            for i in range(len(self.LOP)):
                point = self.LOP[i]
                point.shape.scale.origin = randLoc(point) 
           
        if not self.pause:
            updateLocs(self)        
        pass

        
    
    # =============== All stuff after is for trackball implementation =============
    def moveA(self):
        

        pass
    def moveB(self):
        pass
    def define_rotate_angle(self, touch):
        x_angle = (touch.dx/self.width)*360
        y_angle = -1*(touch.dy/self.height)*360
        return x_angle, y_angle
    
    def on_touch_down(self, touch):
        self._touch = touch
        touch.grab(self)
        self._touches.append(touch)
        
    def on_touch_up(self, touch): 
        touch.ungrab(self)
        self._touches.remove(touch)
        self.fbo.shader.source = 'select_mode.glsl'
        self.fbo.ask_update()
        self.fbo.draw()
        print self.fbo.get_pixel_color(touch.x, touch.y)
        self.fbo.shader.source = 'simple.glsl'
        self.fbo.ask_update()
        self.fbo.draw()
    
    # *O(U(U())(*U(*(******************
    # Keith: This allows keyboard interaction
    def on_keyboard_down(self, keyboard, keycode, text, modifiers):
        if keycode[1] == 'left':
            if self.panCamera == True:
                self.x -= 10
            else: 
                self.roty.angle += 10
        elif keycode[1] == 'right':
            if self.panCamera == True:
                self.x += 10
            else: 
                self.roty.angle -= 10
        if keycode[1] == 'up':
            if self.panCamera == True:
                self.y += 10
            else: 
                self.rotx.angle += 10
        elif keycode[1] == 'down':
            if self.panCamera == True:
                self.y -= 10
            else: 
                self.rotx.angle -= 10

        elif keycode[1] == 'i':
            self.update_glsl()                             
            SCALE_FACTOR = 0.01             
            scale = SCALE_FACTOR
            Logger.debug('Scale up')                  
            xyz = self.scale.xyz                
            if scale:
                self.scale.xyz = tuple(p + scale for p in xyz)
        elif keycode[1] == 'o':
            self.update_glsl()                             
            SCALE_FACTOR = 0.01             
            scale = SCALE_FACTOR
            Logger.debug('Scale up')                  
            xyz = self.scale.xyz  
            if scale:
                temp = tuple(p - scale for p in xyz)
                # Prevent the collection from having a negative size
                if temp[0] > 0:
                    self.scale.xyz = temp
        elif keycode[1] == 't':
            self.panCamera = not self.panCamera    
        elif keycode[1] == 'p':
            self.pause = not self.pause    
            if not self.pause:
                print "Playing"
            else:
                print "Paused"
    
    
    
    def on_touch_move(self, touch): 

        self.update_glsl()
        if touch in self._touches and touch.grab_current == self:
            if len(self._touches) == 1:
                # here do just rotation        
                ax, ay = self.define_rotate_angle(touch)
                
                self.roty.angle += ax
                self.rotx.angle += ay

            elif len(self._touches) == 2: # scaling here
                #use two touches to determine do we need scal
                touch1, touch2 = self._touches 
                old_pos1 = (touch1.x - touch1.dx, touch1.y - touch1.dy)
                old_pos2 = (touch2.x - touch2.dx, touch2.y - touch2.dy)
                
                old_dx = old_pos1[0] - old_pos2[0]
                old_dy = old_pos1[1] - old_pos2[1]
                
                old_distance = (old_dx*old_dx + old_dy*old_dy)
                Logger.debug('Old distance: %s' % old_distance)
                
                new_dx = touch1.x - touch2.x
                new_dy = touch1.y - touch2.y
                
                new_distance = (new_dx*new_dx + new_dy*new_dy)
                
                Logger.debug('New distance: %s' % new_distance)
                SCALE_FACTOR = 0.01
                
                if new_distance > old_distance: 
                    scale = SCALE_FACTOR
                    Logger.debug('Scale up')
                elif new_distance == old_distance:
                    scale = 0
                else:
                    scale = -1*SCALE_FACTOR
                    Logger.debug('Scale down')
                    
                xyz = self.scale.xyz
                
                if scale:
                    self.scale.xyz = tuple(p + scale for p in xyz)
Esempio n. 24
0
class Renderer(Widget):
    
    texture = ObjectProperty(None, allownone=True)    
    
    def __init__(self, **kwargs):

        #self.canvas = RenderContext(compute_normal_mat=True)
        #self.canvas.shader.source = resource_find('simple.glsl')
        self.canvas = Canvas()
        self.scene = ObjFileLoader(resource_find("testnurbs.obj"))
        
        self.meshes = []
        
        with self.canvas:
            self.fbo = Fbo(size=self.size, with_depthbuffer=True, compute_normal_mat=True, clear_color=(0., 0., 0., 0.))
            self.viewport = Rectangle(size=self.size, pos=self.pos)
        self.fbo.shader.source = resource_find('simple.glsl')
        #self.texture = self.fbo.texture
        

        super(Renderer, self).__init__(**kwargs)

        with self.fbo:
            #ClearBuffers(clear_depth=True)
            
            self.cb = Callback(self.setup_gl_context)
            PushMatrix()
            self.setup_scene()
            PopMatrix()
            self.cb = Callback(self.reset_gl_context)

        
        Clock.schedule_interval(self.update_scene, 1 / 60.)
        
        self._touches = []

    def on_size(self, instance, value):
        self.fbo.size = value
        self.viewport.texture = self.fbo.texture
        self.viewport.size = value
        self.update_glsl()

    def on_pos(self, instance, value):
        self.viewport.pos = value

    def on_texture(self, instance, value):
        self.viewport.texture = value


    def setup_gl_context(self, *args):
        #clear_buffer
        glEnable(GL_DEPTH_TEST)
        self.fbo.clear_buffer()
        #glDepthMask(GL_FALSE);

    def reset_gl_context(self, *args):
        glDisable(GL_DEPTH_TEST)
        

    def update_glsl(self, *largs):
        asp = self.width / float(self.height)
        proj = Matrix().view_clip(-asp, asp, -1, 1, 1, 100, 1)
        self.fbo['projection_mat'] = proj

    def setup_scene(self):
        Color(1, 1, 1, 0)

        PushMatrix()
        Translate(0, 0, -5)
        # This Kivy native Rotation is used just for
        # enabling rotation scene like trackball
        self.rotx = Rotate(0, 1, 0, 0)
        self.roty = Rotate(-120, 0, 1, 0) # here just rotate scene for best view
        self.scale = Scale(1)
                
        UpdateNormalMatrix()
        
        self.draw_elements()
        
        PopMatrix()

    def draw_elements(self):
        """ Draw separately all objects on the scene
            to setup separate rotation for each object
        """
        def _draw_element(m):
            Mesh(
                vertices=m.vertices,
                indices=m.indices,
                fmt=m.vertex_format,
                mode='triangles',
            )
            
        def _set_color(*color, **kw):
            id_color = kw.pop('id_color', (0, 0, 0))
            return ChangeState(
                        Kd=color,
                        Ka=color,
                        Ks=(.3, .3, .3),
                        Tr=1., Ns=1.,
                        intensity=1.,
                        id_color=[i / 255. for i in id_color],
                    )
            
        # Draw sphere in the center
        sphere = self.scene.objects['Sphere']
        _set_color(0.7, 0.7, 0., id_color=(255, 255, 0))
        _draw_element(sphere)
        
        # Then draw other elements and totate it in different axis
        pyramid = self.scene.objects['Pyramid']
        PushMatrix()
        self.pyramid_rot = Rotate(0, 0, 0, 1)
        _set_color(0., 0., .7, id_color=(0., 0., 255))
        _draw_element(pyramid)
        PopMatrix()
        
        box = self.scene.objects['Box']
        PushMatrix()
        self.box_rot = Rotate(0, 0, 1, 0)
        _set_color(.7, 0., 0., id_color=(255, 0., 0))
        _draw_element(box)
        PopMatrix()

        cylinder = self.scene.objects['Cylinder']
        PushMatrix()
        self.cylinder_rot = Rotate(0, 1, 0, 0)
        _set_color(0.0, .7, 0., id_color=(0., 255, 0))
        _draw_element(cylinder)
        PopMatrix()
    

    def update_scene(self, *largs):
        self.pyramid_rot.angle += 0.5
        self.box_rot.angle += 0.5
        self.cylinder_rot.angle += 0.5
        
    
    # =============== All stuff after is for trackball implementation =============
        
    def define_rotate_angle(self, touch):
        x_angle = (touch.dx/self.width)*360
        y_angle = -1*(touch.dy/self.height)*360
        return x_angle, y_angle
    
    def on_touch_down(self, touch):
        self._touch = touch
        touch.grab(self)
        self._touches.append(touch)
        
    def on_touch_up(self, touch): 
        touch.ungrab(self)
        self._touches.remove(touch)
        self.fbo.shader.source = 'select_mode.glsl'
        self.fbo.ask_update()
        self.fbo.draw()
        print self.fbo.get_pixel_color(touch.x, touch.y)
        self.fbo.shader.source = 'simple.glsl'
        self.fbo.ask_update()
        self.fbo.draw()
    
    def on_touch_move(self, touch): 

        self.update_glsl()
        if touch in self._touches and touch.grab_current == self:
            if len(self._touches) == 1:
                # here do just rotation        
                ax, ay = self.define_rotate_angle(touch)
                
                self.roty.angle += ax
                self.rotx.angle += ay

            elif len(self._touches) == 2: # scaling here
                #use two touches to determine do we need scal
                touch1, touch2 = self._touches 
                old_pos1 = (touch1.x - touch1.dx, touch1.y - touch1.dy)
                old_pos2 = (touch2.x - touch2.dx, touch2.y - touch2.dy)
                
                old_dx = old_pos1[0] - old_pos2[0]
                old_dy = old_pos1[1] - old_pos2[1]
                
                old_distance = (old_dx*old_dx + old_dy*old_dy)
                Logger.debug('Old distance: %s' % old_distance)
                
                new_dx = touch1.x - touch2.x
                new_dy = touch1.y - touch2.y
                
                new_distance = (new_dx*new_dx + new_dy*new_dy)
                
                Logger.debug('New distance: %s' % new_distance)
                SCALE_FACTOR = 0.01
                
                if new_distance > old_distance: 
                    scale = SCALE_FACTOR
                    Logger.debug('Scale up')
                elif new_distance == old_distance:
                    scale = 0
                else:
                    scale = -1*SCALE_FACTOR
                    Logger.debug('Scale down')
                    
                xyz = self.scale.xyz
                
                if scale:
                    self.scale.xyz = tuple(p + scale for p in xyz)
Esempio n. 25
0
class Paint(StencilView):
    scale = NumericProperty()

    def __init__(self, app, **kwargs):
        StencilView.__init__(self, **kwargs)
        self.app = app
        self.xx = 0
        self.scale = 1.0
        self.size_hint = (None, None)
        self.cursor_pos = (0, 0)
        self.fbo_size = DEFAULT_IMAGE_SIZE
        self.fbo = None
        self.fbo_rect = None
        self.tool_fbo = None
        self.tool_fbo_rect = None
        self.bg_rect = None
        self.rect = None
        self.fbo_clear_color = (1, 1, 1, 1)
        self.layer_undo_stack = []
        self.undo_layer_index = 0
        self.layer_rect = []
        self.fbo_create_on_canvas()
        self.touches = []
        self.move_image = False
        self.active_layer = None
        self.tool_buffer_enabled = True
        self.px = None
        self.py = None
        self.grid_texture = None
        self.active_layer_last_texture = None

    def grid_create(self, size):
        self.grid_texture = Texture.create(size=size, colorfmt='rgba', bufferfmt='ubyte')
        tex = improc.texture_draw_grid(self.grid_texture, 255, 4)
        return tex

    def fbo_create(self, size, tex=None):
        if tex is None:
            tex = Texture.create(size=size, colorfmt='rgba', bufferfmt='ubyte')
            tex.mag_filter = 'nearest'
            tex.min_filter = 'nearest'
        if self.fbo is None:
            self.fbo = Fbo(size=size, texture=tex)
            self.fbo.texture.mag_filter = 'nearest'
            self.fbo.texture.min_filter = 'nearest'
        else:
            self.fbo = Fbo(size=size, texture=tex)
            self.fbo.texture.mag_filter = 'nearest'
            self.fbo.texture.min_filter = 'nearest'
        tool_tex = Texture.create(size=size, colorfmt='rgba', bufferfmt='ubyte')
        tool_tex.mag_filter = 'nearest'
        tool_tex.min_filter = 'nearest'
        if self.tool_fbo is None:
            self.tool_fbo = Fbo(size=size, texture=tool_tex)
            self.tool_fbo.texture.mag_filter = 'nearest'
            self.tool_fbo.texture.min_filter = 'nearest'
        else:
            self.tool_fbo = Fbo(size=size, texture=tool_tex)
            self.tool_fbo.texture.mag_filter = 'nearest'
            self.tool_fbo.texture.min_filter = 'nearest'
        return self.fbo

    def refbo(self):
        tex = Texture.create(size=self.fbo.texture.size, colorfmt='rgba', bufferfmt='ubyte')
        self.fbo = Fbo(size=tex.size, texture=tex)
        self.fbo.texture.mag_filter = 'nearest'
        self.fbo.texture.min_filter = 'nearest'
        self.fbo.draw()
        self.canvas.ask_update()

    def canvas_put_drawarea(self, texture=None):
        self.canvas.clear()
        if texture:
            self.fbo_size = texture.size
            self.fbo_create(texture.size, tex=texture)
        self.bg_rect = layer.Layer.layer_bg_rect
        with self.canvas:
            self.canvas.add(self.bg_rect)
            Color(1, 1, 1, 1)
            for laybox in layer.LayerBox.boxlist:
                if laybox.layer:
                    if laybox.layer.texture and laybox.layer.visible:
                        self.canvas.add(laybox.layer.rect)
                        laybox.layer.rect.pos = self.fbo_rect.pos

                if self.tool_buffer_enabled:
                    self.tool_fbo_rect = Rectangle(pos=self.fbo_rect.pos, size=self.tool_fbo.texture.size,
                                                   texture=self.tool_fbo.texture)
        self.fbo_update_pos()
        self.fbo.draw()
        self.canvas.ask_update()

    def fbo_create_on_canvas(self, size=None, pos=(0, 0)):
        self.canvas.clear()
        if size is None:
            size = self.fbo_size
        else:
            self.fbo_size = size
        self.fbo_create(size)
        with self.canvas:
            Color(1, 1, 1, 1)
            self.fbo_rect = Rectangle(texture=self.fbo.texture, pos=pos, size=self.fbo.texture.size)
            self.tool_fbo_rect = Rectangle(texture=self.tool_fbo.texture, pos=pos, size=self.tool_fbo.texture.size)
        self.fbo.draw()
        self.canvas.ask_update()


    def fbo_clear(self):
        self.fbo.bind()
        self.fbo.clear()
        self.fbo.clear_color = self.fbo_clear_color
        self.fbo.clear_buffer()
        self.fbo.release()
        self.fbo.draw()

    def fbo_update_pos(self):
        x = self.app.aPaintLayout.size[0] / self.scale / 2 - self.fbo.size[0] / 2
        y = self.app.aPaintLayout.size[1] / self.scale / 2 - self.fbo.size[1] / 2
        self.fbo_rect.pos = (x, y)
        self.tool_fbo_rect.pos = (x, y)
        if self.bg_rect:
            self.bg_rect.pos = (x, y)
        if self.app.layer_ribbon:
            for lb in layer.LayerBox.boxlist:
                if lb.layer.rect:
                    lb.layer.rect.pos = self.fbo_rect.pos

    def fbo_move_by_offset(self, offset):
        if self.bg_rect:
            self.bg_rect.pos = self.bg_rect.pos[0] + offset[0], self.bg_rect.pos[1] + offset[1]
            self.fbo_rect.pos = self.bg_rect.pos
            self.tool_fbo_rect.pos = self.bg_rect.pos
        if self.app.layer_ribbon:
            for lb in layer.LayerBox.boxlist:
                if lb.layer.rect:
                    lb.layer.rect.pos = self.fbo_rect.pos
        # self.ox, self.oy = self.bg_rect.pos
    #
    def fbo_render(self, touch, width):
        self.fbo.bind()
        if touch and touch.ud.has_key('line'):
            with self.fbo:
                self.fbo.add(self.app.aColor)
                d = width
                self.cursor_pos = ((touch.x - d / 2) / self.scale - self.fbo_rect.pos[0],
                                   (touch.y - d / 2) / self.scale - self.fbo_rect.pos[1])
                touch.ud['line'].points += self.cursor_pos
        self.fbo.release()
        self.fbo.draw()
        self.canvas.ask_update()

    def fbo_get_texture(self):
        return self.fbo.texture

    def fbo_get_pixel_color(self, touch, format='1'):
        self.fbo.bind()
        x = touch.x / self.scale - self.fbo_rect.pos[0]
        y = touch.y / self.scale - self.fbo_rect.pos[1]
        data = glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE)
        self.fbo.release()
        if format == '1':
            c = [ord(a) / 255.0 for a in data]
        else:
            c = [ord(a) for a in data]
        return c

    def fbo_fill_region(self, touch):
        x = int(touch.x / self.scale - self.fbo_rect.pos[0])
        y = int(touch.y / self.scale - self.fbo_rect.pos[1])
        improc.fillimage(self.fbo, (x, y), [int(255 * c) for c in self.app.aColor.rgba])
        self.canvas.ask_update()

    def fbo_replace_color(self, touch, width):
        cx = int(touch.x / self.scale - self.fbo_rect.pos[0])
        cy = int(touch.y / self.scale - self.fbo_rect.pos[1])
        if self.px is None:
            self.px = cx
        if self.py is None:
            self.py = cy
        if (cx - self.px) > 0:
            tg_alpha = float((cy - self.py)) / (cx - self.px)
            step = int(math.copysign(1, tg_alpha))
            if abs(cx - self.px) > abs(cy - self.py):
                coords = [(x, self.py + (x - self.px) * tg_alpha) for x in xrange(int(self.px), int(cx))]
            else:
                coords = [(self.px + (y - self.py) / tg_alpha, y) for y in xrange(int(self.py), int(cy), step)]
        elif (cx - self.px) < 0:
            tg_alpha = float((cy - self.py)) / (cx - self.px)
            step = int(math.copysign(1, tg_alpha))
            if abs(cx - self.px) > abs(cy - self.py):
                coords = [(x, self.py + (x - self.px) * tg_alpha) for x in xrange(int(cx), int(self.px))]
            else:
                coords = [(self.px + (y - self.py) / tg_alpha, y) for y in xrange(int(cy), int(self.py), step)]
        elif (cx - self.px) == 0:
            if (cy - self.py) > 0:
                coords = [(cx, y) for y in xrange(int(self.py), int(cy))]
            elif (cy - self.py) < 0:
                coords = [(cx, y) for y in xrange(int(cy), int(self.py))]
            else:
                coords = [(cx, cy), ]
        self.fbo.bind()
        for (x, y) in coords:
            improc.texture_replace_color(tex=self.fbo.texture, pos=(x, y), color=0, size=(width, width))
        self.fbo.release()
        self.fbo.clear()
        self.fbo.draw()
        self.canvas.ask_update()
        self.px = cx
        self.py = cy

    def pos_to_widget(self, touch):
        return self.to_widget(touch.x, touch.y)

    def scale_canvas(self, zoom):
        with self.canvas.before:
            PushMatrix()
            self.scale *= zoom
            context_instructions.Scale(zoom)
        with self.canvas.after:
            PopMatrix()
        self.fbo_update_pos()

    def on_scale(self, instance, scale):
        ToolBehavior.scale()

    def scale_pos(self, pos):
        return [pos[0] / self.scale - self.fbo_rect.pos[0],
                pos[1] / self.scale - self.fbo_rect.pos[1]]

    def scaled_pos(self):
        return [self.fbo_rect.pos[0] * self.scale,
                self.fbo_rect.pos[1] * self.scale]

    def scaled_size(self):
        return [self.fbo_rect.texture.size[0] * self.scale,
                self.fbo_rect.texture.size[1] * self.scale]

    def add_touch(self, touch):
        if touch and len(self.touches) < 2:
            self.touches.append(touch)
        if len(self.touches) >= 2:
            self.touch_dist = self.touches[0].distance(self.touches[1])
            self.touch_dist_const = self.touch_dist
            self.first_touch = self.touches[0]

    def double_touch(self):
        if len(self.touches) > 1:
            return True

    # def double_touch_distance(self):
    #     return Vector(self.touches[0].pos).distance(self.touches[1].pos)

    def touch_responce(self):
        result = False
        if len(self.touches) >= 2:
            pos1 = self.pos_to_widget(self.touches[0])
            pos2 = self.touches[1].pos
            dist = distance(pos1, pos2)
            if dist > self.touch_dist + 10:
                self.touch_dist = dist
                result = 2
            elif dist <= self.touch_dist - 10:
                self.touch_dist = dist
                result = 1
            if abs(self.touch_dist_const - dist) < 10:
                result = 3
            return result
        return False

    def on_touch_down(self, touch):
        self.tool_buffer.on_touch_down(touch)

        if self.collide_point(*touch.pos):
            if self.app.config.getint('toolbars', 'toolbar_autohide'):
                self.app.toolbar.animate_hide()
            if self.app.config.getint('toolbars', 'palette_autohide'):
                self.app.palette.animate_hide()
            if self.app.config.getint('toolbars', 'layer_ribbon_autohide'):
                self.app.layer_ribbon.animate_hide()

        if not self.collide_point(*touch.pos):
            if self.app.active_tool == TOOL_LINE:
                self.tool_line._render_and_reset_state(self.fbo, self.tool_fbo)
                self.fbo.draw()
                self.canvas.ask_update()

            return False

        touch.grab(self)

        self.add_touch(touch)

        if len(self.touches) == 1:
            self.active_layer_backup_texture()

        if self.double_touch():
            self.active_layer_set_last_backup_texture()
            return

        if not self.app.layer_ribbon.get_active_layer().visible:
            dialog.PopupMessage("Notification", "The current layer is hidden, make it visible for edit")
            return
        if self.app.layer_ribbon.get_active_layer().texture_locked:
            dialog.PopupMessage("Notification", "The current layer is locked, make it unlock for edit")
            return

        if self.app.active_tool == TOOL_PENCIL1:
            self.fbo.bind()
            if touch:
                with self.fbo:
                    self.fbo.add(self.app.aColor)
                    d = 1.
                    self.cursor_pos = ((touch.x - d / 2) / self.scale - self.fbo_rect.pos[0],
                                       (touch.y - d / 2) / self.scale - self.fbo_rect.pos[1])
                    Ellipse(pos=self.cursor_pos, size=(d, d))
                    touch.ud['line'] = Line(points=self.cursor_pos, width=d)
            self.fbo.release()
            self.fbo.draw()
            self.canvas.ask_update()
        elif self.app.active_tool == TOOL_PENCIL2:
            self.fbo.bind()
            if touch:
                with self.fbo:
                    self.fbo.add(self.app.aColor)
                    d = 2.1
                    self.cursor_pos = ((touch.x - d / 2) / self.scale - self.fbo_rect.pos[0],
                                       (touch.y - d / 2) / self.scale - self.fbo_rect.pos[1])
                    Ellipse(pos=self.cursor_pos, size=(d, d))
                    touch.ud['line'] = Line(points=self.cursor_pos, width=d / 2.0)
            self.fbo.release()
            self.fbo.draw()
            self.canvas.ask_update()
        elif self.app.active_tool == TOOL_PENCIL3:
            self.fbo.bind()
            if touch:
                with self.fbo:
                    self.fbo.add(self.app.aColor)
                    d = 3.
                    self.cursor_pos = ((touch.x - d / 2) / self.scale - self.fbo_rect.pos[0],
                                       (touch.y - d / 2) / self.scale - self.fbo_rect.pos[1])
                    Ellipse(pos=self.cursor_pos, size=(d, d))
                    touch.ud['line'] = Line(points=self.cursor_pos, width=d / 2)
            self.fbo.release()
            self.fbo.draw()
            self.canvas.ask_update()
        elif self.app.active_tool == TOOL_PICKER:
            if touch:
                if self.collide_point(touch.x, touch.y):
                    c = self.fbo_get_pixel_color(touch)
                    self.app.aColor = Color(c[0], c[1], c[2], c[3])
                    self.app.toolbar.tools_select(self.app.prev_tool)
        elif self.app.active_tool == TOOL_FILL:
            if touch:
                if self.collide_point(touch.x, touch.y):
                    self.fbo_fill_region(touch)
        elif self.app.active_tool == TOOL_ERASE1:
            if touch:
                if self.collide_point(touch.x, touch.y):
                    self.fbo_replace_color(touch, width=1)
        elif self.app.active_tool == TOOL_ERASE2:
            if touch:
                if self.collide_point(touch.x, touch.y):
                    self.fbo_replace_color(touch, width=2)
        elif self.app.active_tool == TOOL_ERASE3:
            if touch:
                if self.collide_point(touch.x, touch.y):
                    self.fbo_replace_color(touch, width=3)
        elif self.app.active_tool == TOOL_SELECT:
            if touch:
                if not self.tool_buffer.enabled:
                    self.tool_select.on_touch_down(touch, self.fbo, self.tool_fbo)
                else:
                    pass
        elif self.app.active_tool == TOOL_LINE:
            if touch:
                self.tool_line.on_touch_down(touch, self.fbo, self.tool_fbo)
            self.fbo.draw()
            self.canvas.ask_update()
        elif self.app.active_tool == TOOL_RECT:
            if touch:
                self.tool_rect.on_touch_down(touch, self.fbo, self.tool_fbo)
            self.fbo.draw()
            self.canvas.ask_update()
        elif self.app.active_tool == TOOL_ELLIPSE:
            if touch:
                self.tool_ellipse.on_touch_down(touch, self.fbo, self.tool_fbo)
            self.fbo.draw()
            self.canvas.ask_update()
        elif self.app.active_tool == TOOL_MOVE:
            if touch:
                if self.collide_point(touch.x, touch.y):
                    self.move_image = True
                    self.ox, self.oy = touch.pos
        return True

    def on_touch_move(self, touch):
        result = self.touch_responce()
        if result == 2:
            self.scale_canvas(1.02)
            return
        elif result == 1:
            self.scale_canvas(0.98)
            return
        elif result == 3:
            dist = self.touches[0].distance(self.first_touch)
            self.fbo_move_by_offset((dist / self.scale, dist / self.scale))

        if self.app.active_tool == TOOL_PENCIL1:
            self.fbo_render(touch, width=1.)
        elif self.app.active_tool == TOOL_PENCIL2:
            self.fbo_render(touch, width=2.)
        elif self.app.active_tool == TOOL_PENCIL3:
            self.fbo_render(touch, width=3.)
        elif self.app.active_tool == TOOL_PICKER:
            c = self.fbo_get_pixel_color(touch)
            self.app.aColor = Color(c[0], c[1], c[2])
        elif self.app.active_tool == TOOL_ERASE1:
            if touch:
                if self.collide_point(touch.x, touch.y):
                    self.fbo_replace_color(touch, width=1)
        elif self.app.active_tool == TOOL_ERASE2:
            if touch:
                if self.collide_point(touch.x, touch.y):
                    self.fbo_replace_color(touch, width=2)
        elif self.app.active_tool == TOOL_ERASE3:
            if touch:
                if self.collide_point(touch.x, touch.y):
                    self.fbo_replace_color(touch, width=3)
        elif self.app.active_tool == TOOL_SELECT:
            if touch:
                if not self.tool_buffer.enabled:
                    self.tool_select.on_touch_move(touch, self.tool_fbo)
                    self.fbo.draw()
                    self.canvas.ask_update()
                else:
                    pass

        elif self.app.active_tool == TOOL_LINE:
            if touch:
                self.tool_line.on_touch_move(touch, self.tool_fbo)
            self.fbo.draw()
            self.canvas.ask_update()
        elif self.app.active_tool == TOOL_RECT:
            if touch:
                self.tool_rect.on_touch_move(touch, self.tool_fbo)
            self.fbo.draw()
            self.canvas.ask_update()
        elif self.app.active_tool == TOOL_ELLIPSE:
            if touch:
                self.tool_ellipse.on_touch_move(touch, self.tool_fbo)
            self.fbo.draw()
            self.canvas.ask_update()
        elif self.app.active_tool == TOOL_MOVE:
            if self.move_image:
                self.fbo_move_by_offset((touch.dx / self.scale, touch.dy / self.scale))
        self.tool_buffer.on_touch_move(touch, self.fbo)

    def on_touch_up(self, touch):
        self.tool_buffer.on_touch_up(touch)
        if touch.grab_current is not self:
            return False
        if not self.collide_point(*touch.pos):
            return False
        touch.ungrab(self)

        if self.double_touch():
            _not_add_too_undo = True
        else:
            _not_add_too_undo = False

        if touch:
            try:
                self.touches.remove(touch)
            except:
                pass
            if self.app.active_tool == TOOL_SELECT:
                if touch:
                    self.tool_select.on_touch_up(touch)
                self.fbo.draw()
                self.canvas.ask_update()
            elif self.app.active_tool == TOOL_LINE:
                if touch:
                    self.tool_line.on_touch_up(touch)
                self.fbo.draw()
                self.canvas.ask_update()
            elif self.app.active_tool == TOOL_RECT:
                if touch:
                    self.tool_rect.on_touch_up(touch)
                self.fbo.draw()
                self.canvas.ask_update()
            elif self.app.active_tool == TOOL_ELLIPSE:
                if touch:
                    self.tool_ellipse.on_touch_up(touch)
                self.fbo.draw()
                self.canvas.ask_update()
            elif self.app.active_tool == TOOL_MOVE:
                if touch:
                    self.move_image = False
            elif self.app.active_tool == TOOL_ERASE1 or self.app.active_tool == TOOL_ERASE2 or self.app.active_tool == TOOL_ERASE3:
                if touch:
                    self.px = None
                    self.py = None
            if self.app.active_tool == TOOL_PENCIL1 or self.app.active_tool == TOOL_ERASE1 \
                    or self.app.active_tool == TOOL_PENCIL2 or self.app.active_tool == TOOL_ERASE2 \
                    or self.app.active_tool == TOOL_PENCIL3 or self.app.active_tool == TOOL_ERASE3 \
                    or self.app.active_tool == TOOL_FILL:
                rect = self.app.layer_ribbon.get_active_layer().rect
                pos = rect.pos[0] * self.scale, rect.pos[1] * self.scale
                size = rect.size[0] * self.scale, rect.size[1] * self.scale
                if not _not_add_too_undo:
                    if pos[0] <= touch.x <= pos[0] + size[0] and pos[1] <= touch.y <= pos[1] + size[1]:
                        self.add_undo_stack()
        return True

    def add_redo_stack(self):
        pass

    def add_undo_stack(self):
        _active_layer = self.app.layer_ribbon.get_active_layer()
        _active_layer.backup_texture()
        self.layer_undo_stack = self.layer_undo_stack[:self.undo_layer_index + 1]
        self.layer_undo_stack.append(_active_layer)
        self.undo_layer_index = len(self.layer_undo_stack) - 1

    def do_undo(self, *args):
        if self.layer_undo_stack:
            if self.undo_layer_index > 0:
                _layer = self.layer_undo_stack[self.undo_layer_index]
                _layer.texture_from_backup(direction=-1)
                _active_layer = self.app.layer_ribbon.get_active_layer()
                if _layer is _active_layer:
                    self.fbo_create(_active_layer.texture.size, _active_layer.texture)
                self.undo_layer_index -= 1
                self.canvas_put_drawarea()
            self.fbo_update_pos()

    def active_layer_backup_texture(self):
        active_layer = self.app.layer_ribbon.get_active_layer()
        self.active_layer_last_texture = improc.texture_copy(active_layer.texture)

    def active_layer_set_last_backup_texture(self):
        active_layer = self.app.layer_ribbon.get_active_layer()
        # texture = active_layer.textures_array[-1]
        active_layer.replace_texture(self.active_layer_last_texture)

        self.fbo_create(active_layer.texture.size, active_layer.texture)

        self.canvas_put_drawarea()
        self.fbo_update_pos()
        self.canvas.ask_update()

    def do_redo(self, *args):
        if self.layer_undo_stack:
            if self.undo_layer_index < len(self.layer_undo_stack) - 1:
                self.undo_layer_index += 1
                _layer = self.layer_undo_stack[self.undo_layer_index]
                _layer.texture_from_backup(direction=1)
                _active_layer = self.app.layer_ribbon.get_active_layer()
                if _layer is _active_layer:
                    self.fbo_create(_active_layer.texture.size, _active_layer.texture)
                self.canvas_put_drawarea()
            self.fbo_update_pos()
Esempio n. 26
0
class EffectWidget(RelativeLayout):
    '''
    Widget with the ability to apply a series of graphical effects to
    its children. See the module documentation for more information on
    setting effects and creating your own.
    '''

    background_color = ListProperty((0, 0, 0, 0))
    '''This defines the background color to be used for the fbo in the
    EffectWidget.

    :attr:`background_color` is a :class:`ListProperty` defaults to
    (0, 0, 0, 0)
    '''

    texture = ObjectProperty(None)
    '''The output texture of the final :class:`~kivy.graphics.Fbo` after
    all effects have been applied.

    texture is an :class:`~kivy.properties.ObjectProperty` and defaults
    to None.
    '''

    effects = ListProperty([])
    '''List of all the effects to be applied. These should all be
    instances or subclasses of :class:`EffectBase`.

    effects is a :class:`ListProperty` and defaults to [].
    '''

    fbo_list = ListProperty([])
    '''(internal) List of all the fbos that are being used to apply
    the effects.

    fbo_list is a :class:`ListProperty` and defaults to [].
    '''

    _bound_effects = ListProperty([])
    '''(internal) List of effect classes that have been given an fbo to
    manage. This is necessary so that the fbo can be removed if the
    effect is no longer in use.

    _bound_effects is a :class:`ListProperty` and defaults to [].
    '''
    def __init__(self, **kwargs):
        # Make sure opengl context exists
        EventLoop.ensure_window()

        self.canvas = RenderContext(use_parent_projection=True,
                                    use_parent_modelview=True)
        self._callbacks = {}

        with self.canvas:
            self.fbo = Fbo(size=self.size)

        with self.fbo.before:  # noqa
            PushMatrix()
        with self.fbo:
            ClearColor(0, 0, 0, 0)
            ClearBuffers()
            self._background_color = Color(*self.background_color)
            self.fbo_rectangle = Rectangle(size=self.size)
        with self.fbo.after:  # noqa
            PopMatrix()

        super(EffectWidget, self).__init__(**kwargs)

        fbind = self.fbind
        fbo_setup = self.refresh_fbo_setup
        fbind('size', fbo_setup)
        fbind('effects', fbo_setup)
        fbind('background_color', self._refresh_background_color)

        self.refresh_fbo_setup()
        self._refresh_background_color()  # In case thi was changed in kwargs

    def _refresh_background_color(self, *args):  # noqa
        self._background_color.rgba = self.background_color

    def _propagate_updates(self, *largs):
        """Propagate updates from widgets."""
        del largs
        for fbo in self.fbo_list:
            fbo.ask_update()

    def refresh_fbo_setup(self, *args):  # noqa
        '''(internal) Creates and assigns one :class:`~kivy.graphics.Fbo`
        per effect, and makes sure all sizes etc. are correct and
        consistent.
        '''
        # Add/remove fbos until there is one per effect
        while len(self.fbo_list) < len(self.effects):
            with self.canvas:
                new_fbo = EffectFbo(size=self.size)
            with new_fbo:
                ClearColor(0, 0, 0, 0)
                ClearBuffers()
                Color(1, 1, 1, 1)
                new_fbo.texture_rectangle = Rectangle(size=self.size)

                new_fbo.texture_rectangle.size = self.size
            self.fbo_list.append(new_fbo)
        while len(self.fbo_list) > len(self.effects):
            old_fbo = self.fbo_list.pop()
            self.canvas.remove(old_fbo)

        # Remove fbos from unused effects
        for effect in self._bound_effects:
            if effect not in self.effects:
                effect.fbo = None
        self._bound_effects = self.effects

        # Do resizing etc.
        self.fbo.size = self.size
        self.fbo_rectangle.size = self.size
        for i in range(len(self.fbo_list)):
            self.fbo_list[i].size = self.size
            self.fbo_list[i].texture_rectangle.size = self.size

        # If there are no effects, just draw our main fbo
        if len(self.fbo_list) == 0:  # noqa
            self.texture = self.fbo.texture
            return

        for i in range(1, len(self.fbo_list)):
            fbo = self.fbo_list[i]
            fbo.texture_rectangle.texture = self.fbo_list[i - 1].texture

        # Build effect shaders
        for effect, fbo in zip(self.effects, self.fbo_list):
            effect.fbo = fbo

        self.fbo_list[0].texture_rectangle.texture = self.fbo.texture
        self.texture = self.fbo_list[-1].texture

        for fbo in self.fbo_list:
            fbo.draw()
        self.fbo.draw()

    def add_widget(self, widget):  # noqa
        # Add the widget to our Fbo instead of the normal canvas
        c = self.canvas
        self.canvas = self.fbo
        with widget.canvas:
            self._callbacks[widget.canvas] = Callback(self._propagate_updates)
        super(EffectWidget, self).add_widget(widget)
        self.canvas = c

    def remove_widget(self, widget):
        # Remove the widget from our Fbo instead of the normal canvas
        c = self.canvas
        widget.canvas.remove(self._callbacks[widget.canvas])
        del self._callbacks[widget.canvas]
        self.canvas = self.fbo
        super(EffectWidget, self).remove_widget(widget)
        self.canvas = c

    def clear_widgets(self, children=None):
        # Clear widgets from our Fbo instead of the normal canvas
        c = self.canvas
        self.canvas = self.fbo
        for canvas, callback in self._callbacks.items():
            canvas.remove(callback)
        self._callbacks = {}

        super(EffectWidget, self).clear_widgets(children)
        self.canvas = c
Esempio n. 27
0
        def count_it(num):
            if num == 0:
                fbo = Fbo(size=self.stencil.size, with_stencilbuffer=True)

                with fbo:
                    ClearColor(1, 1, 1, 0)
                    ClearBuffers()
                    img2 = self.paintscreen.bg.texture
                    fbo.add(self.stencil.canvas)
                    fbo.draw()
                    img = fbo.texture
                    fbo.remove(self.stencil.canvas)
                    self.remove_widget(self.paintscreen)
                    im = np.frombuffer(img.pixels, np.uint8)
                    data = np.reshape(im, (im.shape[0], 1)).tostring()

                    data2 = str(data)
                    data2 = str.encode(data2)

                    pix = np.frombuffer(data, np.uint8)
                    a = np.empty_like(pix)
                    a[:] = pix
                    texture = Texture.create(size=self.stencil.size)

                    texture.blit_buffer(a, colorfmt='rgba', bufferfmt='ubyte')
                    self.imge = Image(pos=(0, 0),
                                      size=self.paintscreen.stencil.size,
                                      texture=texture)
                    #self.paintscreen.stencil.add_widget(self.imge)

                    #img2 = self.paintscreen.grid_layout.bg.texture
                    im2 = np.frombuffer(img2.pixels, np.uint8)
                    data = np.reshape(im2, (im2.shape[0], 1)).tostring()

                    data2 = str(data)
                    data2 = str.encode(data2)

                    pix = np.frombuffer(data, np.uint8)
                    a2 = np.empty_like(pix)
                    a2[:] = pix

                    img2 = a2
                    print(img2.shape)

                    print(img2)
                    img1 = a
                    print(img1.shape)

                    import cv2
                    #setting alpha=1, beta=1, gamma=0 gives direct overlay of two images
                    # in theory this would give a direct overlay...
                    #img3 = cv2.addWeighted(img1, 1, img2, 1, 0)
                    #print(img3.shape)

                    im = img1.reshape(1200, 1200, 4)
                    # for i in range(0, 1200):
                    #     for j in range(0,1200):
                    #         points = im[i,j,:]
                    #         if (points[3] == 0):#points[0] == 255 & points[1] == 255 & points[2] == 255):
                    #             im[i,j,:] = [255,255,255,0]
                    img_2 = img2.reshape((1200, 1200, 4))
                    for i in range(0, 1200):
                        for j in range(0, 1200):
                            points1 = im[i, j, :]
                            if (points1[3] != 0):
                                img_2[i, j, :] = im[i, j, :]

                    socket_client.send(img_2)

                    while MESSAGE is None:
                        pass
                    if MESSAGE is not None:
                        new_img = MESSAGE
                    else:
                        new_img = img_2

                    texture = Texture.create(size=(1200, 1200))

                    texture.blit_buffer(np.reshape(new_img,
                                                   (1200 * 1200 * 4, )),
                                        colorfmt='rgba',
                                        bufferfmt='ubyte')

                    self.paintscreen = PaintScreen()
                    self.add_widget(self.paintscreen)
                    self.paintscreen.bg.texture = texture
                return
            num -= 1
            self.count.text = str(num)
            Clock.schedule_once(lambda dt: count_it(num), 1)
Esempio n. 28
0
    def generate_movie(
            self, filename, out_fmt='yuv420p', codec='libx264',
            lib_opts={'crf': '0'}, video_fmt='mp4', start=None, end=None,
            canvas_size=(0, 0),
            canvas_size_hint=(1, 1), projector_pos=(0, 0),
            projector_pos_hint=(None, None), paint_funcs=(),
            stimulation_transparency=1., lum=1., speed=1.):
        from kivy.graphics import (
            Canvas, Translate, Fbo, ClearColor, ClearBuffers, Scale)
        from kivy.core.window import Window

        rate = float(self.view_controller.frame_rate)
        rate_int = int(rate)
        if rate != rate_int:
            raise ValueError('Frame rate should be integer')
        orig_w, orig_h = (
            self.view_controller.screen_width,
            self.view_controller.screen_height)

        canvas_w, canvas_h = canvas_size
        cv_hint_w, cv_hint_h = canvas_size_hint
        w = int(canvas_w if cv_hint_w is None else orig_w * cv_hint_w)
        h = int(canvas_h if cv_hint_h is None else orig_h * cv_hint_h)

        projector_x, projector_y = projector_pos
        projector_hint_x, projector_hint_y = projector_pos_hint
        x = int(projector_x if projector_hint_x is None else
                orig_w * projector_hint_x)
        y = int(projector_y if projector_hint_y is None else
                orig_h * projector_hint_y)

        Window.size = w, h
        intensities = self.shapes_intensity

        n = len(intensities[next(iter(intensities.keys()))])
        if start is not None:
            start = int(start * rate)
            if start >= n:
                raise Exception('Start time is after the end of the data')
        else:
            start = 0

        if end is not None:
            end = int(math.ceil(end * rate)) + 1
            if end <= start:
                raise Exception('End time is before or at the start time')
        else:
            end = n

        stream = {
            'pix_fmt_in': 'rgba', 'pix_fmt_out': out_fmt,
            'width_in': w, 'height_in': h, 'width_out': w,
            'height_out': h, 'codec': codec,
            'frame_rate': (int(speed * rate_int), 1)}
        writer = MediaWriter(
            filename, [stream], fmt=video_fmt, lib_opts=lib_opts)

        fbo = Fbo(size=(w, h), with_stencilbuffer=True)
        with fbo:
            ClearColor(0, 0, 0, 1)
            ClearBuffers()
            Scale(1, -1, 1)
            Translate(0, -h, 0)

        config = {'canvas': fbo, 'pos': (x, y), 'size': (w, h),
                  'orig_size': (orig_w, orig_h), 'rate': rate}
        paint_funcs = [func(config) for func in paint_funcs]
        paint_funcs = [func for func in paint_funcs if func is not None]

        fbo.draw()
        img = Image(plane_buffers=[fbo.pixels], pix_fmt='rgba', size=(w, h))
        writer.write_frame(img, 0.)

        fbo.add(Translate(x, y))
        shape_views = self.stage_factory.get_shapes_gl_color_instructions(
            fbo, 'stage_replay')
        fbo.add(Translate(-x, -y))

        pbar = tqdm(
            total=(end - 1 - start) / rate, file=sys.stdout, unit='second',
            unit_scale=1)
        for i in range(start, end):
            pbar.update(1 / rate)
            for name, intensity in intensities.items():
                r, g, b, a = intensity[i]
                if not r and not g and not b:
                    a = 0
                shape_views[name].rgba = \
                    r * lum, g * lum, b * lum, a * stimulation_transparency

            try:
                for func in paint_funcs:
                    func(i)
            except EndOfDataException:
                break

            fbo.draw()
            img = Image(plane_buffers=[fbo.pixels], pix_fmt='rgba', size=(w, h))
            writer.write_frame(img, (i - start + 1) / (rate * speed))
        pbar.close()