#!BPY

"""
Name: 'Align_Displace'
Blender: 248
Group: 'Object'
Tooltip: 'object_align_displace'
"""

__author__ = "RobertT"
__version__ = "1.0.1"
__url__ = ["http://wiki.blender.org/index.php/Extensions:Py/Scripts/Manual/Object/Object_Aligner_Displacer"]
__bpydoc__ = """\
Aligndisplace.py

Usage:

Load and run this script in Blender (ALT P to run).

This script enables you to align 2 or more objects

or randomly relocate 1 or more objects.  To align

objects, select 2 or more objects in the 3D View.

The last selected object's coordinates will be used

to align the other objects with it.  You may align

by X, Y, or Z, or all X/Y/Z for Location, Size,

and Rotation.  Click the appropriate button in the

script's interface once the script is running.

"""

# -------------------------------------------------------------------------- 
# Aligndisplace.py (c) Robert T. 2009
# -------------------------------------------------------------------------- 
# ***** 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 ***** 
# -------------------------------------------------------------------------- 
# OBJECT ALIGNER/DISPLACER SCRIPT
# Version 1.0
# by RobertT
# Author E-mail: rjtiess@warwick.net
# Script Release Date: December 8, 2003
# Download URL:
# http://webusers.warwick.net/~u1019306/myblenderimages/aligndisplacescript.zip 
#
# WARNING/TERMS OF SERVICE: Use this at your own risk!
# The script has NOT been tested on all versions of
# Blender, nor does it come with any guarantees.  It
# is provided as is with no additional support.  Do not
# run this script on existing Blend files without a full
# understanding of how it works, as modifications cannot
# be undone.  A full Python installation is assumed.
# You have been warned.
#
# About This Script:
#
# Load and run this script in Blender (ALT P to run).
# This script enables you to align 2 or more objects
# or randomly relocate 1 or more objects.  To align
# objects, select 2 or more objects in the 3D View.
# The last selected object's coordinates will be used
# to align the other objects with it.  You may align
# by X, Y, or Z, or all X/Y/Z for Location, Size,
# and Rotation.  Click the appropriate button in the
# script's interface once the script is running.
#
# You may also randomly relocate 1 or more objects
# in the X, Y, or Z coordinates (or all X/Y/Z) by
# selecting 1 or more objects and clicking one of the
# randomize buttons in the script's interface.
# You can do this for Location, Size, and Rotation.
# If you don't like the way the objects get randomized
# you can keep clicking a randomize button for possibly
# better (or worse) results (hey, it's random). You can
# control just how far objects are randomized in terms
# of distance, size, and rotation degrees by adjusting
# the Randomize Range slider in the script's interface.
# Smaller values mean smaller changes.  While the slider
# goes up to 100, when used with Location this can place
# objects well outside the field of view in the 3D View,
# not to mention WELL out of camera range, so beware.
#
# Old and New coordinates for relocated/resized/rerotated
# objects are printed to the Blender console window.  This
# can be handy to track an object's modification history,
# especially if you want to try to manually restore an
# object to its original location (selecting the object
# then pressing N then entering the LocX, LocY, LocZ
# values -- you may not be able to scroll back far enough
# in the console to see the original values, so beware.
# 
# Clearly this is an experimental script, designed
# expressly for experimentation, and like all experiments
# some results are good, and others are not so good.
# The script doesn't modify your .blend file, only the
# active data in the view; HOWEVER, if you somehow save
# your blend file, any changes you made with or without
# the script will likely be irrevesible, so DO NOT SAVE
# YOUR FILE unless you're: A.) Happy with the results
# B.) Saving your file to a new file name (i.e. SAVE AS)
# so as to preserve your original .blend file should you
# need to go back to it at some point.
#
# So you can experiment safely and see what the script
# can do, a sample # scene (filename: sample.blend) has
# been included in this compressed archive
# (aligndisplacescript.zip).  Three files should be in
# the archive:  README.TXT, aligndisplace.py (THIS FILE),
# and sample.blend.  If these three files are not present
# do not use this.  This archive should only be copied
# and republished in its original state.  When in doubt,
# download it again from the URL posted at the top of this
# notice.

import Blender
from Blender.Draw import *
from Blender.BGL import *
from random import random

print "\n\nNow running: Object Aligner/Displacer Script (v1.0) by RobertT (rjtiess@warwick.net)"

randomizeRange = Create(1.0)

def checkSelection(numberOfItemsSelected):
	objects = Blender.Object.GetSelected()
	if len(objects) < numberOfItemsSelected:
		print "\nError: Not enough objects selected."
		return False
	else:
		print "\nObject(s) moved.  Check results in 3D View."
		return True

def printOldCoordinates(objName):
		print "\n" , objName, "Old LocX:", objName.LocX, "Old LocY:", objName.LocY, "Old LocZ:" , objName.LocZ

def printNewCoordinates(objName):
		print "\n" , objName, "New LocX:", objName.LocX, "New LocY:", objName.LocY, "New LocZ:", objName.LocZ

def printOldSize(objName):
		print "\n" , objName, "Old SizeX:", objName.SizeX, "Old SizeY:", objName.SizeY, "Old SizeZ:" , objName.SizeZ

def printNewSize(objName):
		print "\n" , objName, "New SizeX:", objName.SizeX, "New SizeY:", objName.SizeY, "New SizeZ:", objName.SizeZ

def printOldRot(objName):
		print "\n" , objName, "Old RotX:", objName.RotX, "Old RotY:", objName.RotY, "Old RotZ:" , objName.RotZ

def printNewRot(objName):
		print "\n" , objName, "New RotX:", objName.RotX, "New RotY:", objName.RotY, "New RotZ:", objName.RotZ

# align according to LocX of last object selected
def alignObjectsLocX():
	if (checkSelection(2)):
		o = Blender.Object.GetSelected()[0]
		objects = Blender.Object.GetSelected()
		print "\nALIGN to X of " , o
		for a in objects:
			printOldCoordinates(a)
			a.setLocation (o.LocX, a.LocY, a.LocZ) 
			printNewCoordinates(a)
		Blender.Redraw()

# align according to LocY of last object selected
def alignObjectsLocY():
	if (checkSelection(2)):
		o = Blender.Object.GetSelected()[0]
		objects = Blender.Object.GetSelected()
		print "\nALIGN to Y of " , o
		for a in objects:
			printOldCoordinates(a)
			a.setLocation (a.LocX, o.LocY, a.LocZ) 
			printNewCoordinates(a)
		Blender.Redraw()

#align according to LocZ of last object selected
def alignObjectsLocZ():
	if (checkSelection(2)):
		o = Blender.Object.GetSelected()[0]
		objects = Blender.Object.GetSelected()
		print "\nALIGN to Z of " , o
		for a in objects:
			printOldCoordinates(a)
			a.setLocation (a.LocX, a.LocY, o.LocZ) 
			printNewCoordinates(a)
		Blender.Redraw()

#align according to Loc XYZ of last object selected
def alignObjectsLocXYZ():
	if (checkSelection(2)):
		o = Blender.Object.GetSelected()[0]
		objects = Blender.Object.GetSelected()
		print "\nALIGN to XYZ of " , o
		for a in objects:
			printOldCoordinates(a)
			a.setLocation (o.LocX, o.LocY, o.LocZ) 
			printNewCoordinates(a)
		Blender.Redraw()

# align according to SizeX of last object selected
def alignObjectsSizeX():
	if (checkSelection(2)):
		o = Blender.Object.GetSelected()[0]
		objects = Blender.Object.GetSelected()
		print "\nALIGN to SizeX of " , o
		for a in objects:
			printOldSize(a)
			a.SizeX = o.SizeX
			printNewSize(a)
		Blender.Redraw()

# align according to SizeY of last object selected
def alignObjectsSizeY():
	if (checkSelection(2)):
		o = Blender.Object.GetSelected()[0]
		objects = Blender.Object.GetSelected()
		print "\nALIGN to SizeY of " , o
		for a in objects:
			printOldSize(a)
			a.SizeY = o.SizeY
			printNewSize(a)
		Blender.Redraw()

#align according to SizeZ of last object selected
def alignObjectsSizeZ():
	if (checkSelection(2)):
		o = Blender.Object.GetSelected()[0]
		objects = Blender.Object.GetSelected()
		print "\nALIGN to SizeZ of " , o
		for a in objects:
			printOldSize(a)
			a.SizeZ = o.SizeZ
			printNewSize(a)
		Blender.Redraw()

#align according to Size XYZ of last object selected
def alignObjectsSizeXYZ():
	if (checkSelection(2)):
		o = Blender.Object.GetSelected()[0]
		objects = Blender.Object.GetSelected()
		print "\nALIGN to Size XYZ of " , o
		for a in objects:
			printOldSize(a)
			a.SizeX = o.SizeX
			a.SizeY = o.SizeY
			a.SizeZ = o.SizeZ
			printNewSize(a)
		Blender.Redraw()

# align according to RotX of last object selected
def alignObjectsRotX():
	if (checkSelection(2)):
		o = Blender.Object.GetSelected()[0]
		objects = Blender.Object.GetSelected()
		print "\nALIGN to RotX of " , o
		for a in objects:
			printOldRot(a)
			a.RotX = o.RotX
			printNewRot(a)
		Blender.Redraw()

# align according to RotY of last object selected
def alignObjectsRotY():
	if (checkSelection(2)):
		o = Blender.Object.GetSelected()[0]
		objects = Blender.Object.GetSelected()
		print "\nALIGN to RotY of " , o
		for a in objects:
			printOldRot(a)
			a.RotY = o.RotY
			printNewRot(a)
		Blender.Redraw()

#align according to RotZ of last object selected
def alignObjectsRotZ():
	if (checkSelection(2)):
		o = Blender.Object.GetSelected()[0]
		objects = Blender.Object.GetSelected()
		print "\nALIGN to RotZ of " , o
		for a in objects:
			printOldRot(a)
			a.RotZ = o.RotZ
			printNewRot(a)
		Blender.Redraw()

#align according to Size XYZ of last object selected
def alignObjectsRotXYZ():
	if (checkSelection(2)):
		o = Blender.Object.GetSelected()[0]
		objects = Blender.Object.GetSelected()
		print "\nALIGN to Size XYZ of " , o
		for a in objects:
			printOldRot(a)
			a.RotX = o.RotX
			a.RotY = o.RotY
			a.RotZ = o.RotZ
			printNewRot(a)
		Blender.Redraw()


def getRandNum():
	grn = random() * randomizeRange.val
	pn = random() * 4
	if (pn > 2):
		s = -1
	else:
		s = 1
	return grn * s

#randomize LocX of objects selected
def randomizeObjectsLocX():
	checkSelection(1)
	objects = Blender.Object.GetSelected()
	print "\nRANDOMIZE LocX OF " , objects
	for a in objects:
		printOldCoordinates(a)
		a.setLocation (getRandNum(), a.LocY, a.LocZ) 
		printNewCoordinates(a)
	Blender.Redraw()

#randomize LocY of objects selected
def randomizeObjectsLocY():
	checkSelection(1)
	objects = Blender.Object.GetSelected()
	print "\nRANDOMIZE LocY OF " , objects
	for a in objects:
		printOldCoordinates(a)
		a.setLocation (a.LocX, getRandNum(), a.LocZ) 
		printNewCoordinates(a)
	Blender.Redraw()

#randomize LocZ of objects selected
def randomizeObjectsLocZ():
	checkSelection(1)
	objects = Blender.Object.GetSelected()
	print "\nRANDOMIZE LocZ OF " , objects
	for a in objects:
		printOldCoordinates(a)
		a.setLocation (a.LocX, a.LocY, getRandNum()) 
		printNewCoordinates(a)
	Blender.Redraw()

#randomize Loc XYZ of objects selected
def randomizeObjectsLocXYZ():
	checkSelection(1)
	objects = Blender.Object.GetSelected()
	print "\nRANDOMIZE Loc X/Y/Z OF " , objects
	for a in objects:
		printOldCoordinates(a)
		a.setLocation (getRandNum(), getRandNum(), getRandNum()) 
		printNewCoordinates(a)
	Blender.Redraw()

#randomize SizeX of objects selected
def randomizeObjectsSizeX():
	checkSelection(1)
	objects = Blender.Object.GetSelected()
	print "\nRANDOMIZE SizeX OF " , objects
	for a in objects:
		printOldSize(a)
		a.SizeX = getRandNum()
		printNewSize(a)
	Blender.Redraw()

#randomize SizeY of objects selected
def randomizeObjectsSizeY():
	checkSelection(1)
	objects = Blender.Object.GetSelected()
	print "\nRANDOMIZE SizeY OF " , objects
	for a in objects:
		printOldSize(a)
		a.SizeY = getRandNum()
		printNewSize(a)
	Blender.Redraw()

#randomize SizeZ of objects selected
def randomizeObjectsSizeZ():
	checkSelection(1)
	objects = Blender.Object.GetSelected()
	print "\nRANDOMIZE SizeZ OF " , objects
	for a in objects:
		printOldSize(a)
		a.SizeZ = getRandNum()
		printNewSize(a)
	Blender.Redraw()

#randomize Size XYZ of objects selected
def randomizeObjectsSizeXYZ():
	checkSelection(1)
	objects = Blender.Object.GetSelected()
	print "\nRANDOMIZE Size X/Y/Z OF " , objects
	for a in objects:
		printOldSize(a)
		a.SizeX = getRandNum()
		a.SizeY = getRandNum()
		a.SizeZ = getRandNum()
		printNewSize(a)
	Blender.Redraw()

#randomize RotX of objects selected
def randomizeObjectsRotX():
	checkSelection(1)
	objects = Blender.Object.GetSelected()
	print "\nRANDOMIZE RotX OF " , objects
	for a in objects:
		printOldRot(a)
		a.RotX = getRandNum()
		printNewRot(a)
	Blender.Redraw()

#randomize RotY of objects selected
def randomizeObjectsRotY():
	checkSelection(1)
	objects = Blender.Object.GetSelected()
	print "\nRANDOMIZE RotY OF " , objects
	for a in objects:
		printOldRot(a)
		a.RotY = getRandNum()
		printNewRot(a)
	Blender.Redraw()

#randomize RotZ of objects selected
def randomizeObjectsRotZ():
	checkSelection(1)
	objects = Blender.Object.GetSelected()
	print "\nRANDOMIZE RotZ OF " , objects
	for a in objects:
		printOldRot(a)
		a.RotZ = getRandNum()
		printNewRot(a)
	Blender.Redraw()

#randomize Rot XYZ of objects selected
def randomizeObjectsRotXYZ():
	checkSelection(1)
	objects = Blender.Object.GetSelected()
	print "\nRANDOMIZE Rot X/Y/Z OF " , objects
	for a in objects:
		printOldRot(a)
		a.RotX = getRandNum()
		a.RotY = getRandNum()
		a.RotZ = getRandNum()
		printNewRot(a)
	Blender.Redraw()

#reset object's Location to center of Blender's grid
def resetObjectsLocation():
	checkSelection(1)
	objects = Blender.Object.GetSelected()
	print "\nReset Location X/Y/Z OF " , objects
	for a in objects:
		printOldCoordinates(a)
		a.LocX = 0
		a.LocY = 0
		a.LocZ = 0
		printNewCoordinates(a)
	Blender.Redraw()

#reset object's Size to default (1,1,1)
def resetObjectsSize():
	checkSelection(1)
	objects = Blender.Object.GetSelected()
	print "\nReset Size X/Y/Z OF " , objects
	for a in objects:
		printOldSize(a)
		a.SizeX = 1
		a.SizeY = 1
		a.SizeZ = 1
		printNewSize(a)
	Blender.Redraw()

#reset object's Rotation to default (0,0,0)
def resetObjectsRotation():
	checkSelection(1)
	objects = Blender.Object.GetSelected()
	print "\nReset Rotation X/Y/Z OF " , objects
	for a in objects:
		printOldRot(a)
		a.RotX = 0
		a.RotY = 0
		a.RotZ = 0
		printNewRot(a)
	Blender.Redraw()


def draw():
	global randomizeRange
	
	glClearColor(.7, .7, .7, 0.0)
	glClear(GL_COLOR_BUFFER_BIT)
	glRasterPos2i(30,500)
	Text("Object Aligner/Displacer Script (v1.0) by RobertT (rjtiess@warwick.net)")
	glRasterPos2i(30,480)
	Text("To align, select 2 or more objects, click any Align button.")
	glRasterPos2i(30,460)
	Text("To randomize, select 1 or more objects, click any Randomize button.")
	glRasterPos2i(30,440)
	Text("Note: Alignment uses X/Y/Z of last selected object.")

	Button("Align LocX",     70,  30,  400, 100, 25)
	Button("Align LocY",     71, 130,  400, 100, 25)
	Button("Align LocZ",     72, 230,  400, 100, 25)
	Button("Align XYZ",      73, 330,  400, 100, 25)

	Button("Align SizeX",    74,  30,  370, 100, 25)
	Button("Align SizeY",    75, 130,  370, 100, 25)
	Button("Align SizeZ",    76, 230,  370, 100, 25)
	Button("Align SizeXYZ",  77, 330,  370, 100, 25)

	Button("Align RotX",     78,  30,  340, 100, 25)
	Button("Align RotY",     79, 130,  340, 100, 25)
	Button("Align RotZ",     80, 230,  340, 100, 25)
	Button("Align RotXYZ",   81, 330,  340, 100, 25)

	Button("Rand LocX",      82,  30,  310, 100, 25)
	Button("Rand LocY",      83, 130,  310, 100, 25)
	Button("Rand LocZ",      84, 230,  310, 100, 25)
	Button("Rand LocXYZ",    85, 330,  310, 100, 25)

	Button("Rand SizeX",     86,  30,  280, 100, 25)
	Button("Rand SizeY",     87, 130,  280, 100, 25)
	Button("Rand SizeZ",     88, 230,  280, 100, 25)
	Button("Rand SizeXYZ",   89, 330,  280, 100, 25)

	Button("Rand RotX",      90,  30,  250, 100, 25)
	Button("Rand RotY",      91, 130,  250, 100, 25)
	Button("Rand RotZ",      92, 230,  250, 100, 25)
	Button("Rand RotXYZ",    93, 330,  250, 100, 25)

	Button("SetLoc: 0,0,0",  94,  30,  220, 100, 25)
	Button("SetSize: 1,1,1", 95, 130,  220, 100, 25)
	Button("SetRot: 0,0,0",  96, 230,  220, 100, 25)

	randomizeRange = Slider("Randomize range: ", 97, 30, 185, 350, 25, randomizeRange.val, 1, 100, True)
	glRasterPos2i(30,160)
	Text("Check Blender console window for old and new X/Y/Z values.")
	Button("Exit",           99, 330, 220,  100, 25)

def event(evt, val):	
	if ((evt == QKEY) and not val):
		print "Aligner/Displacer Script exited by user."
		Exit()

def bevent(evt):
	if evt == 99:
		print "Aligner/Displacer Script exited by user."
		Exit()
	elif evt == 70:
		alignObjectsLocX()
	elif evt == 71:
		alignObjectsLocY()
	elif evt == 72:
		alignObjectsLocZ()
	elif evt == 73:
		alignObjectsLocXYZ()
	elif evt == 74:
		alignObjectsSizeX()
	elif evt == 75:
		alignObjectsSizeY()
	elif evt == 76:
		alignObjectsSizeZ()
	elif evt == 77:
		alignObjectsSizeXYZ()
	elif evt == 78:
		alignObjectsRotX()
	elif evt == 79:
		alignObjectsRotY()
	elif evt == 80:
		alignObjectsRotZ()
	elif evt == 81:
		alignObjectsRotXYZ()
	elif evt == 82:
		randomizeObjectsLocX()
	elif evt == 83:
		randomizeObjectsLocY()
	elif evt == 84:
		randomizeObjectsLocZ()
	elif evt == 85:
		randomizeObjectsLocXYZ()
	elif evt == 86:
		randomizeObjectsSizeX()
	elif evt == 87:
		randomizeObjectsSizeY()
	elif evt == 88:
		randomizeObjectsSizeZ()
	elif evt == 89:
		randomizeObjectsSizeXYZ()
	elif evt == 90:
		randomizeObjectsRotX()
	elif evt == 91:
		randomizeObjectsRotY()
	elif evt == 92:
		randomizeObjectsRotZ()
	elif evt == 93:
		randomizeObjectsRotXYZ()
	elif evt == 94:
		resetObjectsLocation()
	elif evt == 95:
		resetObjectsSize()
	elif evt == 96:
		resetObjectsRotation()
	elif evt == 97:
		return
	Blender.Redraw()

Register(draw, event, bevent)