1: import clutter
2: import gtk
3: import math
4: import os
5:
6: class BehaviourHighlight(clutter.Behaviour):
7:
8: __gtype_name__ = 'BehaviourHighlight'
9:
10: def __init__(self, alpha):
11: clutter.Behaviour.__init__(self)
12: self.set_alpha(alpha)
13: self.bulge_angle = 90
14: self.bulge_min = 67.5
15: self.bulge_max = 112.5
16: self.interval = self.bulge_max - self.bulge_min
17: self.fraction = 180.0 / self.interval
18:
19: def do_alpha_notify (self, alpha_value):
20: for actor in self.get_actors():
21: if self.bulge_min <= actor.angle <= self.bulge_max:
22: actor.set_opacity(int(255 * math.sin(math.radians((actor.angle - self.bulge_min) * self.fraction))))
23: elif self.bulge_min - 360 <= actor.angle <= self.bulge_max - 360:
24: actor.set_opacity(int(255 * math.sin(math.radians((actor.angle - (self.bulge_min - 360)) * self.fraction))))
25: else:
26: actor.set_opacity(0)
27:
28:
29: class BehaviourTurn(clutter.Behaviour):
30:
31: __gtype_name__ = 'BehaviourTurn'
32:
33: def __init__(self, alpha):
34: clutter.Behaviour.__init__(self)
35: self.set_alpha(alpha)
36:
37: def do_alpha_notify(self, alpha_value):
38: for actor in self.get_actors():
39: actor.set_rotation(clutter.Z_AXIS, actor.get_rotation(clutter.Z_AXIS)[0] + 1, (actor.get_width() / 2), (actor.get_height() / 2), 0)
40:
41:
42: class BehaviourSpin(clutter.Behaviour):
43:
44: __gtype_name__ = 'BehaviourSpin'
45:
46: def __init__(self, alpha, direction = "clockwise", items = 1, item_number = 1):
47: clutter.Behaviour.__init__(self)
48: self.set_alpha(alpha) # Apply the animation step to follow
49: self.direction = direction # Remember which way around to go
50: self.bulge_angle = 90 # The angle at which we should be bigger
51: self.bulge_min = 67.5 # The angles at which to start/end growing
52: self.bulge_max = 112.5
53: # The start and end angles tell us how fast to move around the ellipse
54: # ie. the angle until the next stop
55: if direction == "clockwise":
56: self.angle_start = self.bulge_angle + (360.0 / items) * item_number
57: self.angle_end = 360.0 + self.bulge_angle + (360.0 / items) * item_number
58: else:
59: self.angle_start = 360.0 + self.bulge_angle - (360.0 / items) * item_number
60: self.angle_end = self.bulge_angle - (360.0 / items) * item_number
61: self.angle = self.angle_start
62: self.width = 500.0
63: self.height = 75.0
64: self.tilt = -10.0
65: self.items = items
66: self.item_number = item_number
67: self.phase = 0.0 # Initial value to compare first alpha with
68:
69: def apply(self, actor):
70: """This sets the start position when the behaviour is applied"""
71: clutter.Behaviour.apply(self, actor)
72: actor.angle = self.angle # Store the angle around the ellipse inside the actor so every behaviour on the actor is in sync
73: # Set default positions and size
74: actor.set_position(int(self.x_position(actor.angle)), int(self.y_position(actor.angle)))
75: actor.set_scale(math.cos(math.radians((actor.angle / 2) - 45))**2 + 0.25, math.cos(math.radians((actor.angle / 2) - 45))**2 + 0.25)
76: if self.bulge_min <= actor.angle <= self.bulge_angle:
77: actor.set_scale(math.cos(math.radians((actor.angle / 2) - 45))**2 + 0.25 + (actor.angle - self.bulge_min) / (self.bulge_angle - self.bulge_min), math.cos(math.radians((actor.angle / 2) - 45))**2 + 0.25 + (actor.angle - self.bulge_min) / (self.bulge_angle - self.bulge_min))
78: elif self.bulge_angle < actor.angle <= self.bulge_max:
79: actor.set_scale(math.cos(math.radians((actor.angle / 2) - 45))**2 + 0.25 - (actor.angle - self.bulge_max) / (self.bulge_max - self.bulge_angle), math.cos(math.radians((actor.angle / 2) - 45))**2 + 0.25 - (actor.angle - self.bulge_max) / (self.bulge_max - self.bulge_angle))
80:
81:
82: def x_position(self, angle):
83: return self.width * math.cos(math.radians(angle)) * math.cos(math.radians(self.tilt)) - self.height * math.sin(math.radians(angle)) * math.sin(math.radians(self.tilt)) + 275
84:
85: def y_position(self, angle):
86: return self.width * math.cos(math.radians(angle)) * math.sin(math.radians(self.tilt)) + self.height * math.sin(math.radians(angle)) * math.cos(math.radians(self.tilt)) + 200
87:
88: def do_alpha_notify (self, alpha_value):
89: phase = (alpha_value + 0.0) / (clutter.MAX_ALPHA + 0.0)
90: delta = self.phase - phase
91: self.phase = phase
92: increment = delta * (((self.angle_end - self.angle_start) / self.items))
93:
94: for actor in self.get_actors():
95: if abs(increment) <= abs(((self.angle_end - self.angle_start) / self.items) / 2):
96: actor.angle += increment
97: if actor.angle > 360:
98: actor.angle -= 360
99: elif actor.angle < -360:
100: actor.angle += 360
101: actor.set_position(int(self.x_position(actor.angle)), int(self.y_position(actor.angle)))
102: actor.set_scale(math.cos(math.radians((actor.angle / 2) - 45))**2 + 0.25, math.cos(math.radians((actor.angle / 2) - 45))**2 + 0.25)
103: if self.bulge_min < actor.angle < self.bulge_max:
104: if self.bulge_min <= actor.angle <= self.bulge_angle:
105: actor.set_scale(math.cos(math.radians((actor.angle / 2) - 45))**2 + 0.25 + (actor.angle - self.bulge_min) / (self.bulge_angle - self.bulge_min), math.cos(math.radians((actor.angle / 2) - 45))**2 + 0.25 + (actor.angle - self.bulge_min) / (self.bulge_angle - self.bulge_min))
106: elif self.bulge_angle < actor.angle <= self.bulge_max:
107: actor.set_scale(math.cos(math.radians((actor.angle / 2) - 45))**2 + 0.25 - (actor.angle - self.bulge_max) / (self.bulge_max - self.bulge_angle), math.cos(math.radians((actor.angle / 2) - 45))**2 + 0.25 - (actor.angle - self.bulge_max) / (self.bulge_max - self.bulge_angle))
108: elif self.bulge_min - 360 < actor.angle < self.bulge_max - 360:
109: if self.bulge_min - 360 <= actor.angle <= self.bulge_angle - 360:
110: actor.set_scale(math.cos(math.radians((actor.angle / 2) - 45))**2 + 0.25 + (actor.angle - (self.bulge_min - 360)) / (self.bulge_angle - self.bulge_min), math.cos(math.radians((actor.angle / 2) - 45))**2 + 0.25 + (actor.angle - (self.bulge_min - 360)) / (self.bulge_angle - self.bulge_min))
111: elif self.bulge_angle - 360 < actor.angle <= self.bulge_max - 360:
112: actor.set_scale(math.cos(math.radians((actor.angle / 2) - 45))**2 + 0.25 - (actor.angle - (self.bulge_max - 360)) / (self.bulge_max - self.bulge_angle), math.cos(math.radians((actor.angle / 2) - 45))**2 + 0.25 - (actor.angle - (self.bulge_max - 360)) / (self.bulge_max - self.bulge_angle))
113:
114:
115: class ClutterDisplay:
116:
117: def __init__(self, (size_x, size_y), background, timelines):
118: self.x = size_x
119: self.y = size_y
120: #self.stage = clutter.stage_get_default()
121: self.stage = clutter.Stage()
122: self.stage.set_size(size_x, size_y)
123: self.stage.set_color(clutter.color_parse(background))
124: self.timelines = timelines
125:
126: def add_rectangle(self, (position_x, position_y), (size_x, size_y), color, border = 0, border_color = "#FFFFFF", behaviours = {}):
127: rectangle = clutter.Rectangle()
128: rectangle.set_position(position_x, position_y)
129: rectangle.set_size(size_x, size_y)
130: rectangle.set_color(clutter.color_parse(color))
131: if border > 0:
132: rectangle.set_border_width(border)
133: rectangle.set_border_color(clutter.color_parse(border_color))
134: self.stage.add(rectangle)
135: for behaviour in behaviours.itervalues():
136: behaviour.apply(rectangle)
137: rectangle.show()
138:
139: def add_texture(self, filename, (position_x, position_y), (size_x, size_y), behaviours = {}):
140: try:
141: pixbuf = gtk.gdk.pixbuf_new_from_file(filename)
142: except Exception:
143: print "Unable to find " + filename
144: else:
145: texture = clutter.Texture(pixbuf)
146: texture.set_position(position_x, position_y)
147: if size_x != 0:
148: texture.set_size(size_x, size_y)
149: self.stage.add(texture)
150: for behaviour in behaviours.itervalues():
151: behaviour.apply(texture)
152: texture.behaviours = behaviours # This is needed to stop the behaviours getting garbage-collected
153: texture.show()
154:
155: def add_face(self, filename, (position_x, position_y), (size_x, size_y), behaviours = {}, spin_behaviours = []):
156: try:
157: pixbuf = gtk.gdk.pixbuf_new_from_file(filename)
158: pixbuf_sparkle = gtk.gdk.pixbuf_new_from_file("sparkle.png")
159: except Exception:
160: print "Unable to find " + filename
161: texture = clutter.Texture(pixbuf)
162: texture.set_position(position_x, position_y)
163: texture.set_size(size_x, size_y)
164: sparkle = clutter.Texture(pixbuf_sparkle)
165: sparkle.set_position(position_x, position_y)
166: sparkle.set_size(size_x, size_y)
167: face = clutter.Group()
168: face.add(sparkle)
169: face.add(texture)
170: self.stage.add(face)
171: for behaviour in behaviours.itervalues():
172: behaviour.apply(face)
173: for behaviour in spin_behaviours:
174: behaviour.apply(sparkle)
175: face.show_all()
176:
177: def input_keys(self, stage, event):
178: key = gtk.gdk.keyval_name(event.keyval)
179: self.timelines[key].start()
180: self.timelines["Opacity"].start()
181:
182: def delete_event(self, event, data=None):
183: clutter.main_quit()
184:
185: def main(self):
186: self.stage.show()
187: self.stage.connect("key-press-event", self.input_keys)
188: self.stage.connect("destroy-event", self.delete_event)
189: clutter.main()
190:
191: if __name__ == '__main__':
192: timeline1 = clutter.Timeline(fps=50, duration=500)
193: timeline1.set_loop(False)
194: timeline2 = clutter.Timeline(fps=50, duration=500)
195: timeline2.set_loop(False)
196: timeline_opacity = clutter.Timeline(fps=50, duration=500)
197: timeline2.set_loop(False)
198: timeline_rotate = clutter.Timeline(fps=50, duration=5000)
199: timeline_rotate.set_loop(True)
200:
201: timelines = {"Right":timeline1, "Left":timeline2, "Opacity":timeline_opacity}
202:
203: alpha1 = clutter.Alpha(timeline1, clutter.smoothstep_inc_func)
204: alpha2 = clutter.Alpha(timeline2, clutter.smoothstep_inc_func)
205: alpha_opacity = clutter.Alpha(timeline_opacity, clutter.smoothstep_inc_func)
206: alpha_rotate = clutter.Alpha(timeline_rotate, clutter.ramp_inc_func)
207:
208: #display = ClutterDisplay((800, 600), "#E0DFDE", timelines) # Makes an 800x600 Oxygen-coloured window
209: display = ClutterDisplay((800, 600), "#000000", timelines) # Makes an 800x600 black window
210:
211: spin_behaviours = [BehaviourTurn(alpha_rotate), BehaviourHighlight(alpha_opacity)] # These are the highlight-specific behaviours
212:
213: filenames = os.listdir(os.getcwd() + "/faces")
214:
215: for x in range(0, len(filenames)):
216: display.add_texture("sparkle.png", (x, x), (100, 100), {"Right":BehaviourSpin(alpha1, "anticlockwise", len(filenames), x + 1), "Left":BehaviourSpin(alpha2, "clockwise", len(filenames), x + 1), "Opacity":BehaviourHighlight(alpha_opacity), "Spin":BehaviourTurn(alpha_rotate)})
217: display.add_texture("faces/" + filenames[x], (x, x), (0, 0), {"Right":BehaviourSpin(alpha1, "anticlockwise", len(filenames), x + 1), "Left":BehaviourSpin(alpha2, "clockwise", len(filenames), x + 1)})
218:
219: timeline_rotate.start()
220:
221: display.main()
Generated by git2html.