python-clutter-experiments: da285b7c20ce63278f266da318a514a6bba1f3f6

     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.