#----------------------------------------------------------------------
#
# ABOUT THIS FILE:  This file is intended to make work with enemy animations a bit simpler.
#                   I hope it really does the trick. 
#
# STEPS:  Several things must be done before this script will really do some work.
#
# 0. Blender must be started from FreeDroid/graphics/blender_sources directory.
#
# 1. Coppy (part of FreedroidRPG) must be compiled somewhere.
#
# 2. path where to find croppy must be entered below in variable 'croppy_path'
#
# 3. /tmp/ directory must be writable for common user
#
# 4. MAYBE the number of frames used for the animation will change.  The correct number of
#    frames in the animation is :
# 
#                           ( number_of_frames_in_motion_cycle * number_of_directions ) + 1
#
#    THIS VALUE DOES NOT HAVE TO BE ENTERED INTO ANY PYTHON VARIABLES or something, but
#    is just the recommended setting for the final frame at the 'ANIM' button.
# 
# 5. The number of frames for stand/walk/attack/gethit/death animation should be entered into
#    the corresponding variables, see detailed instructions below, but it's plain simple
#    now (unlike the weird system that was there earlier)
#
# 6. (And of course:  Enough copies of the animation blocks have to be made.  At least 
#     number_of_directions + 1 are recommended.  It's not sufficient to just have everything
#     once.)
#
# --------------------
#
# NOTE:  an occasional error message 'cannot stat ...0000.png' is completely ok.  The script
#        will still work as intended.
#
# --------------------
#

######################################################################
######################### PREPARE EVERYTHING #########################
######################################################################

######################
# Let's start with the preparations:  Importing modules...
#
import Blender
import os
import sys
from math import *

#--------------------
#
# The variable definitions right below should be correct like that
# for a lot of cases.  Adaption should (in general) not be nescessary.
#
#--------------------

pi2 = pi * 2 
number_of_enemy_directions = 8.0
rot_angle = pi2 / number_of_enemy_directions
our_cam = Blender.Object.Get("RotoCamera")
source_directory = "/tmp/"
mv_path = "mv"
rm_path = "rm"

#--------------------
#
# The croppy path is now the local path from the CVSROOT/graphics/blender_sources/
# directory, so it should work on any CVS tree, that has croppy compiled. 
#
#--------------------

croppy_path = "../../croppy/croppy"

#--------------------
#
# Adapt the 'target_directory' variable to point to the directory where you want
# the final images to come to rest.
#
#--------------------

target_directory = "../droids/247/"

#--------------------
#
# Stand cycle starts at frame 1 and 5 is the last frame that belongs to it, so the values
# for that are just that.
#
# Walk cycle starts at frame 6 and 10 is the last frame that belongs to it, so the values
# for that are just that.
#
# Attack cycle starts at frame 11 and 15 is the last frame that belongs to it, so the
# values for that are just that.
#
# Same goes for the gethit animation.
#
# Same goes again for the death animation.  
#
# No adaptions (like un-intuitive +1 modifiers or such 
# crap) are nescessary beyond that.  Just the images used.
#
#--------------------
 

first_stand_animation_image   = 1
last_stand_animation_image    = 5
first_walk_animation_image    = 6
last_walk_animation_image     = 10

first_attack_animation_image  = 11
last_attack_animation_image   = 18
first_gethit_animation_image  = 19
last_gethit_animation_image   = 23
first_death_animation_image   = 24
last_death_animation_image    = 29


#--------------------
# The motion circle starts at frame 1, at frame 21, at frame 41, ....
# so the DIFFERENCE between each cycle start is exactly 20.  We will
# use the word 'full_motion_cycle' in exactly that sense (from now on
# it hasn't always been like that, but it should make things simple and
# more intuitive).  So the value needed for 'full_motion_cycle' is clear.
#--------------------

full_motion_cycle = 29

#--------------------
# 
# How many images must be rendered?
# Internal note:  27 * 8 directions makes for at least, say
#                 230 images we _should_ generate, so it goes
#                 through the whole circle at least once...
#--------------------


#----------------------------------------
#
# RECOMMENDATION:  Do not fiddle around with the code _BELOW_ this line. 
#                  Everything that has to be adapted for an animation
#                  can be adapted to work in the lines _ABOVE_, while
#                  moving around the script part below might break the
#                  script.  (That isn't a problem.  We can make a new
#                  one or use a backup any time... :)
#
#----------------------------------------

#--------------------
#
# Since there are no really 'dead' (i.e. not-to-be-saved) frames in this 
# animation, the 'stop_file_generation_after_image_nr' is not really used
# at all.  To 'disable' it, just set it to any value greater than the
# full_motion_cycle.  (We might use it some time, so it can stay just like
# that.  It won't hurt.
#
#--------------------
stop_file_generation_after_image_nr = full_motion_cycle + 1

######################################################################
################## FIND OUT THE OUTPUT DIRECTION #####################
######################################################################

######################
# Now we can start to identify the current direction
# by taking a closer look at the current camera position.
#
output_direction = 0 
start_x_pos = our_cam.LocX
start_y_pos = our_cam.LocY
#
# Now we need to be careful to avoid division by zero...
#
if our_cam.LocX == 0:
	our_arctan = atan ( our_cam.LocY / 0.0001 )
else:
	our_arctan = atan ( our_cam.LocY / our_cam.LocX )

# print "Our arc tan is: " , our_arctan 

def get_output_direction_8():
	global output_direction
	if abs( our_arctan - 0 * pi/4 ) < pi2/32:
		if start_x_pos < 0 :
			output_direction = 2
		else:
			output_direction = 6
	elif abs( our_arctan - 1 * pi/4 ) < pi2/32:
		if start_y_pos < 0 :
			output_direction = 1
		else:
			output_direction = 5
	elif abs( our_arctan + 1 * pi/4 ) < pi2/32:
		if start_y_pos < 0 :
			output_direction = 7
		else:
			output_direction = 3
	elif abs( our_arctan - 2 * pi/4 ) < pi2/32:
		if start_y_pos < 0 :
			output_direction = 0
		else:
			output_direction = 4
	elif abs( our_arctan + 2 * pi/4 ) < pi2/32:
		if start_y_pos < 0 :
			output_direction = 0
		else:
			output_direction = 4
	else:
		print "ERROR:  UNABLE TO DETERMINE DIRECTION!"
		Exit()

def get_output_direction_16():
	global output_direction
	if abs( our_arctan - 0 * pi/4 ) < pi2/32:
		if start_x_pos < 0 :
			output_direction = 4
		else:
			output_direction = 12
	elif abs( our_arctan - 1 * pi/8 ) < pi2/32:
		if start_x_pos < 0 :
			output_direction = 3
		else:
			output_direction = 11
	elif abs( our_arctan + 1 * pi/8 ) < pi2/32:
		if start_x_pos < 0 :
			output_direction = 5
		else:
			output_direction = 13
	elif abs( our_arctan - 1 * pi/4 ) < pi2/32:
		if start_x_pos < 0 :
			output_direction = 2
		else:
			output_direction = 10
	elif abs( our_arctan + 1 * pi/4 ) < pi2/32:
		if start_y_pos < 0 :
			output_direction = 14
		else:
			output_direction = 6
	elif abs( our_arctan + 3 * pi/8 ) < pi2/32:
		if start_y_pos < 0 :
			output_direction = 15
		else:
			output_direction = 7
	elif abs( our_arctan - 3 * pi/8 ) < pi2/32:
		if start_y_pos < 0 :
			output_direction = 1
		else:
			output_direction = 9
	elif abs( our_arctan - 2 * pi/4 ) < pi2/32:
		if start_y_pos < 0 :
			output_direction = 0
		else:
			output_direction = 8
	elif abs( our_arctan + 2 * pi/4 ) < pi2/32:
		if start_y_pos < 0 :
			output_direction = 0
		else:
			output_direction = 8
	else:
		print "ERROR:  UNABLE TO DETERMINE DIRECTION!"
		Exit()

if number_of_enemy_directions == 16:
	get_output_direction_16()
elif number_of_enemy_directions == 8:
	get_output_direction_8()
else:
	print "ERROR:  illegal number of directions given."
	Exit()

print "Final output direction: " , output_direction


######################################################################
##################### CAMERA ROTATION FUNCTION #######################
######################################################################

#######################
# Now we define our function that will rotate the camera
# by a fraction of a full turn
#
def do_cam_rot():
	r = our_cam.LocX * our_cam.LocX + our_cam.LocY * our_cam.LocY
	# print "Radius square: " , r
	r = sqrt ( r )
	# print "Radius used (without Z component):" , r
	######################
	# First we print out the starting position and rotation of the camera, just
	# so that we can check everything is all right, if we want to...
	#
	# print "Starting with coordinates: " , our_cam.loc
	# print "Starting with rotation: " , our_cam.rot
	######################
	# Now it's time to start doing the rotation.  Hope everything will go well...
	#
	X_new = 1.0 * ( cos ( rot_angle ) * our_cam.LocX + sin ( rot_angle ) * our_cam.LocY )
	Y_new = 1.0 * (-sin ( rot_angle ) * our_cam.LocX + cos ( rot_angle ) * our_cam.LocY )
	
	our_cam.LocX = X_new
	our_cam.LocY = Y_new
	our_cam.RotZ = our_cam.RotZ - rot_angle
	Blender.Redraw()

######################################################################
###################### RENAME AND CROPPY FUNCTION ####################
######################################################################

########################
# Now we check if maybe the last frame of the animation
# has been reached.  In this case we will do a rotation 
# of the camera.  If not we will start a croppy operation
# on the current output file.
#
time = Blender.Get("curframe") - 1

def do_rename_and_croppy():
	if time < 10 :
		number_code = "0" + "0" + "0" + str(time)
	elif time < 100 :
		number_code = "0" + "0" + str(time)
	else :
		number_code = "0" + str(time)

	target_time = ( ( time + full_motion_cycle - 1 ) % ( full_motion_cycle ) ) + 1 
	
	get_output_direction_16()

	if output_direction < 10 :
		direction_code = "0" + str ( output_direction )
	else:
		direction_code = str ( output_direction)

	source_filename = source_directory + "iso_tmpfile_" + number_code + ".png"

	#--------------------
	# Now that we're not using the 'ingame' file names any more for droid animations,
	# we need to do something more sophisticated to find out the proper filename and
	# therefore we need to separate some cases...
	#
	if ( ( target_time >= first_stand_animation_image ) & ( target_time <= last_stand_animation_image ) ) :
		output_string = "stand"
		target_time = target_time - first_stand_animation_image + 1
	elif ( ( target_time >= first_walk_animation_image ) & ( target_time <= last_walk_animation_image ) ) :
		output_string = "walk"
		target_time = target_time - first_walk_animation_image + 1
	elif ( ( target_time >= first_attack_animation_image ) & ( target_time <= last_attack_animation_image ) ) :
		output_string = "attack"
		target_time = target_time - first_attack_animation_image + 1
	elif ( ( target_time >= first_gethit_animation_image ) & ( target_time <= last_gethit_animation_image ) ) :
		output_string = "gethit"
		target_time = target_time - first_gethit_animation_image + 1
	elif ( ( target_time >= first_death_animation_image ) & ( target_time <= last_death_animation_image ) ) :
		output_string = "death"
		target_time = target_time - first_death_animation_image + 1

	if target_time < 10 :
		target_number_code = "0" + "0" + "0" + str(target_time)
	else :
		target_number_code = "0" + "0" + str(target_time)

	target_filename = target_directory + output_string + "_" + direction_code + "_" + target_number_code + ".png"

	if ( ( target_time != 0 ) & ( target_time <= stop_file_generation_after_image_nr ) ) :
		# os.system ( "pwd" )
		command_line = mv_path + " " + source_filename + " " + target_filename
		print "invoking command line: " , command_line
		os.system ( command_line )
		# ----
		parameter = " -i " + target_filename
		print "Command line: " , croppy_path , parameter
		os.system ( croppy_path + parameter )
	else :
		print "This image will not be needed by the engine and therefore we delete it."
		command_line = rm_path + " " + source_filename
		# ----

######################################################################
########################## 'MAIN PROGRAM' ############################
######################################################################


if ( time % ( full_motion_cycle ) ) == 0 :
	do_cam_rot()
	do_rename_and_croppy()
else:
	do_rename_and_croppy()
