#!BPY

"""
Name: 'Sama_Landscape'
Blender: 248
Group: 'Wizards'
Tooltip: 'Sama's Landscape.'
"""

######################################################################
# Script: terrainmaker.py                                           
# Author: Chris Smailis (SmaTheGreek)                               
# Author Websites: www.freewebs.com/smathegreek, www.greekblend.invisionplus.net                    
# Date: 12/7/2007                                                   
# Version: 1.0                                                     
#                                                                        
# Description: This script can create terrain models for Blender     
# Developed with Blender 2.44                                       
#                                                                   
######################################################################
# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
# Copyright (c) Chris Smailis (SmaTheGreek), 2007
#
# 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
from Blender import Draw, BGL,Mesh,Object,Scene,Modifier,Mathutils

#Mesh, scene and object variables
object=0
mountain=0
plane=0
scene=0
menu=Draw.Create(1)

    
#GUI Variables
quitbtn=0 #BUTTON USED TO EXIT THE SCRIPT
createbtn=0 # BUTTON USED TO CREATE A NEW TERRAIN

#SLIDERS USED FOR CREATING A RANDOM TERRAIN 
randomxsld=Draw.Create(0.07)
randomysld=Draw.Create(0.07)
randomzsld=Draw.Create(0.07)

sizenum=Draw.Create(4.12) # NUMBER SLIDER USED FOR RESIZING THE TERRAIN
resetbtn=Draw.Create(0)


mountynum=[0,1,2,3,4]
for i in range (0,4):
 mountynum[i]=Draw.Create(0.0)

mountxnum=[0,1,2,3,4]
for i in range(0,4):
 mountxnum[i]=Draw.Create(0.0)


cliffynum=[0,1,2,3,4,5]
for i in range(0,5):
 cliffynum[i]=Draw.Create(0.0)

cliffxnum=[0,1,2,3,4,5]
for i in range(0,5):
 cliffxnum[i]=Draw.Create(0.0)

#Event Variables
scrollevt=1
createevt=2
quitevt=3
menuevt=4
saveevt=5
loadevt=6
resetevt=7


class cliffobj:

 def __init__(self,xval,yval,nameint):
  self.x=xval
  self.y=yval
  if nameint==0:
    self.name="Cliff - Top Left"
  elif nameint==1:
    self.name="Cliff - Top Right"
  elif nameint==2:
    self.name="Cliff - Down Left"   
  elif nameint==3:
    self.name="Cliff - Down Right"
  elif nameint==4:
    self.name="Cliff - Center"  
  self.tag=None  

clf=[0,1,2,3,4,5]
for i in range (0,5):
 clf[i]=cliffobj(0.0,0.5,i)

class mountobj:

 def __init__(self,xval,yval,nameint):
  self.x=xval
  self.y=yval
  if nameint==0:
    self.name="Mountain - Vertical Down"
  elif nameint==1:
    self.name="Mountain - Vertical Top"
  elif nameint==2:
    self.name="Mountain - Horizontal Right" 
  elif nameint==3:
    self.name="Mountain - Horizontal Left"  
  self.tag=None 

mount=[0,1,2,3,4]
for i in range (0,4):
 mount[i]=mountobj(0.0,0.0,i)
 

pathstr=Draw.Create("")  
  
###################################################--Functions--#########################################################################

##################################################--SAVE TERRAIN FUNCTION--#############################################################
def saveterrain(path):
 
 try:   
  outp=open(path,"w")
 except IOError:
    block=[]
    block.append("Path not found")
    popup=Draw.PupBlock("Error:",block)
    print "Directory does not exist"
 else:  
  outp.write("Terran File----Created with terrainmaker v1.0"+"\n")
  outp.write("size="+str(sizenum.val)+"\n")
  outp.write("Randomx=" +str(randomxsld.val)+"\n")
  outp.write("Randomy="+str(randomysld.val)+"\n")
  outp.write("Randomz="+str(randomzsld.val)+"\n")
    
  for i in range(0,5):
   outp.write(clf[i].name+"y="+str(clf[i].y)+"\n")
  for i in range(0,5):
   outp.write(clf[i].name+"x="+str(clf[i].x)+"\n")

  for i in range(0,4):
   outp.write(mount[i].name+"y="+str(mount[i].y)+"\n")
  for i in range(0,4):
   outp.write(mount[i].name+"x="+str(mount[i].x)+"\n")
 
  outp.close()

#############################################--LOAD TERRAIN FUNCTION--#################################################################
def loadterrain(path):
 try:
  inp=file(path,"r")
 except IOError:
    block=[]
    block.append("File not found")
    popup=Draw.PupBlock("Error:",block)
    print "File not found"
 else:
  text=[]
  for i in inp.readlines():
   text.append(i)
  
  val=text[1].split("=") 
  sizenum.val=float(val[1]) 

  val=text[2].split("=")
  randomxsld.val=float(val[1])

  val=text[3].split("=")
  randomysld.val=float(val[1])

  val=text[4].split("=")
  randomzsld.val=float(val[1])

  for i in range(0,5):
   val=text[i+5].split("=") 
   clf[i].y=float(val[1])
   cliffynum[i].val=clf[i].y
  
  for i in range(0,5):
   val=text[i+10].split("=")    
   clf[i].x=float(val[1])
   cliffxnum[i].val=clf[i].x

  for i in range(0,4):
   val=text[i+15].split("=")    
   mount[i].y=float(val[1])
   mountynum[i].val=mount[i].y

  for i in range(0,4):
   val=text[i+19].split("=")    
   mount[i].x=float(val[1])
   mountxnum[i].val=mount[i].x
  
  inp.close()

        

############################################################--CreateCliffs FUNCTION--###############################################

def createcliffs(mesh):
#Creates cliffs by moving certain vertices(the vertices in the center of each square)
 for i in range (21,25):
  mesh.verts[i].co[2]+=clf[i-21].y*sizenum.val

 for i in range(21,25):
  mesh.verts[i].co[0]+=clf[i-21].x*sizenum.val
 
 mesh.verts[8].co[2]+=clf[4].y*sizenum.val
 mesh.verts[8].co[0]+=clf[4].x*sizenum.val

############################################################--MOVECENTERVERTS FUNCTION--###############################################
def movecenterverts(mesh):
#Moves only the vertices belonging to the center of the subdivided plane

 mesh.verts[4].co[2]+=mount[0].y*sizenum.val
 mesh.verts[4].co[0]+=mount[0].x*sizenum.val
 mesh.verts[20].co[2]+=mount[0].y*sizenum.val
 mesh.verts[20].co[0]+=mount[0].x*sizenum.val

 mesh.verts[6].co[2]+=mount[1].y*sizenum.val
 mesh.verts[6].co[0]+=mount[1].x*sizenum.val
 mesh.verts[18].co[2]+=mount[1].y*sizenum.val
 mesh.verts[18].co[0]+=mount[1].x*sizenum.val

 mesh.verts[5].co[2]+=mount[2].y*sizenum.val
 mesh.verts[5].co[0]+=mount[2].x*sizenum.val
 mesh.verts[19].co[2]+=mount[2].y*sizenum.val
 mesh.verts[19].co[0]+=mount[2].x*sizenum.val

 mesh.verts[7].co[2]+=mount[3].y*sizenum.val
 mesh.verts[7].co[0]+=mount[3].x*sizenum.val
 mesh.verts[17].co[2]+=mount[3].y*sizenum.val
 mesh.verts[17].co[0]+=mount[3].x*sizenum.val

########################################################--RANDOMTERRAIN FUNCTION--#####################################################
def randomterrain(mesh):
 #makes everything smooth
 for i in mesh.faces:
   i.smooth=1
 
 mesh.subdivide(1)
 mesh.subdivide(1)

#Adds randomness to the terrain
 for i in mesh.verts:
   if randomxsld.val>0:
    i.co[0]+=Mathutils.Rand(0.0,randomxsld.val)*sizenum.val
   if randomysld.val>0:
    i.co[1]+=Mathutils.Rand(0.0,randomysld.val)*sizenum.val
   if randomzsld.val>0:
    i.co[2]+=Mathutils.Rand(0.0,randomzsld.val)*sizenum.val


##################################################################--CREATEMOUNTAIN FUNCTION--###########################################
def createmountain():

#Creates object and mesh and links it to the current scene
 object=Object.New("Mesh")
 object.setName("mountain")
 # resizes object
 mountain=Mesh.Primitives.Plane(sizenum.val)
 #links object to scene
 object.link(mountain)
 scene=Scene.GetCurrent()
 scene.link(object)
 Blender.Redraw()
#Subdivides and updates mesh
 mountain.subdivide(0)
 mountain.subdivide(1)
 mountain.update()

 createcliffs(mountain)

 movecenterverts(mountain)

 randomterrain(mountain)

#Adds Subsurf modifier 
 mod=object.modifiers.append(Modifier.Types.SUBSURF)
 mod[Modifier.Settings.LEVELS]=3
 mod[Modifier.Settings.RENDLEVELS]=3
 return mountain
 
################################################--RESET FUNCTION--#####################################################################
def reset():
	
  sizenum.val=4.12
  randomxsld.val=0.07
  randomysld.val=0.07
  randomzsld.val=0.07 
  
  for i in range(0,5):
	cliffxnum[i].val=0
	clf[i].x=0
	cliffynum[i].val=0
	clf[i].y=0
  
  for i in range(0,4):
	mount[i].y=0
	mountynum[i].val=0
	mount[i].x=0
	mountxnum[i].val=0
  
##############################################################################--INPUT FUNCTION--####################################### 
def event(evt, val):    # the function to handle input events
		
 Draw.Redraw(1)

##############################################################################--BUTTONEVENT FUNTION--##################################
def button_event(evt):  # the function to handle Draw Button events
  global quitbtn,sizenum

  if evt == scrollevt:
   for i in range(0,5):  
      clf[i].y=cliffynum[i].val
      clf[i].x=cliffxnum[i].val
   for i in range (0,4):
      mount[i].y=mountynum[i].val
      mount[i].x=mountxnum[i].val
   Draw.Redraw(1)
        
  if evt==createevt:
     ob=createmountain()

    
  if evt==menuevt:
    if menu.val==1:
     for i in range(0,5):   
      cliffynum[i].val=clf[i].y
      cliffxnum[i].val=clf[i].x
    if menu.val==2:
     for i in range (0,4):
      mountynum[i].val=mount[i].y
      mountxnum[i].val=mount[i].x 
  
  if evt==saveevt:
    saveterrain(pathstr.val)
    
  if evt==loadevt:
    loadterrain(pathstr.val)
  
  if evt==resetevt:
     reset()
           
  if evt==quitevt:
    Draw.Exit()
			
################################################################--GUI FUNCTION--#######################################################
    
def gui():          # the function to draw the screen
  global quitbtn,sizenum,cliffynum,randomxsld,pathstr,randomysld,randomzsld,y,randomxbtn,randomybtn,randomzbtn,mountynum,mountxnum,cliffxnum,menu
  BGL.glClear(BGL.GL_COLOR_BUFFER_BIT)
  
  #Draws Red Title
  BGL.glColor3f(255,0,0)
  BGL.glRasterPos3i(320, 275,10) #x,y
  Draw.Text("Welcome To SmaTheGreek's Terrain Maker Script !","large")
		
  # Creates Buttons, sliders and other stuff
  y=200
  
  if menu.val==1:
   y=200    
   for i in range (0,5):
    cliffynum[i]=Draw.Number(clf[i].name +" Y: ",scrollevt,5,y,250,20,cliffynum[i].val,-1.0,1.0,"Enter a number betwwen 0.0 and 1.0")
    cliffxnum[i]=Draw.Number(clf[i].name +" X: ",scrollevt,280,y,250,20,cliffxnum[i].val,-0.2,0.2,"Enter a number betwwen 0.0 and 1.0")
    clf[i].y=cliffynum[i].val
    clf[i].x=cliffxnum[i].val
    y-=27
  
  if menu.val==2:
   y=200
   for i in range(0,4):
    mountynum[i]=Draw.Number(mount[i].name+ " Y: ",scrollevt,5,y,250,20,mountynum[i].val,-1.0,1.0,"Enter a number betwwen 0.0 and 1.0")
    mount[i].y=mountynum[i].val
    mountxnum[i]=Draw.Number(mount[i].name+ " X: ",scrollevt,280,y,250,20,mountxnum[i].val,-0.2,0.2,"Enter a number betwwen 0.0 and 1.0")
    mount[i].x=mountxnum[i].val
    y-=27
   
  
  y=200
  sizenum=Draw.Number("Mountain Size:",scrollevt,580,y,250,20,sizenum.val,-30.200,30.200,"Enter a value for Size")
  y-=27
  randomxsld=Draw.Slider("Random Factor X: ",scrollevt,580,y,250,20,randomxsld.val,0.0,1,1,"Enter a demical value")
  y-=27
  randomysld=Draw.Slider("Random Factor Y: ",scrollevt,580,y,250,20,randomysld.val,0.0,1,1,"Enter a demical value")
  y-=27
  randomzsld=Draw.Slider("Random Factor Z: ",scrollevt,580,y,250,20,randomzsld.val,0.0,1,1,"Enter a demical value")  
   
  pathstr=Draw.String("Path: ",scrollevt,580,65,250,20,pathstr.val,399,"None")
  savebtn=Draw.PushButton("Save Terrain",saveevt,580,35,85,25,"Save the terrain properties")   
  loadbtn=Draw.PushButton("Load Terrain",loadevt,750,35,85,25,"Load terrain properties")
  resetbtn=Draw.PushButton("Reset",resetevt,870,35,85,25,"Reset Values")

  name="Selection: Cliffs|Selection: Mountains"
  menu=Draw.Menu(name,menuevt,5,230,150,22,menu.val,"None")

  createbtn=Draw.Toggle("Create",createevt,10,10,50,25,0,"Create the Mountain")
  quitbtn=Draw.Toggle("Quit",quitevt,80,10,50,25,0,"Exit Script")
  
  
################################################# Main Script ##########################################################################

Draw.Register(gui, event, button_event)