Interactive 'Formula' deformation tool.

Interactive ‘Formula’ deformation tool
#-----------------------------------------------------------------
#_Distort mesh with formulae from math import *
#_Distort mesh with noise from Blender.Noise import *


#!BPY

"""
Name: 'Formula deformation tool'
Blender: 233
Group: 'Mesh'
Tip: 'Distort sellected mesh with formulae and noise'
"""

##################################################################
# Jimmy Hazevoet  July 2004
#-----------------------------------------------------------------
# Interactive 'Formula' deformation tool -------------------------
#-----------------------------------------------------------------
#_Distort mesh with formulae from math import *
#_Distort mesh with noise from Blender.Noise import *
#-----------------------------------------------------------------
# A few simple examples:
#
#EXAMPLE 1:
# d: sin(x*y*z)*2
#
#EXAMPLE 2:
# d: x*sin(u*4*pi) + y*cos(u*4*pi)
#
#EXAMPLE 3:
# d: exp(u*4*pi)*2
#
#EXAMPLE 4:turbulence((x,y,z),depth,soft/hard,basisnoise,amp,freq)
# d: turbulence((x,y,z), 2, 0, 3, 0.5, 2.0)
#
###################################################################
#_Interactive mesh deform function copied from:                   #
# Taper and Twist.py ( 'flippyneck' / '_Ph_' ).                   #
#_Save and Load file function copied from:                        #
# Tessalate.py ( 'JMS' ).                                         #
###################################################################

import Blender
from Blender import *
from Blender.Draw import *
from Blender.BGL import *
from Blender.Noise import *
from math import *

#------------------------------------------------------------------
save_load_as = 'formtest 01.form'
#------------------------------------------------------------------
infotext = ""
dirpath=Blender.sys.dirname(Blender.Get('filename'))
print dirpath.replace('\\','/')+'/'
form_Path=dirpath.replace('\\','/')+'/'
#-------------------
class buttons:
   global form_Path
   def __init__(self):
      self.Record={}
      self.Record['Save']=Create(0)
      self.Record['Load']=Create(0)
      self.Record['SaveAs']=Create(save_load_as)
      self.path=form_Path
      self.buttonslist=[]
      self.Effecttype = Create(2)
      self.SIZx = Create(1.0)
      self.SIZy = Create(1.0)
      self.SIZz = Create(1.0)
      self.Fdstring = Create("sin(u*2*pi)")   # preset formula #
      self.Fxstring = Create("0")
      self.Fystring = Create("0")
      self.Fzstring = Create("0")
#------------------------------------------------------------------------
   def prf_dump(self):
      global infotext
      n0=dir(self)
      f=open(self.path+self.Record['SaveAs'].val,'w')
      for n in n0:
         #print n0,
         if  (n.find('__')!=0 and n.find('prf_dump')==-1
            and n.find('prf_load')==-1 and n.find('prf_save')==-1
            and n.find('path')==-1) and n.find('Record')==-1:
            exec """l1=str(type(self.%s))"""%n
            l0=n+';'+l1+'
'
            f.write(l0)
            exec """f.write(str(self.%s))"""%n
            infotext = "  File Saved !"
            f.write('
')
      f.close()
#---------------------
   def prf_load(self):
      global infotext
      try:
         f=open(self.path+self.Record['SaveAs'].val,'r')
         buffer=f.readlines()
         f.close()
         for n in range(0,len(buffer),2):
            var=buffer[n].split(';')
            if var[0] not in self.buttonslist:
               self.buttonslist.append(var[0])
            if buffer[n].find("""<type 'str""")!=-1:
               exec """self.%s='''%s'''"""%(var[0],buffer[n+1][:-1])               
            elif buffer[n].find("""<type 'dict'>""")!=-1:
               exec """provdict=%s"""%buffer[n+1][:-1]
               for d in provdict.keys():
                  l00="""self.%s['%s'].val=%s"""%(var[0],d,provdict[d])
                  exec l00
            elif buffer[n].find("""<type 'Button'>""")!=-1:
                  exec """self.%s.val=%s"""%(var[0],buffer[n+1][:-1])
            infotext = " File Loaded !"
      except:
         infotext = "Load file: FAILED !"

B=buttons()

#-----------------------------------------------------------------------
def form_input_fu(x,y,z):
   global B, infotext

   x = (x-x/2)/B.SIZx.val
   y = (y-y/2)/B.SIZy.val
   z = (z-z/2)/B.SIZz.val
   dfunc = B.Fdstring.val
   xfunc = B.Fxstring.val
   yfunc = B.Fystring.val
   zfunc = B.Fzstring.val

   try:
      if (B.Effecttype.val==1):        # manual
         u = sqrt((x-x/2)**2+(y-y/2)**2)
         v = sqrt((y-y/2)**2+(z-z/2)**2)
         w = sqrt((z-z/2)**2+(x-x/2)**2)
         d = eval(dfunc)
         x = eval(xfunc)
         y = eval(yfunc)
         z = eval(zfunc)
      if B.Effecttype.val==2:         # spherical
         u = sqrt((x-x/2)**2+(y-y/2)**2)
         v = sqrt((y-y/2)**2+(z-z/2)**2)
         w = sqrt((z-z/2)**2+(x-x/2)**2)
         d = eval(dfunc)
         x = d
         y = d
         z = d
      if (B.Effecttype.val==3):        # cilindrical
         u = sqrt((x-x/2)**2+(y-y/2)**2)
         v = sqrt((y-y/2)**2+(z-z/2)**2)
         w = sqrt((z-z/2)**2+(x-x/2)**2)
         d = eval(dfunc)
         x = d
         y = d
         z = d
      if (B.Effecttype.val==4):        # z radial
         u = sqrt((x-x/2)**2+(y-y/2)**2)
         v = sqrt((y-y/2)**2+(z-z/2)**2)
         w = sqrt((z-z/2)**2+(x-x/2)**2)
         d = eval(dfunc)
         x = 0
         y = 0
         z *= d
      if (B.Effecttype.val==5):        # y radial
         u = sqrt((z-z/2)**2+(x-x/2)**2)
         v = sqrt((y-y/2)**2+(z-z/2)**2)
         w = sqrt((x-x/2)**2+(y-y/2)**2)
         d = eval(dfunc)
         x = 0
         y *= d
         z = 0
      if (B.Effecttype.val==6):        # x radial
         u = sqrt((y-y/2)**2+(z-z/2)**2)
         v = sqrt((z-z/2)**2+(x-x/2)**2)
         w = sqrt((x-x/2)**2+(y-y/2)**2)
         d = eval(dfunc)
         x *= d
         y = 0
         z = 0

   except:
      infotext = "Warning: input error !"

   return x,y,z

#-----------------------------------------------------------------------
def Get_And_Apply_fu():
   global B, infotext

   try:
      obj=Blender.Object.GetSelected()[0]
   except:
      infotext = "Nothing sellected!"
      return 0
   if obj:
      dat = obj.getData()
      if type(dat) != Types.NMeshType:
         infotext = "Sellect a mesh!"
         return 0
      else:
         pass
      if obj != Blender.working_object:
         Blender.working_object = obj
         Blender.base_data = obj.getData()

      mesh=obj.getData()
      normals = []
      coordinates = []
      for v in mesh.verts:
         i = mesh.verts.index(v)
         normals.append([v.no[0],v.no[1],v.no[2]])
         coordinates.append([v.co[0],v.co[1],v.co[2]])

         inp = form_input_fu(v.co[0],v.co[1],v.co[2])

         if (B.Effecttype.val==1):  # manual
            v.co[0] = coordinates[i][0] + (inp[0] * normals[i][0])
            v.co[1] = coordinates[i][1] + (inp[1] * normals[i][1])
            v.co[2] = coordinates[i][2] + (inp[2] * normals[i][2])

         if (B.Effecttype.val==2):  # spherical
            for z in range(3):
               v.co[z] = coordinates[i][z] + (inp[2] * normals[i][z])

         if (B.Effecttype.val==3):  # cilindrical
            for c in range(2):
               v.co[c] = coordinates[i][c] + (inp[2] * normals[i][c])

         else:                      # x,y,z radial
            v.co[0] = coordinates[i][0] + (inp[0] * normals[i][0])
            v.co[1] = coordinates[i][1] + (inp[1] * normals[i][1])
            v.co[2] = coordinates[i][2] + (inp[2] * normals[i][2])

      mesh.update()
      obj.makeDisplayList()

#----------------------------
def restore(object):
   m=object.getData()
   m=Blender.base_data
   m.update()
   object.makeDisplayList()
#----------------------------
Blender.working_object=None
Blender.base_data=None

#------------------------------------------------------------------------
def GUI_Box(x, y, w, h, r, g, b):
   glColor3f(r+0.075, g+0.075, b+0.075)
   glRecti(x+6, y-6, w+6, h-6)
   glColor3f(r+0.05, g+0.05, b+0.05)
   glRecti(x+5, y-5, w+5, h-5)
   glColor3f(r+0.025, g+0.025, b+0.025)
   glRecti(x+4, y-4, w+4, h-4)
   glColor3f(r, g, b)
   glRecti(x+3, y-3, w+3, h-3)
   glColor3f(r-0.025, g-0.025, b-0.025)
   glRecti(x+2, y-2, w+2, h-2)
   glColor3f(r-0.3, g-0.3, b-0.3)
   glRecti(x, y, w, h)
   glColor3f(r+0.2, g+0.2, b+0.2)
   glRecti(x+1, y+1, w-1, h-1)
   glColor3f(r-0.1,g-0.1,b-0.1)
   glLineWidth(1)
   glBegin(GL_LINES) 
   glVertex2d(250,20)
   glVertex2d(405,20)
   glEnd()
   glBegin(GL_LINES) 
   glVertex2d(330,36)
   glVertex2d(390,36)
   glEnd()
   glBegin(GL_LINES) 
   glVertex2d(180,27)
   glVertex2d(335,27)
   glEnd()
   glColor3f(0.1, 0.1, 0.1)
   glRasterPos2d(340, 24)
   Text("Formula D.")

#------------------------------------------------------------------------
def gui():
   global B, infotext
   BGL.glClearColor(0.6, 0.6, 0.6, 1)
   BGL.glClear(BGL.GL_COLOR_BUFFER_BIT)

   eft="Effect%t|Manual%x1|Spherical%x2|Cilindrical%x3|Z radial%x4|Y radial%x5|X radial%x6"
   B.Effecttype = Menu(eft, 3, 250,80,140,18, B.Effecttype.val)
   if (B.Effecttype.val==1):
      GUI_Box(10, 10, 420, 215, 0.5,0.5,0.5)
      glColor3f(1.0, 0.0, 0.0)
      glRasterPos2d(40, 195)
      Text(infotext)
      B.Fdstring=String("d: ",3,40,170,350,18,B.Fdstring.val,256,
                       "d (u,v,w, x,y,z)")
      B.Fxstring=String("x: ",3,40,145,350,18,B.Fxstring.val,256,
                       "x (d, u,v,w, x,y,z)")
      B.Fystring=String("y: ",3,40,125,350,18,B.Fystring.val,256,
                       "y (d, u,v,w, x,y,z)")
      B.Fzstring=String("z: ",3,40,105,350,18,B.Fzstring.val,256,
                       "z (d, u,v,w, x,y,z)")
   else:
      GUI_Box(10, 10, 420, 150, 0.5,0.5,0.5)
      glColor3f(1.0, 0.0, 0.0)
      glRasterPos2d(40, 130)
      Text(infotext)
      B.Fdstring=String("d: ",3,40,105,350,18,B.Fdstring.val,256,
                       "d (u,v,w, x,y,z)")

   B.SIZx=Number("x:",3,40,80,70,18,B.SIZx.val,0.001,50.0,"size X")
   B.SIZy=Number("y:",3,110,80,70,18,B.SIZy.val,0.001,50.0,"size Y")
   B.SIZz=Number("z:",3,180,80,70,18,B.SIZz.val,0.001,50.0,"size Z")

   Button("Apply",12,40,55,70,18,"Apply deformation.")
   Button("Restore",11,110,55,70,18,"Restore to original mesh.")
   Button("Redraw",3,180,55,70,18," Redraw mesh.")
   Button("Reset",4,250,55,70,18,"Restore to original and Reset input.")
   Button("Exit",1,320,55,70,18,"Exit and Restore to original.")

   lstip="Save/Load file name"
   BRSAtxt=B.Record['SaveAs'].val
   B.Record['SaveAs']=String("File: ",3,180,35,140,18,BRSAtxt,256,lstip)
   B.Record['Save']=Button("Save", 5, 40, 35, 70, 18)
   B.Record['Load']=Button("Load", 6, 110, 35, 70, 18)


#---------------------------------------
def event(evt, val):
   if (evt == ESCKEY and not val):
      name = "OK?%t|Exit %x1"
      result = Blender.Draw.PupMenu(name)
      if result == 1:
         Exit()
#---------------------------------------
def bevent(evt):
   global B, infotext

   if evt == 1:
      name = "OK?%t|Exit %x1"
      result = Blender.Draw.PupMenu(name)
      if result == 1:
         Exit()

   if evt == 5:  # Save file #
      infotext = ""
      name = "OK?%t|Save %x1"
      result = Blender.Draw.PupMenu(name)
      if result == 1:
         B.prf_dump()
         Blender.Window.Redraw()
   if evt == 6:   # Load file #
      infotext = ""
      name = "OK?%t|Load %x1"
      result = Blender.Draw.PupMenu(name)
      if result == 1:
         B.prf_load()
         Blender.Window.Redraw()

   if evt == 4:   # Reset value's , and Restore mesh #
      infotext = ""
      name = "OK?%t|Reset %x1"
      result = Blender.Draw.PupMenu(name)
      if result == 1:
         B.SIZx  = Create(1.0)
         B.SIZy  = Create(1.0)
         B.SIZz  = Create(1.0)
         B.Fdstring = Create("0")
         B.Fxstring = Create("0")
         B.Fystring = Create("0")
         B.Fzstring = Create("0")
         Draw()
   if evt == 11:   # Restore mesh #
      infotext = ""
      if Blender.working_object:
         restore(Blender.working_object)
      return 0
   if evt == 12:   # Apply deformation #
      infotext = ""
      name = "OK?%t|Apply deformation %x1"
      result = Blender.Draw.PupMenu(name)
      if result == 1:
         obj=Blender.Object.GetSelected()[0]
         m=obj.getData()
         Blender.base_data=m
         restore(obj)
         infotext = "Mesh 'Deformed'."
         return 0

   if Blender.working_object:
         restore(Blender.working_object)
   if evt == 3:   # Update mesh #
      infotext = ""
      Get_And_Apply_fu()
      Draw()


Register(gui, event, bevent)