#!BPY

"""
Name: 'Shake_n_Bake'
Blender: '248'
Group: 'Animation'
Tooltip: 'A Camera (Object) shaker with ease-in and ease-out support'
"""

__author__ = "Markus Kothe"
__version__ = "2.0 2009/03/16"
__email__ = "markus.kothe[at]gmail.com"
__url__ = "none"

# shake_n_bake.py (c) Markus Kothe 
# -------------------------------------------------------------------------- 
# ***** BEGIN GPL LICENSE BLOCK ***** 
# 
# This program is free software; you can redistribute it and/or 
# modify it under the terms of the GNU General Public License 
# as published by the Free Software Foundation; either version 2 
# of the License, or (at your option) any later version. 
# 
# This program is distributed in the hope that it will be useful, 
# but WITHOUT ANY WARRANTY; without even the implied warranty of 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
# GNU General Public License for more details. 
# 
# You should have received a copy of the GNU General Public License 
# along with this program; if not, write to the Free Software Foundation, 
# Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. 
# 
# ***** END GPL LICENCE BLOCK ***** 
# -------------------------------------------------------------------------- 

import Blender as B
import math

amount = B.Draw.Create(200)
start = B.Draw.Create(1)
amp = B.Draw.Create(20)
ramp = B.Draw.Create(5)
easein = B.Draw.Create(25)
easeout = B.Draw.Create(25)
freq = B.Draw.Create(2)
togx = B.Draw.Create(1)
togy = B.Draw.Create(1)
togz = B.Draw.Create(1)
rtogx = B.Draw.Create(1)
rtogy = B.Draw.Create(1)
rtogz = B.Draw.Create(1)
togloc = B.Draw.Create(1)
togrot = B.Draw.Create(0)
clearipo = B.Draw.Create(0)
softcurv = B.Draw.Create(0)
help = B.Draw.Create(0)
page = 1

EVENT_NOEVENT = 1
EVENT_RUN = 2
EVENT_EXIT = 3
EVENT_RELOAD = 4
EVENT_NEXTP = 5
EVENT_BACKP = 6
EVENT_PRESET1 = 11
EVENT_PRESET2 = 12
EVENT_PRESET3 = 13
EVENT_PRESET4 = 14

def draw():	
	global amount
	global start
	global amp
	global ramp
	global easein
	global easeout
	global freq
	global togx
	global togy
	global togz
	global rtogx
	global rtogy
	global rtogz
	global togloc
	global togrot
	global clearipo
	global softcurv
	global help
	global page
	global EVENT_NOEVENT, EVENT_EXIT, EVENT_RUN, EVENT_RELOAD, EVENT_NEXTP, EVENT_BACKP, EVENT_PRESET1, EVENT_PRESET2, EVENT_PRESET3, EVENT_PRESET4
	
	B.BGL.glClear(B.BGL.GL_COLOR_BUFFER_BIT)
	
	B.BGL.glColor3f(.2, .2, .2)
	B.BGL.glRecti(2,4,223,251)
	B.BGL.glColor3f(.2, .2, .2)
	B.BGL.glRecti(4,2,221,253)
	B.BGL.glColor3f(.1, .1, .1)
	B.BGL.glRecti(3,3,222,252)
	B.BGL.glColor3f(.85, .85, .85)
	B.BGL.glRecti(5,5,215,250)
	B.BGL.glColor3f(.75, .75, .75)
	B.BGL.glRecti(15,5,105,250)
	B.BGL.glColor3f(.65, .65, .65)
	B.BGL.glRecti(5,217,215,250)
	B.BGL.glColor3f(.4, .4, .4)
	B.BGL.glRecti(5,220,215,239)
	B.BGL.glColor3f(.4, .4, .4)
	B.BGL.glRecti(215,5,220,250)
	
	B.BGL.glColor3f(.6, .6, .6)
	B.BGL.glRasterPos2d(13, 225)
	B.Draw.Text("S H A K E  n'  B A K E  2 . 0", "normal")
	B.BGL.glColor3f(.1, .1, .1)
	B.BGL.glRasterPos2d(12, 226)
	B.Draw.Text("S H A K E  n'  B A K E  2 . 0", "normal")
	B.BGL.glColor3f(0.5, 0.5, 0.5)
	B.BGL.glRasterPos2d(12, 15)
	B.Draw.Text("written by: Markus Kothe -09", "small")
	
	B.Draw.Button("Exit",EVENT_EXIT,10,30,100,20,"Exit the script")
	B.Draw.Button("Run",EVENT_RUN,110,30,100,20,"Run the script")
	
	help = B.Draw.Toggle("?", EVENT_RELOAD, 194, 222, 16, 16, help.val, "Help")
	
	amp = B.Draw.Slider("Loc: ", EVENT_NOEVENT, 10, 80, 100, 20,amp.val, 1, 300, 1, "How much the camera will shake in loc")
	ramp = B.Draw.Slider("Rot: ", EVENT_NOEVENT, 110, 80, 100, 20,ramp.val, 1, 100, 1, "How much the camera will shake in rot")
	easein = B.Draw.Number("E-in: ", EVENT_NOEVENT, 10, 170, 100, 20,easein.val, 1, 200, "Ease in value in frames")
	easeout = B.Draw.Number("E-out: ", EVENT_NOEVENT, 110, 170, 100, 20,easeout.val, 1, 200, "Ease out value in frames")
	amount = B.Draw.Number("Frames: ", EVENT_NOEVENT, 10, 190, 100, 20,amount.val, 1, 20000, "Number of frames the shake will last")
	start = B.Draw.Number("Start: ", EVENT_NOEVENT, 110, 190, 100, 20,start.val, 1, 20000, "Shake start frame")
		
	softcurv = B.Draw.Toggle("Soft Curve", EVENT_NOEVENT, 10, 125, 200, 20, softcurv.val, "Use a sinus curve instead of linear curve in the ease")
		
	freq = B.Draw.Number("Freq: ", EVENT_NOEVENT, 110, 150, 100, 20,freq.val, 1, 15, "How often the script will put out keyframes")
	togloc = B.Draw.Toggle("Loc", EVENT_NOEVENT, 10, 100, 100, 20, togloc.val, "Shake in location ipos")
	togx = B.Draw.Toggle("X", EVENT_NOEVENT, 10, 60, 33, 20, togx.val, "Animate LocX")
	togy = B.Draw.Toggle("Y", EVENT_NOEVENT, 43, 60, 34, 20, togy.val, "Animate LocY")
	togz = B.Draw.Toggle("Z", EVENT_NOEVENT, 77, 60, 33, 20, togz.val, "Animate LocZ")
	togrot = B.Draw.Toggle("Rot", EVENT_NOEVENT, 110, 100, 100, 20, togrot.val, "Shake in rotation ipos")
	rtogx = B.Draw.Toggle("X", EVENT_NOEVENT, 110, 60, 33, 20, rtogx.val, "Animate RotX")
	rtogy = B.Draw.Toggle("Y", EVENT_NOEVENT, 143, 60, 34, 20, rtogy.val, "Animate RotY")
	rtogz = B.Draw.Toggle("Z", EVENT_NOEVENT, 177, 60, 33, 20, rtogz.val, "Animate RotZ")
	clearipo = B.Draw.Toggle("Clear ipos", EVENT_NOEVENT, 10, 150, 100, 20, clearipo.val, "Clear ALL ipos before script run")
	
	if (help.val == 1):
		B.BGL.glColor3f(.1, .1, .1)
		B.BGL.glRecti(220,5,450,249)
		B.BGL.glColor3f(.1, .1, .1)
		B.BGL.glRecti(220,4,449,250)
		B.BGL.glColor3f(.85, .85, .85)
		B.BGL.glRecti(223,8,447,246)
		B.BGL.glColor3f(.85, .85, .85)
		B.BGL.glRecti(224,7,446,247)
		
		B.BGL.glColor3f(.05, .05, .05)
		B.BGL.glRasterPos2d(250, 225)
		B.Draw.Text("I n f o r m a t i o n   a n d   H e l p", "small")
		
		if (page == 1):
			B.BGL.glColor3f(.2, .2, .2)
			B.BGL.glRasterPos2d(230, 200)
			B.Draw.Text("Shake n' Bake is a camera shake script used", "small")
			B.BGL.glRasterPos2d(230, 190)
			B.Draw.Text("to simulate human camera movement or other", "small")
			B.BGL.glRasterPos2d(230, 180)
			B.Draw.Text("type of iregular camera movement", "small")
			
			B.BGL.glRasterPos2d(230, 160)
			B.Draw.Text("To get as much control as possible, link", "small")
			B.BGL.glRasterPos2d(230, 150)
			B.Draw.Text("your camera to an empty and use the empty", "small")
			B.BGL.glRasterPos2d(230, 140)
			B.Draw.Text("to animate camera movement. This way you", "small")
			B.BGL.glRasterPos2d(230, 130)
			B.Draw.Text("won't mess up your movement ipos when", "small")
			B.BGL.glRasterPos2d(230, 120)
			B.Draw.Text("you run the script on the camera object.", "small")
			
			B.BGL.glRasterPos2d(230, 100)
			B.Draw.Text("Most of the help (if needed) is in the", "small")
			B.BGL.glRasterPos2d(230, 90)
			B.Draw.Text("tooltip of every button/variable.", "small")
			
			B.BGL.glRasterPos2d(350, 60)
			B.Draw.Text("Happy shakin'  :D", "small")
			
			#B.Draw.Button("<",EVENT_BACKP,290,30,15,15,"Back")
			B.BGL.glRasterPos2d(323, 34)
			B.Draw.Text("1 / 6", "small")
			B.Draw.Button(">",EVENT_NEXTP,360,30,15,15,"Next page")
			
		if (page == 2):
			B.BGL.glColor3f(.2, .2, .2)
			B.BGL.glRasterPos2d(230, 200)
			B.Draw.Text("CHAPTER 1 - FRAME SETTINGS (1/2)", "small")
			
			B.BGL.glRasterPos2d(230, 185)
			B.Draw.Text("The fist 6 settings in the script are connected", "small")
			B.BGL.glRasterPos2d(230, 175)
			B.Draw.Text("to the frame keying of the shake, this is how", "small")
			B.BGL.glRasterPos2d(230, 165)
			B.Draw.Text("it works...", "small")
			
			B.BGL.glRasterPos2d(230, 150)
			B.Draw.Text("'Frames' lets you decide for how many frames", "small")
			B.BGL.glRasterPos2d(230, 140)
			B.Draw.Text("you want your camera shake to be.", "small")
			
			B.BGL.glRasterPos2d(230, 125)
			B.Draw.Text("'Start' lets you decide where in your animation", "small")
			B.BGL.glRasterPos2d(230, 115)
			B.Draw.Text("you want to start the camera shake (in frames).", "small")
			
			B.BGL.glRasterPos2d(230, 100)
			B.Draw.Text("'E-In' is the variable you use to set the number", "small")
			B.BGL.glRasterPos2d(230, 90)
			B.Draw.Text("of frames you want the ease in to take.", "small")
			
			B.BGL.glRasterPos2d(230, 75)
			B.Draw.Text("'E-out' is the variable you use to set the", "small")
			B.BGL.glRasterPos2d(230, 65)
			B.Draw.Text("number of frames you want the ease out to", "small")
			B.BGL.glRasterPos2d(230, 55)
			B.Draw.Text("take.", "small")
			
			B.Draw.Button("<",EVENT_BACKP,290,30,15,15,"Back")
			B.BGL.glRasterPos2d(323, 34)
			B.Draw.Text("2 / 6", "small")
			B.Draw.Button(">",EVENT_NEXTP,360,30,15,15,"Next page")
			
		if (page == 3):
			B.BGL.glColor3f(.2, .2, .2)
			B.BGL.glRasterPos2d(230, 200)
			B.Draw.Text("CHAPTER 1 - FRAME SETTINGS (2/2)", "small")
			
			B.BGL.glRasterPos2d(230, 185)
			B.Draw.Text("'Clear ipos' is used if you're testing your", "small")
			B.BGL.glRasterPos2d(230, 175)
			B.Draw.Text("settings and want the script to delete the", "small")
			B.BGL.glRasterPos2d(230, 165)
			B.Draw.Text("current ipos before every new calculation.", "small")
			
			B.BGL.glRasterPos2d(230, 150)
			B.Draw.Text("'Freq' is used to set how often you want the", "small")
			B.BGL.glRasterPos2d(230, 140)
			B.Draw.Text("script to set keyframes, higher value gives", "small")
			B.BGL.glRasterPos2d(230, 130)
			B.Draw.Text("smoother movement.", "small")
			
			B.Draw.Button("<",EVENT_BACKP,290,30,15,15,"Back")
			B.BGL.glRasterPos2d(323, 34)
			B.Draw.Text("3 / 6", "small")
			B.Draw.Button(">",EVENT_NEXTP,360,30,15,15,"Next page")
			
		if (page == 4):
			B.BGL.glColor3f(.2, .2, .2)
			B.BGL.glRasterPos2d(230, 200)
			B.Draw.Text("CHAPTER 2 - SOFT CURVE", "small")
			
			B.BGL.glRasterPos2d(230, 185)
			B.Draw.Text("'Soft Curve' is used to change the way", "small")
			B.BGL.glRasterPos2d(230, 175)
			B.Draw.Text("ease in and ease out is calculated.", "small")
			
			B.BGL.glRasterPos2d(230, 160)
			B.Draw.Text("The standard calculation is linear and makes a", "small")
			B.BGL.glRasterPos2d(230, 150)
			B.Draw.Text("very stright ease up/down to the wanted", "small")
			B.BGL.glRasterPos2d(230, 140)
			B.Draw.Text("amplitude. The Soft Curve uses a sinus curve", "small")
			B.BGL.glRasterPos2d(230, 130)
			B.Draw.Text("to calculate the ease and gives a much more", "small")
			B.BGL.glRasterPos2d(230, 120)
			B.Draw.Text("smooth output.", "small")
			
			B.BGL.glRasterPos2d(230, 105)
			B.Draw.Text("This button applies to both Rot and Loc", "small")
			
			B.Draw.Button("<",EVENT_BACKP,290,30,15,15,"Back")
			B.BGL.glRasterPos2d(323, 34)
			B.Draw.Text("4 / 6", "small")
			B.Draw.Button(">",EVENT_NEXTP,360,30,15,15,"Next page")
			
		if (page == 5):
			B.BGL.glColor3f(.2, .2, .2)
			B.BGL.glRasterPos2d(230, 200)
			B.Draw.Text("CHAPTER 3 - LOC/ROT VALUES", "small")
			
			B.BGL.glRasterPos2d(230, 185)
			B.Draw.Text("The main buttons, 'Loc' and 'Rot' is used", "small")
			B.BGL.glRasterPos2d(230, 175)
			B.Draw.Text("to enable the animation on the different", "small")
			B.BGL.glRasterPos2d(230, 165)
			B.Draw.Text("ipos.", "small")
			
			B.BGL.glRasterPos2d(230, 150)
			B.Draw.Text("You use the sliders directly under the toggle", "small")
			B.BGL.glRasterPos2d(230, 140)
			B.Draw.Text("buttons to set the amount of jitter that will", "small")
			B.BGL.glRasterPos2d(230, 130)
			B.Draw.Text("be applied to the ipos.", "small")
			
			B.BGL.glRasterPos2d(230, 115)
			B.Draw.Text("The X, Y, Z buttons is used to determine what", "small")
			B.BGL.glRasterPos2d(230, 105)
			B.Draw.Text("axis will be used in the shake.", "small")
			
			B.Draw.Button("<",EVENT_BACKP,290,30,15,15,"Back")
			B.BGL.glRasterPos2d(323, 34)
			B.Draw.Text("5 / 6", "small")
			B.Draw.Button(">",EVENT_NEXTP,360,30,15,15,"Next page")
			
		if (page == 6):
			B.BGL.glColor3f(.2, .2, .2)
			B.BGL.glRasterPos2d(230, 200)
			B.Draw.Text("CHAPTER 4 - PRESETS", "small")
			
			B.BGL.glRasterPos2d(230, 185)
			B.Draw.Text("Here's a couple of presets to try out:", "small")
				
			B.Draw.Button("Default",EVENT_PRESET1,282,150,100,20,"Sets all variables to default")
			B.Draw.Button("Handcam",EVENT_PRESET2,282,120,100,20,"Simulates a hand hold camera")
			B.Draw.Button("Explotion",EVENT_PRESET3,282,90,100,20,"Simulates a explotion")
			B.Draw.Button("Earthquake",EVENT_PRESET4,282,60,100,20,"Simulates a Earthquake")
			
			B.Draw.Button("<",EVENT_BACKP,290,30,15,15,"Back")
			B.BGL.glRasterPos2d(323, 34)
			B.Draw.Text("6 / 6", "small")
			#B.Draw.Button(">",EVENT_NEXTP,360,30,15,15,"Next page")
			
		B.BGL.glColor3f(.6, .6, .6)
		B.BGL.glRasterPos2d(230, 15)
		B.Draw.Text("Ver - 2.0 Built: 2009-03-16", "small")
	
def event(evt,val):
	if evt == B.Draw.QKEY:
		B.Draw.Exit()
		return
	
def button(evt):
	global amount
	global start
	global amp
	global ramp
	global easein
	global easeout
	global freq
	global togx
	global togy
	global togz
	global rtogx
	global rtogy
	global rtogz
	global togloc
	global togrot
	global clearipo
	global softcurv
	global help
	global page
	global EVENT_NOEVENT, EVENT_EXIT, EVENT_RUN, EVENT_RELOAD, EVENT_NEXTP, EVENT_BACKP, EVENT_PRESET1, EVENT_PRESET2, EVENT_PRESET3, EVENT_PRESET4

	if (evt == EVENT_EXIT):
		B.Draw.Exit()
		return
	if (evt == EVENT_RUN):
		run(amount.val, start.val, amp.val, easein.val, easeout.val, freq.val, togx.val, togy.val, togz.val, clearipo.val, togloc.val, togrot.val, ramp.val, rtogx.val, rtogy.val, rtogz.val, softcurv.val)
		B.Redraw(-1)
	if (evt == EVENT_RELOAD):
		B.Redraw(-1)
	if (evt == EVENT_NEXTP):
		page = page + 1
		B.Redraw(-1)
	if (evt == EVENT_BACKP):
		page = page - 1
		B.Redraw(-1)
	if (evt == EVENT_PRESET1):
		amount.val = 200
		start.val = 1
		amp.val = 50
		ramp.val = 5
		easein.val = 25
		easeout.val = 25
		freq.val = 2
		togx.val = 1
		togy.val = 1
		togz.val = 1
		rtogx.val = 1
		rtogy.val = 1
		rtogz.val = 1
		togloc.val = 1
		togrot.val = 0
		clearipo.val = 0
		softcurv.val = 0
		B.Redraw(-1)
	if (evt == EVENT_PRESET2):
		amount.val = 300
		start.val = 1
		amp.val = 4
		ramp.val = 2
		easein.val = 5
		easeout.val = 5
		freq.val = 4
		togx.val = 1
		togy.val = 1
		togz.val = 1
		rtogx.val = 1
		rtogy.val = 1
		rtogz.val = 1
		togloc.val = 1
		togrot.val = 1
		clearipo.val = 1
		softcurv.val = 1
		B.Redraw(-1)
	if (evt == EVENT_PRESET3):
		amount.val = 60
		start.val = 50
		amp.val = 150
		ramp.val = 5
		easein.val = 5
		easeout.val = 55
		freq.val = 1
		togx.val = 1
		togy.val = 1
		togz.val = 1
		rtogx.val = 0
		rtogy.val = 0
		rtogz.val = 0
		togloc.val = 1
		togrot.val = 0
		clearipo.val = 1
		softcurv.val = 1
		B.Redraw(-1)
	if (evt == EVENT_PRESET4):
		amount.val = 400
		start.val = 1
		amp.val = 75
		ramp.val = 5
		easein.val = 125
		easeout.val = 125
		freq.val = 1
		togx.val = 1
		togy.val = 1
		togz.val = 1
		rtogx.val = 1
		rtogy.val = 1
		rtogz.val = 1
		togloc.val = 1
		togrot.val = 1
		clearipo.val = 1
		softcurv.val = 0
		B.Redraw(-1)
		
B.Draw.Register(draw,event,button)

def run(amount, start, amp, easein, easeout, freq, togx, togy, togz, clearipo, togloc, togrot, ramp, rtogx, rtogy, rtogz, softcurv):
	oldframe = B.Get('curframe')
	
	tempamp = 0
	easeraise = float(amp) / float(easein)
	easelower = float(amp) / float(easeout)
	rtempamp = 0
	reaseraise = float(ramp) / float(easein)
	reaselower = float(ramp) / float(easeout)
	
	
	fcurrent = 0
	
	camera = B.Object.GetSelected()
	
	for lock in camera:
		if clearipo == 1:
			lock.ipo = None
			
		clear = 0
		while clear <= amount:
			B.Set('curframe', (start + clear))
			lock.insertIpoKey(B.Object.IpoKeyTypes.LOC)
			lock.insertIpoKey(B.Object.IpoKeyTypes.ROT)
			clear = clear + freq
	
	for hand in camera:
		while fcurrent <= amount:
			B.Set('curframe', (fcurrent + start))
			
			if togloc == 1:
				if togx == 1:
					hand.LocX = (hand.LocX + (((B.Noise.random()-0.5)/100)*tempamp))
				if togy == 1:
					hand.LocY = (hand.LocY + (((B.Noise.random()-0.5)/100)*tempamp))
				if togz == 1:
					hand.LocZ = (hand.LocZ + (((B.Noise.random()-0.5)/100)*tempamp))
					
			if togrot == 1:
				if rtogx == 1:
					hand.RotX = (hand.RotX + (((B.Noise.random()-0.5)/100)*rtempamp))
				if rtogy == 1:
					hand.RotY = (hand.RotY + (((B.Noise.random()-0.5)/100)*rtempamp))
				if rtogz == 1:
					hand.RotZ = (hand.RotZ + (((B.Noise.random()-0.5)/100)*rtempamp))
		
			hand.insertIpoKey(B.Object.IpoKeyTypes.LOC)
			hand.insertIpoKey(B.Object.IpoKeyTypes.ROT)
	
			if (start + easein - B.Get('curframe')) >= 0:
				if softcurv == 0:
					tempamp = tempamp + (easeraise * freq)
					rtempamp = rtempamp + (reaseraise * freq)
				if softcurv == 1:
					tempamp = amp * math.sin((B.Get('curframe') - start) * 3.141592 / (easein * 2))
					rtempamp = ramp * math.sin((B.Get('curframe') - start) * 3.141592 / (easein * 2))
	
			if B.Get('curframe') >= (amount + start - easeout):
				if softcurv == 0:
					tempamp = tempamp - (easelower * freq)
					rtempamp = rtempamp - (reaselower * freq)
				if softcurv == 1:
					tempamp = amp * math.sin((easeout - (B.Get('curframe') - (amount - easeout) - start)) * 3.141592 / (easeout * 2))
					rtempamp = ramp * math.sin((easeout - (B.Get('curframe') - (amount - easeout) - start)) * 3.141592 / (easeout * 2))
	
			fcurrent = fcurrent + freq
	
	B.Set('curframe', oldframe)