#!BPY

"""
Name: 'Stamp Noise'
Blender: 248
Group: 'Mesh'
Tooltip: 'Adding a heightmap-based noise to selected vertices'
"""
__author__ = "Dariusz Dawidowski"
__version__ = "1.3"

# ***** BEGIN GPL LICENSE BLOCK *****
#
# Copyright (c) 2006: Dariusz Dawidowski <dariusz.dawidowski@interia.pl>
#
# 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 LICENSE BLOCK *****

import Blender
from Blender import Object, Mesh, BGL, Draw, Window, Image
from Blender.BGL import *

uicursor = Draw.Create(1)
uiheight = Draw.Create(100.0)
uiroot = Draw.Create(1)
uioperation = Draw.Create(1)

def StampANoise():
	global uicursor, uiheight, uiroot, uioperation
	is_editmode = Window.EditMode()
	if is_editmode: Window.EditMode(0)
	try:
		object = Object.GetSelected()[0]
		mesh = object.getData(mesh=True)
	except:
		Draw.PupMenu("Select mesh object !%t|Ok")
		return
	image = Blender.Image.GetCurrent()
	if image == None:
		Draw.PupMenu("Select image in UV editor !%t|Ok")
		return
	imwidth = image.getSize()[0]
	imheight = image.getSize()[1]
	bbwest = 0.0
	bbeast = 0.0
	bbnorth = 0.0
	bbsouth = 0.0
	bbtop = 0.0
	bbbottom = 0.0
	firstone = True
	for vtx in mesh.verts:
		if vtx.sel:
			if firstone == True:
				bbwest = vtx.co[0]
				bbeast = vtx.co[0]
				bbnorth = vtx.co[1]
				bbsouth = vtx.co[1]
				bbtop = vtx.co[2]
				bbbottom = vtx.co[2]
				firstone = False
			else:
				if vtx.co[0] < bbwest: bbwest = vtx.co[0]
				if vtx.co[0] > bbeast: bbeast = vtx.co[0]
				if vtx.co[1] > bbnorth: bbnorth = vtx.co[1]
				if vtx.co[1] < bbsouth: bbsouth = vtx.co[1]
				if vtx.co[2] > bbtop: bbtop = vtx.co[2]
				if vtx.co[2] < bbbottom: bbbottom = vtx.co[2]
	bbwidth = bbeast - bbwest
	bblength = bbnorth - bbsouth
	bbheight = bbtop - bbbottom
	try:
		unitx = float(imwidth) / bbwidth
		unity = float(imheight) / bblength
	except:
		Draw.PupMenu("Bad vert's selection !%t|Ok")
		return
	if uicursor.val == 1:
		scale = Window.GetCursorPos()[2] - object.getLocation()[2]
	else:
		scale = uiheight.val
	if uiroot.val == 2:
		scale = bbtop - scale
	if uiroot.val == 3:
		scale = bbbottom + scale
	for vtx in mesh.verts:
		if vtx.sel:
			getx = (vtx.co[0] - bbwest) * unitx
			gety = (vtx.co[1] - bbsouth) * unity
			imx = int(getx) - 1
			if (imx < 0): imx = 0
			if (imx > imwidth): imx = imwidth
			imy = int(gety) - 1
			if (imy < 0): imy = 0
			if (imy > imheight): imy = imheight
			newz = (image.getPixelF (imx, imy)[0])
			if uioperation.val == 1:
				vtx.co[2] = (newz * scale)
			if uioperation.val == 2:
				vtx.co[2] = (vtx.co[2] + (newz * scale)) / 2.0
			if uioperation.val == 3:
				vtx.co[2] = (vtx.co[2] + (newz * scale))
			if uioperation.val == 4:
				vtx.co[2] = (vtx.co[2] - (newz * scale))
			if uioperation.val == 5:
				if vtx.co[2] < (newz * scale):
					vtx.co[2] = (newz * scale)
			if uioperation.val == 6:
				if vtx.co[2] > (newz * scale):
					vtx.co[2] = (newz * scale)
	if is_editmode: Window.EditMode(1)
	Window.QRedrawAll()

def CallDraw():
	global uicursor, uiheight, uiroot, uioperation
	glColor3f(0.75, 0.75, 0.75)
	glRecti(5, 5, 260, 180)
	glColor3f(0.5, 0.5, 0.5)
	glRecti(5, 165, 260, 180)
	glColor3f(0, 0, 0)
	glRasterPos2i (10, 170)
	Draw.Text('Stamp noise 1.3', 'small')
	Draw.Button('x', 1, 245, 167, 12, 12, 'Exit')
	glRasterPos2i(10, 145)
	Draw.Text('Heightmap:', 'normal')
	glRasterPos2i(110, 145)
	try:
		image = Blender.Image.GetCurrent()
		Draw.Text(image.getName(), 'normal')
	except:
		Draw.Text('(Select in UV editor)', 'normal')
	glRasterPos2i(10, 120)
	Draw.Text('Height:', 'normal')
	uicursor = Draw.Toggle("Cursor", 2, 110, 115, 72, 18, uicursor.val, "Cursor position instead of value")
	uiheight = Draw.Number("", 3, 182, 115, 72, 18, uiheight.val, -10000.0, 10000.0, "Value instead of cursor position")
	glRasterPos2i(10, 95)
	Draw.Text('Root:', 'normal')
	uiroot = Draw.Menu("Root %t|Zero %x1|Top %x2|Bottom %x3", 4, 110, 90, 144, 18, uiroot.val, "Where is mountain's root")
	glRasterPos2i(10, 70)
	Draw.Text('Operation:', 'normal')
	uioperation = Draw.Menu("Opertation %t|Copy %x1|Mix %x2|Add %x3|Sub %x4|Higher %x5|Lower %x6", 4, 110, 65, 144, 18, uioperation.val, "Select operation")
	Draw.Button('STAMP', 5, 50, 10, 165, 40, 'Stamp a noise')

def CallEvent(ev, val):
	if (ev == Draw.QKEY and not val):
		Draw.Exit()

def CallButton(ev):
	if (ev == 1):
		Draw.Exit()
	if (ev == 5):
		StampANoise()

Draw.Register(CallDraw, CallEvent, CallButton)
