diff --git a/kivy/data/glsl/default.vs b/kivy/data/glsl/default.vs index 62f2f1690..ac9ac4d6d 100644 --- a/kivy/data/glsl/default.vs +++ b/kivy/data/glsl/default.vs @@ -1,6 +1,6 @@ $HEADER$ void main (void) { - frag_color = color; + frag_color = color * vec4(1.0, 1.0, 1.0, opacity); tex_coord0 = vTexCoords0; gl_Position = projection_mat * modelview_mat * vec4(vPosition.xy, 0.0, 1.0); } diff --git a/kivy/data/glsl/header.vs b/kivy/data/glsl/header.vs index ef00fcf35..a2638bffc 100644 --- a/kivy/data/glsl/header.vs +++ b/kivy/data/glsl/header.vs @@ -14,3 +14,4 @@ attribute vec2 vTexCoords0; uniform mat4 modelview_mat; uniform mat4 projection_mat; uniform vec4 color; +uniform float opacity; diff --git a/kivy/graphics/instructions.pxd b/kivy/graphics/instructions.pxd index 1bda49dfe..fe90ae929 100644 --- a/kivy/graphics/instructions.pxd +++ b/kivy/graphics/instructions.pxd @@ -82,6 +82,7 @@ cdef class CanvasBase(InstructionGroup): cdef class Canvas(CanvasBase): cdef object __weakref__ + cdef float _opacity cdef CanvasBase _before cdef CanvasBase _after cdef void reload(self) @@ -89,6 +90,7 @@ cdef class Canvas(CanvasBase): cpdef add(self, Instruction c) cpdef remove(self, Instruction c) cpdef draw(self) + cdef void apply(self) cdef class RenderContext(Canvas): diff --git a/kivy/graphics/instructions.pyx b/kivy/graphics/instructions.pyx index acaacc0e6..10e8ca3ba 100644 --- a/kivy/graphics/instructions.pyx +++ b/kivy/graphics/instructions.pyx @@ -499,6 +499,7 @@ cdef class Canvas(CanvasBase): def __init__(self, **kwargs): get_context().register_canvas(self) CanvasBase.__init__(self, **kwargs) + self._opacity = kwargs.get('opacity', 1.0) self._before = None self._after = None @@ -530,6 +531,19 @@ cdef class Canvas(CanvasBase): ''' self.apply() + cdef void apply(self): + cdef float opacity = self._opacity + cdef float rc_opacity + cdef RenderContext rc + if opacity != 1.0: + rc = getActiveContext() + rc_opacity = rc['opacity'] + rc.push_state('opacity') + rc['opacity'] = rc_opacity * opacity + InstructionGroup.apply(self) + if opacity != 1.0: + rc.pop_state('opacity') + cpdef add(self, Instruction c): # the after group must remain the last one. if self._after is None: @@ -569,6 +583,30 @@ cdef class Canvas(CanvasBase): self._after = c return self._after + property opacity: + '''Property for get/set the opacity value of the canvas. + + .. versionadded:: 1.4.1 + + The opacity attribute controls the opacity of the canvas and its + children. Be careful, it's a cumulative attribute: the value is + multiplied to the current global opacity, and the result is applied to + the current context color. + + For example: if your parent have an opacity of 0.5, and one children have an + opacity of 0.2, the real opacity of the children will be 0.5 * 0.2 = 0.1. + + Then, the opacity is applied on the shader as:: + + frag_color = color * vec4(1.0, 1.0, 1.0, opacity); + + ''' + def __get__(self): + return self._opacity + def __set__(self, value): + self._opacity = value + self.flag_update() + # Active Canvas and getActiveCanvas function is used # by instructions, so they know which canvas to add # tehmselves to @@ -629,8 +667,8 @@ cdef class RenderContext(Canvas): self.default_texture = tex self.state_stacks = { + 'opacity': [1.0], 'texture0' : [0], - 'linewidth': [1.0], 'color' : [[1.0,1.0,1.0,1.0]], 'projection_mat': [Matrix()], 'modelview_mat' : [Matrix()], diff --git a/kivy/uix/widget.py b/kivy/uix/widget.py index bb4a582ea..f06dd326f 100644 --- a/kivy/uix/widget.py +++ b/kivy/uix/widget.py @@ -532,6 +532,30 @@ class Widget(EventDispatcher): dict. ''' + opacity = NumericProperty(1.0) + '''Opacity of the widget and all the children. + + .. versionadded:: 1.4.1 + + The opacity attribute controls the opacity of the widget and its children. + Be careful, it's a cumulative attribute: the value is multiplied to the + current global opacity, and the result is applied to the current context + color. + + For example: if your parent have an opacity of 0.5, and one children have an + opacity of 0.2, the real opacity of the children will be 0.5 * 0.2 = 0.1. + + Then, the opacity is applied on the shader as:: + + frag_color = color * vec4(1.0, 1.0, 1.0, opacity); + + :data:`opacity` is a :class:`~kivy.properties.NumericProperty`, default to + 1.0. + ''' + + def on_opacity(self, instance, value): + self.canvas.opacity = value + canvas = None '''Canvas of the widget.