diff options
Diffstat (limited to 'release')
-rw-r--r-- | release/scripts/ac3d_export.py | 15 | ||||
-rw-r--r-- | release/scripts/bpymodules/svg2obj.py | 59 | ||||
-rw-r--r-- | release/scripts/console.py | 102 | ||||
-rw-r--r-- | release/scripts/fixfromarmature.py | 36 | ||||
-rw-r--r-- | release/scripts/help_browser.py | 44 | ||||
-rw-r--r-- | release/scripts/obj_export.py | 6 | ||||
-rw-r--r-- | release/scripts/obj_import.py | 458 | ||||
-rw-r--r-- | release/scripts/save_theme.py | 9 | ||||
-rw-r--r-- | release/scripts/tex2uvbaker.py | 368 |
9 files changed, 740 insertions, 357 deletions
diff --git a/release/scripts/ac3d_export.py b/release/scripts/ac3d_export.py index 85d1ac5ceff..b9b7b8e5ae6 100644 --- a/release/scripts/ac3d_export.py +++ b/release/scripts/ac3d_export.py @@ -10,7 +10,7 @@ Tip: 'Export selected meshes to AC3D (.ac) format' __author__ = "Willian P. Germano" __url__ = ("blender", "elysiun", "AC3D's homepage, http://www.ac3d.org", "PLib 3d gaming lib, http://plib.sf.net") -__version__ = "2.36 2005-04-14" +__version__ = "2.37a 2005-06-09" __bpydoc__ = """\ This script exports selected Blender meshes to AC3D's .ac file format. @@ -47,6 +47,8 @@ left without mats -- it's better to always add your own materials;<br> - set texture dir: override the actual textures path with a given default path (or simply export the texture names, without dir info, if the path is empty);<br> + - only selected: only consider selected objects when looking for meshes +to export (read notes below about tokens, too);<br> strings: - export dir: default dir to export to;<br> - texture dir: override textures path with this path if 'set texture dir' @@ -118,6 +120,7 @@ SET_TEX_DIR = True TEX_DIR = '' AC3D_4 = True # export crease value, compatible with AC3D 4 loaders NO_SPLIT = False +ONLY_SELECTED = True EXPORT_DIR = '' tooltips = { @@ -130,6 +133,7 @@ tooltips = { 'TEX_DIR': "(see \"set tex dir\") dir to prepend to all exported texture names (leave empty for no dir)", 'AC3D_4': "compatibility mode, adds 'crease' tag and slightly better material support", 'NO_SPLIT': "don't split meshes with multiple textures (or both textured and non textured polygons)", + 'ONLY_SELECTED': "export only selected objects" } def update_RegistryInfo(): @@ -143,6 +147,7 @@ def update_RegistryInfo(): d['AC3D_4'] = AC3D_4 d['NO_SPLIT'] = NO_SPLIT d['EXPORT_DIR'] = EXPORT_DIR + d['ONLY_SELECTED'] = ONLY_SELECTED d['tooltips'] = tooltips Blender.Registry.SetKey(REG_KEY, d, True) @@ -159,6 +164,7 @@ if rd: SET_TEX_DIR = rd['SET_TEX_DIR'] TEX_DIR = rd['TEX_DIR'] EXPORT_DIR = rd['EXPORT_DIR'] + ONLY_SELECTED = rd['ONLY_SELECTED'] NO_SPLIT = rd['NO_SPLIT'] except KeyError: update_RegistryInfo() @@ -673,10 +679,13 @@ def fs_callback(filename): # -- End of definitions -OBJS = Blender.Object.GetSelected() +if ONLY_SELECTED: + OBJS = Blender.Object.GetSelected() +else: + OBJS = Blender.Scene.GetCurrent().getChildren() if not OBJS: - Blender.Draw.PupMenu('ERROR: No objects selected') + Blender.Draw.PupMenu('ERROR: no objects selected') else: fname = bsys.makename(ext=".ac") if EXPORT_DIR: diff --git a/release/scripts/bpymodules/svg2obj.py b/release/scripts/bpymodules/svg2obj.py index e7837b9bb15..11d21991bc5 100644 --- a/release/scripts/bpymodules/svg2obj.py +++ b/release/scripts/bpymodules/svg2obj.py @@ -42,8 +42,19 @@ Yet done: c : relative curve to 2004/08/03 s : relative curve to with only one handle -To do: A,S,V,H,Q,T, - a,s, m, v, h, q,t + + A : courbe_vers_a, + V : ligne_tracee_v, + H : ligne_tracee_h, + Z : boucle_z, + Q : courbe_vers_q, + T : courbe_vers_t, + a : courbe_vers_a, + v : ligne_tracee_v, + h : ligne_tracee_h, + z : boucle_z, + q : courbe_vers_q, + Changelog: 0.1.1 : - control file without extension @@ -53,11 +64,13 @@ Changelog: instead of x,y,width and height 0.2.2 : - read compact path data from Illustrator 10 0.2.3 : - read a few new relative displacements - 0.2.4 : - better hash for command with followed by a lone data + 0.2.4 : - better hash for command followed by a lone data (h,v) or uncommun number (a) 0.2.5 : - correction for gimp import 0.2.6 : - correction for illustrator 10 SVG 0.2.7 : - correction for inskape 0.40 cvs SVG + 0.2.8 : - correction for inskape plain SVG + ================================================================================== ==================================================================================""" @@ -290,15 +303,17 @@ def contruit_SYMETRIC(l): def mouvement_vers(c, D, n0,CP): global DEBUG,TAGcourbe - #print c,D[c[1]+1] + print 'c',c,'D[c[1]+1]',D[c[1]+1] l=filtre_DATA(c,D,1) - #print l + print 'l',l if n0 in courbes.ITEM.keys(): n0+=1 - CP=[l[0],l[1]] - else: - CP=[l[0],l[1]] + # + # CP=[l[0],l[1]] + #else: + # CP=[l[0],l[1]] + CP=[l[0],l[1]] courbes.ITEM[n0]=ITEM() courbes.ITEM[n0].Origine=[l[0],l[1]] @@ -522,10 +537,19 @@ def get_BOUNDBOX(BOUNDINGBOX,SVG,viewbox): return BOUNDINGBOX +# 0.2.8 : - correction for inskape 0.40 cvs SVG +def repack_DATA(DATA): + for d in Actions.keys(): + DATA=DATA.replace(d,d+' ') + return DATA + + def unpack_DATA(DATA): DATA[0]=DATA[0].replace('-',',-') + for d in Actions.keys(): DATA[0]=DATA[0].replace(d,','+d+',') + DATA[0]=DATA[0].replace(',,',',') if DATA[0][0]==',':DATA[0]=DATA[0][1:] if DATA[0][-1]==',':DATA[0]=DATA[0][:-1] @@ -575,9 +599,12 @@ def format_PATH(t): if PATH.find(' d="')!=-1: PATH,D=get_content('d',PATH) - - #print "D0= :",D - + + # 0.2.8 : - correction for inskape plain SVG + if D.find(',')==-1: + D=repack_DATA(D) + # 0.2.8 : end + D=D.split(' ') try: @@ -586,17 +613,12 @@ def format_PATH(t): except: pass - #print len(D) - #for D0 in D: - #print " ----> D = :", D0 - if len(D)==1 or len(D[0])>1: D1=[] for D0 in D: D1+=unpack_DATA([D0])[:] D=D1 - - #print "D2= :",D + return t,D @@ -627,8 +649,6 @@ def scan_FILE(nom): else: BOUNDINGBOX = get_BOUNDBOX(BOUNDINGBOX,SVG,viewbox) - #print t - while t.find('path')!=-1: t,D=format_PATH(t) cursor=0 @@ -670,4 +690,3 @@ def fonctionSELECT(nom): if DEVELOPPEMENT==1: Blender.Window.FileSelector (fonctionSELECT, 'SELECT a .SVG FILE') - #sys.path=oldpath diff --git a/release/scripts/console.py b/release/scripts/console.py index 1fbf7908c7a..e95d6bc34b1 100644 --- a/release/scripts/console.py +++ b/release/scripts/console.py @@ -2,22 +2,24 @@ """ Name: 'Interactive Console' -Blender: 236 +Blender: 237 Group: 'System' Tooltip: 'Interactive Python Console' """ + __author__ = "Campbell Barton AKA Ideasman" -__url__ = ["http://members.iinet.net.au/~cpbarton/ideasman/", "blender", "elysiun", "Official Python site, http://www.python.org"] +__url__ = ["Author's homepage, http://members.iinet.net.au/~cpbarton/ideasman/", "blender", "elysiun", "Official Python site, http://www.python.org"] __bpydoc__ = """\ This is an interactive console, similar to Python's own command line interpreter. Since it is embedded in Blender, it has access to all Blender Python modules. -Those completely new to Python can check the link button above that points to -its official homepage, with news, downloads and documentation. +Those completely new to Python are recommended to check the link button above +that points to its official homepage, with news, downloads and documentation. Usage:<br> Type your code and hit "Enter" to get it executed.<br> - - Right mouse click: Save output;<br> + - Right mouse click: Console Menu (Save output, etc);<br> - Arrow keys: command history and cursor;<br> + - Shift + arrow keys: jump words;<br> - Ctrl + Tab: auto compleate based on variable names and modules loaded -- multiple choices popup a menu;<br> - Ctrl + Enter: multiline functions -- delays executing code until only Enter is pressed. """ @@ -31,9 +33,13 @@ import types # Constants __DELIMETERS__ = '. ,=+-*/%<>&~][{}():' __LINE_HISTORY__ = 200 + +global __LINE_HEIGHT__ __LINE_HEIGHT__ = 14 +global __FONT_SIZE__ __FONT_SIZE__ = "normal" + ''' # Generic Blender functions def getActScriptWinRect(): @@ -255,8 +261,10 @@ def handle_event(evt, val): cmdBuffer[-1].cmd = cmdBuffer[histIndex].cmd def actionRightMouse(): - choice = Draw.PupMenu('Console Menu%t|Write Input Data (white)|Write Output Data (blue)|Write Error Data (red)|Write All Text|%l|Insert Blender text|%l|Quit') - print choice + global __FONT_SIZE__ + global __LINE_HEIGHT__ + choice = Draw.PupMenu('Console Menu%t|Write Input Data (white)|Write Output Data (blue)|Write Error Data (red)|Write All Text|%l|Insert Blender text|%l|Font Size|%l|Help|%l|Quit') + # print choice if choice == 1: writeCmdData(cmdBuffer, 0) # type 0 user elif choice == 2: @@ -267,7 +275,26 @@ def handle_event(evt, val): writeCmdData(cmdBuffer, 3) # All elif choice == 6: insertCmdData(cmdBuffer) # All - elif choice == 8: # Exit + elif choice == 8: + # Fontsize. + font_choice = Draw.PupMenu('Font Size%t|Large|Normal|Small|Tiny') + if font_choice != -1: + if font_choice == 1: + __FONT_SIZE__ = 'large' + __LINE_HEIGHT__ = 16 + elif font_choice == 2: + __FONT_SIZE__ = 'normal' + __LINE_HEIGHT__ = 14 + elif font_choice == 3: + __FONT_SIZE__ = 'small' + __LINE_HEIGHT__ = 12 + elif font_choice == 4: + __FONT_SIZE__ = 'tiny' + __LINE_HEIGHT__ = 10 + Draw.Redraw() + elif choice == 10: + Blender.ShowHelp('console.py') + elif choice == 12: # Exit Draw.Exit() @@ -356,12 +383,52 @@ def handle_event(evt, val): if (evt == Draw.UPARROWKEY and val): actionUpKey() elif (evt == Draw.DOWNARROWKEY and val): actionDownKey() - elif (evt == Draw.RIGHTARROWKEY and val): - cursor +=1 - if cursor > -1: - cursor = -1 + elif (evt == Draw.RIGHTARROWKEY and val): + if Window.GetKeyQualifiers() & Window.Qual.SHIFT: + wordJump = False + newCursor = cursor+1 + while newCursor<0: + + if cmdBuffer[-1].cmd[newCursor] not in __DELIMETERS__: + newCursor+=1 + else: + wordJump = True + break + if wordJump: # Did we find a new cursor pos? + cursor = newCursor + else: + cursor = -1 # end of line + else: + cursor +=1 + if cursor > -1: + cursor = -1 + elif (evt == Draw.LEFTARROWKEY and val): - cursor -=1 + if Window.GetKeyQualifiers() & Window.Qual.SHIFT: + wordJump = False + newCursor = cursor-1 + while abs(newCursor) < len(cmdBuffer[-1].cmd): + + if cmdBuffer[-1].cmd[newCursor] not in __DELIMETERS__ or\ + newCursor == cursor: + newCursor-=1 + else: + wordJump = True + break + if wordJump: # Did we find a new cursor pos? + cursor = newCursor + else: + cursor = -len(cmdBuffer[-1].cmd) # Start of line + + else: + if len(cmdBuffer[-1].cmd) > abs(cursor): + cursor -=1 + + elif (evt == Draw.HOMEKEY and val): + cursor = -len(cmdBuffer[-1].cmd) + + elif (evt == Draw.ENDKEY and val): + cursor = -1 elif (evt == Draw.TABKEY and val): if Window.GetKeyQualifiers() & Window.Qual.CTRL: @@ -391,7 +458,6 @@ def draw_gui(): BGL.glGetFloatv(BGL.GL_SCISSOR_BOX, __CONSOLE_RECT__) __CONSOLE_RECT__= __CONSOLE_RECT__.list - # Clear the screen BGL.glClearColor(0.0, 0.0, 0.0, 1.0) BGL.glClear(BGL.GL_COLOR_BUFFER_BIT) # use it to clear the color buffer @@ -399,7 +465,10 @@ def draw_gui(): # Draw cursor location colour cmd2curWidth = Draw.GetStringWidth(cmdBuffer[-1].cmd[:cursor], __FONT_SIZE__) BGL.glColor3f(0.8, 0.2, 0.2) - BGL.glRecti(cmd2curWidth-1,4,cmd2curWidth+1, 20) + if cmd2curWidth == 0: + BGL.glRecti(0,2,2, __LINE_HEIGHT__+2) + else: + BGL.glRecti(cmd2curWidth-2,2,cmd2curWidth, __LINE_HEIGHT__+2) BGL.glColor3f(1,1,1) # Draw the set of cammands to the buffer @@ -469,8 +538,9 @@ __CONSOLE_VAR_DICT__ = {} # Initialize var dict # Print Startup lines cmdBuffer = [cmdLine("Welcome to Ideasman's Blender Console", 1, None),\ - cmdLine(' * Right Click: Save output', 1, None),\ + cmdLine(' * Right Click: Console Menu (Save output, etc.)', 1, None),\ cmdLine(' * Arrow Keys: Command history and cursor', 1, None),\ + cmdLine(' * Shift With Arrow Keys: Jump words', 1, None),\ cmdLine(' * Ctrl + Tab: Auto compleate based on variable names and modules loaded, multiple choices popup a menu', 1, None),\ cmdLine(' * Ctrl + Enter: Multiline functions, delays executing code until only Enter is pressed.', 1, None)] diff --git a/release/scripts/fixfromarmature.py b/release/scripts/fixfromarmature.py index a9fea501b87..b43cdb0a1e2 100644 --- a/release/scripts/fixfromarmature.py +++ b/release/scripts/fixfromarmature.py @@ -11,14 +11,14 @@ __author__ = "Jean-Michel Soler (jms)" __url__ = ("blender", "elysiun", "Script's homepage, http://jmsoler.free.fr/util/blenderfile/py/fixfromarmature.py", "Communicate problems and errors, http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender") -__version__ = "05/2005" +__version__ = "06/2005" __bpydoc__ = """\ This script creates a copy of the active mesh with deformations fixed. Usage: -Select the mesh and run this script. A fixed copy of it will be created. +Select the deformed mesh and run this script. A fixed copy of it will be created. """ # $Id$ @@ -72,21 +72,21 @@ def fix_mesh(nomdelobjet): Obis.setMatrix(Ozero.getMatrix()) scene = Blender.Scene.getCurrent() scene.link (Obis) - - Mesh2=Obis.getData() - Mesh1=Ozero.getData() - - if len(Mesh2.verts)==len(Mesh1.verts): - for VertGroupName in Mesh1.getVertGroupNames(): - VertexList = Mesh1.getVertsFromGroup(VertGroupName, True) - Mesh2.addVertGroup(VertGroupName) - for Vertex in VertexList: - Mesh2.assignVertsToGroup(VertGroupName, [Vertex[0]], Vertex[1], 'add') - else: - for vgroupname in Mesh1.getVertGroupNames(): - Mesh2.addVertGroup(vgroupname) - Mesh2.update() - + try : + Mesh2=Obis.getData() + Mesh1=Ozero.getData() + if len(Mesh2.verts)==len(Mesh1.verts): + for VertGroupName in Mesh1.getVertGroupNames(): + VertexList = Mesh1.getVertsFromGroup(VertGroupName, True) + Mesh2.addVertGroup(VertGroupName) + for Vertex in VertexList: + Mesh2.assignVertsToGroup(VertGroupName, [Vertex[0]], Vertex[1], 'add') + else: + for vgroupname in Mesh1.getVertGroupNames(): + Mesh2.addVertGroup(vgroupname) + Mesh2.update() + except: + print "mesh has no vertex group " Ozero=Blender.Object.GetSelected()[0] @@ -110,5 +110,5 @@ else: elif softbodies==1: for f in range(1, curframe + 1): Blender.Set('curframe',f) + Blender.Window.RedrawAll() if fix: fix_mesh(Ozero.getName()) - diff --git a/release/scripts/help_browser.py b/release/scripts/help_browser.py index aa05c988207..d321ffa6256 100644 --- a/release/scripts/help_browser.py +++ b/release/scripts/help_browser.py @@ -71,7 +71,7 @@ Hotkeys:<br> # -------------------------------------------------------------------------- import Blender -from Blender import sys as bsys, Draw, Window +from Blender import sys as bsys, Draw, Window, Registry WEBBROWSER = True try: @@ -390,7 +390,7 @@ def parse_help_info(script): fname = bsys.join(path, script.fname) if not bsys.exists(fname): - Draw.PupMenu('IO Error: Couldn\'t find script %s' % fname) + Draw.PupMenu('IO Error: couldn\'t find script %s' % fname) return None f = file(fname, 'r') @@ -545,7 +545,7 @@ def gui(): # drawing the screen global SCRIPT_INFO, AllGroups, GROUP_MENUS global BEVT_EMAIL, BEVT_LINK global BEVT_VIEWSOURCE, BEVT_EXIT, BEVT_BACK, BEVT_GMENU, BUT_GMENU - global PADDING, WIN_W, WIN_H, SCROLL_DOWN, COLUMNS + global PADDING, WIN_W, WIN_H, SCROLL_DOWN, COLUMNS, FMODE theme = Theme.Get()[0] tui = theme.get('ui') @@ -667,7 +667,7 @@ def gui(): # drawing the screen 'View this script\'s source code in the Text Editor (hotkey: S)') Draw.PushButton('exit', BEVT_EXIT, x + 45, 17, 45, bh, 'Exit from Scripts Help Browser (hotkey: Q)') - Draw.PushButton('back', BEVT_BACK, x + 2*45, 17, 45, bh, + if not FMODE: Draw.PushButton('back', BEVT_BACK, x + 2*45, 17, 45, bh, 'Back to scripts selection screen (hotkey: ESC)') BGL.glColor3ub(COL_TXTHI[0],COL_TXTHI[1], COL_TXTHI[2]) BGL.glRasterPos2i(x, 5) @@ -686,12 +686,12 @@ def fit_scroll(): def event(evt, val): # input events global SCREEN, START_SCREEN, SCRIPT_SCREEN - global SCROLL_DOWN + global SCROLL_DOWN, FMODE if not val: return if evt == Draw.ESCKEY: - if SCREEN == START_SCREEN: Draw.Exit() + if SCREEN == START_SCREEN or FMODE: Draw.Exit() else: SCREEN = START_SCREEN SCROLL_DOWN = 0 @@ -719,7 +719,7 @@ def button_event(evt): # gui button events global SCREEN, START_SCREEN, SCRIPT_SCREEN global BEVT_LINK, BEVT_EMAIL, BEVT_GMENU, BUT_GMENU, SCRIPT_INFO - global SCROLL_DOWN + global SCROLL_DOWN, FMODE if evt >= 100: # group menus for i in range(len(BUT_GMENU)): @@ -754,10 +754,36 @@ def button_event(evt): # gui button events Draw.Exit() return elif evt == BEVT_BACK: - if SCREEN == SCRIPT_SCREEN: + if SCREEN == SCRIPT_SCREEN and not FMODE: SCREEN = START_SCREEN SCRIPT_INFO = None SCROLL_DOWN = 0 Draw.Redraw() -Draw.Register(gui, event, button_event) +keepon = True +FMODE = False # called by Blender.ShowHelp(name) API function ? + +KEYNAME = '__help_browser' +rd = Registry.GetKey(KEYNAME) +if rd: + rdscript = rd['script'] + keepon = False + Registry.RemoveKey(KEYNAME) + for group in AllGroups: + for script in group.get_scripts(): + if rdscript == script.fname: + parseit = parse_help_info(script) + if parseit == True: + keepon = True + SCREEN = SCRIPT_SCREEN + BEVT_LINK = range(20, len(SCRIPT_INFO.d['__url__']) + 20) + BEVT_EMAIL = range(50, len(SCRIPT_INFO.d['__email__']) + 50) + FMODE = True + elif parseit == False: + Draw.PupMenu("ERROR: script doesn't have proper help data") + break + +if not keepon: + Draw.PupMenu("ERROR: couldn't find script") +else: + Draw.Register(gui, event, button_event) diff --git a/release/scripts/obj_export.py b/release/scripts/obj_export.py index d51658b2598..b6ef15a47e3 100644 --- a/release/scripts/obj_export.py +++ b/release/scripts/obj_export.py @@ -57,10 +57,10 @@ NULL_IMG = '(null)' # from docs at http://astronomy.swin.edu.au/~pbourke/geomfor def save_mtl(filename): file = open(filename, "w") for mat in Material.Get(): - + file.write('newmtl %s\n' % (mat.getName())) # Define a new material - # Hardness, convert blenders 1-511 to MTL's + # Hardness, convert blenders 1-511 to MTL's file.write('Ns %s\n' % ((mat.getHardness()-1) * 1.9607843137254901 ) ) col = mat.getRGBCol() @@ -163,7 +163,7 @@ def save_obj(filename): if f.image.filename != currentImgName: currentImgName = f.image.filename # Set a new image for all following faces - file.write( 'usemapusemap %s\n' % currentImgName.split('\\')[-1].split('/')[-1] ) + file.write( 'usemap %s\n' % currentImgName.split('\\')[-1].split('/')[-1] ) elif currentImgName != NULL_IMG: # Not using an image so set to NULL_IMG currentImgName = NULL_IMG diff --git a/release/scripts/obj_import.py b/release/scripts/obj_import.py index 2913cc015ec..6930ef86ef5 100644 --- a/release/scripts/obj_import.py +++ b/release/scripts/obj_import.py @@ -2,7 +2,7 @@ """ Name: 'Wavefront (.obj)...' -Blender: 237 +Blender: 232 Group: 'Import' Tooltip: 'Load a Wavefront OBJ File' """ @@ -76,17 +76,7 @@ def stripName(name): # name is a string from Blender import * - -#==================================================================================# -# This gets a mat or creates one of the requested name if none exist. # -#==================================================================================# -def getMat(matName): - # Make a new mat - try: - return Material.Get(matName) - except: - return Material.New(matName) - +import sys as py_sys #==================================================================================# # This function sets textures defined in .mtl file # @@ -99,8 +89,8 @@ def getImg(img_fileName): # if we are this far it means the image hasnt been loaded. try: return Image.Load(img_fileName) - except: - print "unable to open", img_fileName + except IOError: + print '\tunable to open image file: "%s"' % img_fileName return @@ -108,48 +98,56 @@ def getImg(img_fileName): #==================================================================================# # This function sets textures defined in .mtl file # #==================================================================================# -def load_mat_image(mat, img_fileName, type, mesh): - try: - image = Image.Load(img_fileName) - except: - print "unable to open", img_fileName - return +def load_mat_image(mat, img_fileName, type, meshDict): + texture = Texture.New(type) texture.setType('Image') - texture.image = image + + image = getImg(img_fileName) + if image: + texture.image = image # adds textures to faces (Textured/Alt-Z mode) # Only apply the diffuse texture to the face if the image has not been set with the inline usemat func. if type == 'Kd': - for f in mesh.faces: - if mesh.materials[f.mat].name == mat.name: - - # the inline usemat command overides the material Image - if not f.image: - f.image = image - + for meshPair in meshDict.values(): + for f in meshPair[0].faces: + if meshPair[0].materials[f.mat].name == mat.name: + # the inline usemat command overides the material Image + if not f.image: + f.image = image + # adds textures for materials (rendering) - if type == 'Ka': + elif type == 'Ka': mat.setTexture(0, texture, Texture.TexCo.UV, Texture.MapTo.CMIR) - if type == 'Kd': + elif type == 'Kd': mat.setTexture(1, texture, Texture.TexCo.UV, Texture.MapTo.COL) - if type == 'Ks': + elif type == 'Ks': mat.setTexture(2, texture, Texture.TexCo.UV, Texture.MapTo.SPEC) #==================================================================================# # This function loads materials from .mtl file (have to be defined in obj file) # #==================================================================================# -def load_mtl(dir, mtl_file, mesh): - # Remove ./ - if mtl_file.endswith('./'): - mtl_file= mtl_file[2:] +def load_mtl(dir, mtl_file, meshDict): + #===============================================================================# + # This gets a mat or creates one of the requested name if none exist. # + #===============================================================================# + def getMat(matName): + # Make a new mat + try: + return Material.Get(matName) + except NameError: + return Material.New(matName) + + mtl_file = stripPath(mtl_file) mtl_fileName = dir + mtl_file + try: fileLines= open(mtl_fileName, 'r').readlines() - except: - print "unable to open", mtl_fileName + except IOError: + print '\tunable to open referenced material file: "%s"' % mtl_fileName return lIdx=0 @@ -162,7 +160,7 @@ def load_mtl(dir, mtl_file, mesh): elif l[0] == '#' or len(l) == 0: pass elif l[0] == 'newmtl': - currentMat = getMat(' '.join(l[1:])) + currentMat = getMat('_'.join(l[1:])) # Material should alredy exist. elif l[0] == 'Ka': currentMat.setMirCol(float(l[1]), float(l[2]), float(l[3])) elif l[0] == 'Kd': @@ -177,56 +175,59 @@ def load_mtl(dir, mtl_file, mesh): currentMat.setAlpha(float(l[1])) elif l[0] == 'map_Ka': img_fileName = dir + l[1] - load_mat_image(currentMat, img_fileName, 'Ka', mesh) + load_mat_image(currentMat, img_fileName, 'Ka', meshDict) elif l[0] == 'map_Ks': img_fileName = dir + l[1] - load_mat_image(currentMat, img_fileName, 'Ks', mesh) + load_mat_image(currentMat, img_fileName, 'Ks', meshDict) elif l[0] == 'map_Kd': img_fileName = dir + l[1] - load_mat_image(currentMat, img_fileName, 'Kd', mesh) + load_mat_image(currentMat, img_fileName, 'Kd', meshDict) lIdx+=1 #===========================================================================# # Returns unique name of object/mesh (preserve overwriting existing meshes) # #===========================================================================# def getUniqueName(name): + newName = name uniqueInt = 0 while 1: try: - ob = Object.Get(name) + ob = Object.Get(newName) # Okay, this is working, so lets make a new name - name = '%s.%d' % (name, uniqueInt) + newName = '%s.%d' % (name, uniqueInt) uniqueInt +=1 - except: - if name not in NMesh.GetNames(): - return name + except AttributeError: + if newName not in NMesh.GetNames(): + return newName else: - name = '%s.%d' % (name, uniqueInt) + newName = '%s.%d' % (name, uniqueInt) uniqueInt +=1 + +# Gets the meshs index for this material, -1 if its not in the list +def getMeshMaterialIndex(mesh, material): + meshMatIndex = -1 + matIdx = 0 + meshMatList = mesh.materials + while matIdx < len(meshMatList): + if meshMatList[matIdx].name == material.name: + meshMatIndex = matIdx # The current mat index. + break + matIdx+=1 + # -1 if not found + return meshMatIndex + + + + #==================================================================================# # This loads data from .obj file # #==================================================================================# def load_obj(file): time1 = sys.time() - def applyMat(mesh, f, mat): - # Check weather the 16 mat limit has been met. - if len( meshList[objectName][0].materials ) >= MATLIMIT: - print 'Warning, max material limit reached, using an existing material' - return meshList[objectName][0] - - mIdx = 0 - for m in meshList[objectName][0].materials: - if m.getName() == mat.getName(): - break - mIdx+=1 - - if mIdx == len(mesh.materials): - meshList[objectName][0].addMaterial(mat) - - f.mat = mIdx - return f - + + TEX_OFF_FLAG = ~NMesh.FaceModes['TEX'] + # Get the file name with no path or .obj fileName = stripName( stripPath(file) ) @@ -235,56 +236,76 @@ def load_obj(file): DIR = pathName(file, stripPath(file)) fileLines = open(file, 'r').readlines() - - - + uvMapList = [(0,0)] # store tuple uv pairs here # This dummy vert makes life a whole lot easier- # pythons index system then aligns with objs, remove later vertList = [NMesh.Vert(0, 0, 0)] - - nullMat = getMat(NULL_MAT) + + # Store all imported materials in a dict, names are key + materiaDict = {} + + # Store all imported images in a dict, names are key + imageDict = {} + + # This stores the index that the current mesh has for the current material. + # if the mesh does not have the material then set -1 + contextMeshMatIdx = -1 + + # Keep this out of the dict for easy accsess. + nullMat = Material.New(NULL_MAT) currentMat = nullMat # Use this mat. currentImg = NULL_IMG # Null image is a string, otherwise this should be set to an image object.\ - currentSmooth = 0 + currentSmooth = 1 - #==================================================================================# - # Make split lines, ignore blenk lines or comments. # - #==================================================================================# - lIdx = 0 - while lIdx < len(fileLines): - fileLines[lIdx] = fileLines[lIdx].split() - lIdx+=1 + # Store a list of unnamed names + currentUnnamedGroupIdx = 0 + currentUnnamedObjectIdx = 0 + + quadList = (0, 1, 2, 3) #==================================================================================# # Load all verts first (texture verts too) # #==================================================================================# + nonVertFileLines = [] lIdx = 0 - print 'file length: %d' % len(fileLines) + print '\tfile length: %d' % len(fileLines) while lIdx < len(fileLines): - l = fileLines[lIdx] - if len(l) == 0: - fileLines.pop(lIdx) - lIdx-=1 - - elif l[0] == 'v': - # This is a new vert, make a new mesh - vertList.append( NMesh.Vert(float(l[1]), float(l[2]), float(l[3]) ) ) - fileLines.pop(lIdx) - lIdx-=1 - + # Dont Bother splitting empty or comment lines. + if len(fileLines[lIdx]) == 0: + pass + elif fileLines[lIdx][0] == '\n': + pass + elif fileLines[lIdx][0] == '#': + pass - # UV COORDINATE - elif l[0] == 'vt': - # This is a new vert, make a new mesh - uvMapList.append( (float(l[1]), float(l[2])) ) - fileLines.pop(lIdx) - lIdx-=1 + else: + fileLines[lIdx] = fileLines[lIdx].split() + l = fileLines[lIdx] + + # Splitting may + if len(l) == 0: + pass + # Verts + elif l[0] == 'v': + vertList.append( NMesh.Vert(float(l[1]), float(l[2]), float(l[3]) ) ) + + # UV COORDINATE + elif l[0] == 'vt': + uvMapList.append( (float(l[1]), float(l[2])) ) + else: + nonVertFileLines.append(l) lIdx+=1 + del fileLines + fileLines = nonVertFileLines + del nonVertFileLines + + # Make a list of all unused vert indicies that we can copy from + VERT_USED_LIST = [-1]*len(vertList) # Here we store a boolean list of which verts are used or not # no we know weather to add them to the current mesh @@ -295,10 +316,13 @@ def load_obj(file): # objectName has a char in front of it that determins weather its a group or object. # We ignore it when naming the object. objectName = 'omesh' # If we cant get one, use this - meshList = {} - meshList[objectName] = (NMesh.GetRaw(), [-1]*len(vertList)) # Mesh/meshList[objectName][1] - meshList[objectName][0].verts.append(vertList[0]) - meshList[objectName][0].hasFaceUV(1) + + meshDict = {} + currentMesh = NMesh.GetRaw() + meshDict[objectName] = (currentMesh, VERT_USED_LIST[:]) # Mesh/meshDict[objectName][1] + currentMesh.verts.append(vertList[0]) + currentMesh.hasFaceUV(1) + #==================================================================================# # Load all faces into objects, main loop # @@ -308,29 +332,21 @@ def load_obj(file): while lIdx < len(fileLines): l = fileLines[lIdx] - # VERTEX - if l[0] == 'v': - pass - - # Comment - if l[0] == '#': - pass - - # VERTEX NORMAL - elif l[0] == 'vn': - pass - - # UV COORDINATE - elif l[0] == 'vt': - pass - # FACE - elif l[0] == 'f': + if l[0] == 'f': # Make a face with the correct material. f = NMesh.Face() - f = applyMat(meshList[objectName][0], f, currentMat) - f.smooth = currentSmooth - if currentImg != NULL_IMG: f.image = currentImg + + # Add material to mesh + if contextMeshMatIdx == -1: + tmpMatLs = currentMesh.materials + + if len(tmpMatLs) == MATLIMIT: + contextMeshMatIdx = 0 # Use first material + print 'material overflow, attempting to use > 16 materials. defaulting to first.' + else: + contextMeshMatIdx = len(tmpMatLs) + currentMesh.addMaterial(currentMat) # Set up vIdxLs : Verts # Set up vtIdxLs : UV @@ -341,7 +357,7 @@ def load_obj(file): for v in l[1:]: # OBJ files can have // or / to seperate vert/texVert/normal # this is a bit of a pain but we must deal with it. - objVert = v.split('/', -1) + objVert = v.split('/') # Vert Index - OBJ supports negative index assignment (like python) @@ -349,8 +365,9 @@ def load_obj(file): if fHasUV: # UV if len(objVert) == 1: - vtIdxLs.append(int(objVert[0])) # Sticky UV coords - elif objVert[1] != '': # Its possible that theres no texture vert just he vert and normal eg 1//2 + #vtIdxLs.append(int(objVert[0])) # replace with below. + vtIdxLs.append(vIdxLs[-1]) # Sticky UV coords + elif objVert[1]: # != '' # Its possible that theres no texture vert just he vert and normal eg 1//2 vtIdxLs.append(int(objVert[1])) # Seperate UV coords else: fHasUV = 0 @@ -365,13 +382,13 @@ def load_obj(file): # Quads only, we could import quads using the method below but it polite to import a quad as a quad. if len(vIdxLs) == 4: - for i in [0,1,2,3]: - if meshList[objectName][1][vIdxLs[i]] == -1: - meshList[objectName][0].verts.append(vertList[vIdxLs[i]]) - f.v.append(meshList[objectName][0].verts[-1]) - meshList[objectName][1][vIdxLs[i]] = len(meshList[objectName][0].verts)-1 + for i in quadList: # quadList == [0,1,2,3] + if meshDict[objectName][1][vIdxLs[i]] == -1: + currentMesh.verts.append(vertList[vIdxLs[i]]) + f.v.append(currentMesh.verts[-1]) + meshDict[objectName][1][vIdxLs[i]] = len(currentMesh.verts)-1 else: - f.v.append(meshList[objectName][0].verts[meshList[objectName][1][vIdxLs[i]]]) + f.v.append(currentMesh.verts[meshDict[objectName][1][vIdxLs[i]]]) # UV MAPPING if fHasUV: @@ -380,44 +397,53 @@ def load_obj(file): # f.uv.append( uvMapList[ vtIdxLs[i] ] ) if f.v > 0: - f = applyMat(meshList[objectName][0], f, currentMat) + f.mat = contextMeshMatIdx if currentImg != NULL_IMG: - f.image = currentImg - meshList[objectName][0].faces.append(f) # move the face onto the mesh - if len(meshList[objectName][0].faces[-1]) > 0: - meshList[objectName][0].faces[-1].smooth = currentSmooth - + f.image = currentImg + else: + f.mode &= TEX_OFF_FLAG + currentMesh.faces.append(f) # move the face onto the mesh + if len(f) > 0: + f.smooth = currentSmooth + elif len(vIdxLs) >= 3: # This handles tri's and fans for i in range(len(vIdxLs)-2): f = NMesh.Face() - f = applyMat(meshList[objectName][0], f, currentMat) + for ii in [0, i+1, i+2]: - if meshList[objectName][1][vIdxLs[ii]] == -1: - meshList[objectName][0].verts.append(vertList[vIdxLs[ii]]) - f.v.append(meshList[objectName][0].verts[-1]) - meshList[objectName][1][vIdxLs[ii]] = len(meshList[objectName][0].verts)-1 + if meshDict[objectName][1][vIdxLs[ii]] == -1: + currentMesh.verts.append(vertList[vIdxLs[ii]]) + f.v.append(currentMesh.verts[-1]) + meshDict[objectName][1][vIdxLs[ii]] = len(currentMesh.verts)-1 else: - f.v.append(meshList[objectName][0].verts[meshList[objectName][1][vIdxLs[ii]]]) + f.v.append(currentMesh.verts[meshDict[objectName][1][vIdxLs[ii]]]) # UV MAPPING if fHasUV: f.uv.extend([uvMapList[ vtIdxLs[0] ], uvMapList[ vtIdxLs[i+1] ], uvMapList[ vtIdxLs[i+2] ]]) - + if f.v > 0: - f = applyMat(meshList[objectName][0], f, currentMat) + f.mat = contextMeshMatIdx if currentImg != NULL_IMG: - f.image = currentImg - meshList[objectName][0].faces.append(f) # move the face onto the mesh - if len(meshList[objectName][0].faces[-1]) > 0: - meshList[objectName][0].faces[-1].smooth = currentSmooth + f.image = currentImg + else: + f.mode |= TEX_OFF_FLAG + currentMesh.faces.append(f) # move the face onto the mesh + if len(f) > 0: + f.smooth = currentSmooth # FACE SMOOTHING elif l[0] == 's': - if l[1] == 'off': currentSmooth = 0 - else: currentSmooth = 1 - # print "smoothing", currentSmooth + # No value? then turn on. + if len(l) == 1: + currentSmooth = 1 + else: + if l[1] == 'off': + currentSmooth = 0 + else: + currentSmooth = 1 # OBJECT / GROUP elif l[0] == 'o' or l[0] == 'g': @@ -426,51 +452,93 @@ def load_obj(file): # Only make a new group.object name if the verts in the existing object have been used, this is obscure # but some files face groups seperating verts and faces which results in silly things. (no groups have names.) - if len(l) == 1 and len( meshList[objectName][0].faces ) == 0: - pass + if len(l) > 1: + objectName = '_'.join(l[1:]) + else: # No name given + # Make a new empty name + if l[0] == 'g': # Make a blank group name + objectName = 'unnamed_grp_%d' % currentUnnamedGroupIdx + currentUnnamedGroupIdx +=1 + else: # is an object. + objectName = 'unnamed_ob_%d' % currentUnnamedObjectIdx + currentUnnamedObjectIdx +=1 - else: - newObjectName = l[0] + '_' - - # if there is no groups name then make gp_1, gp_2, gp_100 etc - - if len(l) == 1: # No name given, make a unique name up. - - unique_count = 0 - while newObjectName in meshList.keys(): - newObjectName = '%s_%d' % (l[0], unique_count) - unique_count +=1 - else: # The the object/group name given - newObjectName += '_'.join(l[1:]) - - # Assign the new name - objectName = newObjectName - - # If we havnt written to this mesh before then do so. - # if we have then we'll just keep appending to it, this is required for soem files. - if objectName not in meshList.keys(): - meshList[objectName] = (NMesh.GetRaw(), [-1]*len(vertList)) - meshList[objectName][0].hasFaceUV(1) - meshList[objectName][0].verts.append( vertList[0] ) + + # If we havnt written to this mesh before then do so. + # if we have then we'll just keep appending to it, this is required for soem files. + + # If we are new, or we are not yet in the list of added meshes + # then make us new mesh. + if len(l) == 1 or objectName not in meshDict.keys(): + currentMesh = NMesh.GetRaw() + meshDict[objectName] = (currentMesh, VERT_USED_LIST[:]) + currentMesh.hasFaceUV(1) + currentMesh.verts.append( vertList[0] ) + contextMeshMatIdx = -1 + else: + # Since we have this in Blender then we will check if the current Mesh has the material. + # set the contextMeshMatIdx to the meshs index but only if we have it. + currentMesh = meshDict[objectName] + contextMeshMatIdx = getMeshMaterialIndex(currentMesh, currentMat) + + # MATERIAL elif l[0] == 'usemtl': - if len(l) == 1 or l[1] == '(null)': - currentMat = getMat(NULL_MAT) + if len(l) == 1 or l[1] == NULL_MAT: + #~ currentMat = getMat(NULL_MAT) + newMatName = NULL_MAT + currentMat = nullMat else: - currentMat = getMat(' '.join(l[1:])) # Use join in case of spaces - - # MATERIAL + #~ currentMat = getMat(' '.join(l[1:])) # Use join in case of spaces + newMatName = '_'.join(l[1:]) + + + try: # Add to material list if not there + currentMat = materiaDict[newMatName] + newMatName = currentMat.name # Make sure we are up to date, Blender might have incremented the name. + + # Since we have this in Blender then we will check if the current Mesh has the material. + matIdx = 0 + tmpMeshMaterials = currentMesh.materials + while matIdx < len(tmpMeshMaterials): + if tmpMeshMaterials[matIdx].name == newMatName: + contextMeshMatIdx = matIdx # The current mat index. + break + matIdx+=1 + + + + except KeyError: # Not added yet, add now. + currentMat = Material.New(newMatName) + materiaDict[newMatName] = currentMat + contextMeshMatIdx = -1 # Mesh cant possibly have the material. + + # IMAGE elif l[0] == 'usemat' or l[0] == 'usemap': if len(l) == 1 or l[1] == '(null)' or l[1] == 'off': currentImg = NULL_IMG else: - currentImg = getImg('%s%s' % (DIR, ' '.join(l[1:]).replace('./', '') ) ) # Use join in case of spaces + # Load an image. + newImgName = stripPath(' '.join(l[1:])) + + try: + # Assume its alredy set in the dict (may or maynot be loaded) + currentImg = imageDict[newImgName] + + except KeyError: # Not in dict, add for first time. + try: # Image has not been added, Try and load the image + currentImg = Image.Load( '%s%s' % (DIR, newImgName) ) # Use join in case of spaces + imageDict[newImgName] = currentImg + + except IOError: # Cant load, just set blank. + imageDict[newImgName] = NULL_IMG + currentImg = NULL_IMG # MATERIAL FILE elif l[0] == 'mtllib': - mtl_fileName = ' '.join(l[1:]) + mtl_fileName = ' '.join(l[1:]) # SHOULD SUPPORT MULTIPLE MTL? lIdx+=1 @@ -479,22 +547,24 @@ def load_obj(file): # Write all meshs in the dictionary # #==============================================# for ob in Scene.GetCurrent().getChildren(): # Deselect all - ob.sel = 0 + ob.sel = 0 + + + # Applies material properties to materials alredy on the mesh as well as Textures. + if mtl_fileName != '': + load_mtl(DIR, mtl_fileName, meshDict) + importedObjects = [] - for mk in meshList.keys(): - # Applies material properties to materials alredy on the mesh as well as Textures. - if mtl_fileName != '': - load_mtl(DIR, mtl_fileName, meshList[mk][0]) - - meshList[mk][0].verts.pop(0) + for mk in meshDict.keys(): + meshDict[mk][0].verts.pop(0) # Ignore no vert meshes. - if not meshList[mk][0].verts: + if not meshDict[mk][0].verts: continue name = getUniqueName(mk) - ob = NMesh.PutRaw(meshList[mk][0], name) + ob = NMesh.PutRaw(meshDict[mk][0], name) ob.name = name importedObjects.append(ob) @@ -507,8 +577,10 @@ def load_obj(file): Window.FileSelector(load_obj, 'Import Wavefront OBJ') -''' + # For testing compatibility +''' +TIME = sys.time() import os for obj in os.listdir('/obj/'): if obj.lower().endswith('obj'): @@ -517,3 +589,5 @@ for obj in os.listdir('/obj/'): newScn.makeCurrent() load_obj('/obj/' + obj) ''' +#print "TOTAL IMPORT TIME: ", sys.time() - TIME +#load_obj('/obj/her.obj') diff --git a/release/scripts/save_theme.py b/release/scripts/save_theme.py index ba0b9bbcf8f..79205c0d478 100644 --- a/release/scripts/save_theme.py +++ b/release/scripts/save_theme.py @@ -2,14 +2,14 @@ """ Name: 'Save Current Theme...' -Blender: 236 +Blender: 237 Group: 'Export' Tooltip: 'Save current theme as a bpython script' """ __author__ = "Willian P. Germano" __url__ = ("blender", "elysiun") -__version__ = "1.2 2005/05/17" +__version__ = "2.37 2005/06/06" __bpydoc__ = """\ This script saves the current Theme in Blender as a Blender Python script. @@ -39,7 +39,6 @@ some information on it before sharing it with others. # $Id$ # # -------------------------------------------------------------------------- -# save_theme version 2.34 Sep 20, 2004 # Copyright (C) 2004: Willian P. Germano, wgermano _at_ ig.com.br # -------------------------------------------------------------------------- # Released under the Blender Artistic License (BAL): @@ -71,13 +70,13 @@ def write_theme(filename): # \"\"\" # Name: '%s' -# Blender: 236 +# Blender: 237 # Group: 'Themes' # Tooltip: 'Change current theme' # \"\"\" __%s__ = "????" -__%s__ = "1.2" +__%s__ = "2.37" __%s__ = ["blender"] __%s__ = \"\"\"\\ You can edit this section to write something about your script that can diff --git a/release/scripts/tex2uvbaker.py b/release/scripts/tex2uvbaker.py index 1e46e06475c..326f852d53d 100644 --- a/release/scripts/tex2uvbaker.py +++ b/release/scripts/tex2uvbaker.py @@ -2,20 +2,19 @@ """ Registration info for Blender menus: Name: 'Texture Baker' -Blender: 233 +Blender: 237 Group: 'UV' Tooltip: 'Procedural to uvmapped texture baker' """ __author__ = "Jean-Michel Soler (jms)" __url__ = ("blender", "elysiun", -"Script online, http://jmsoler.free.fr/util/blenderfile/py/text2uvbaker.py", +"Official Page, http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_mesh3d2uv2d_en.htm", "Communicate problems and errors, http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender") -__version__ = "0.2.3 2004/12/30" +__version__ = "0.2.6 2005/5/29" __bpydoc__ = """\ -This script "bakes" Blender procedural materials (including textures): it saves -them as 2d uv-mapped images. +Texture Baker "bakes" Blender procedural materials (including textures): it saves them as 2d uv-mapped images. This script saves an uv texture layout of the chosen mesh, that can be used as an uv map for it. It is a way to export procedurals from Blender as normal @@ -24,24 +23,47 @@ with the mesh in games and other 3d applications. Usage: -a) Enter face mode and define uv coordinates for your mesh;<br> -b) Define its materials and textures and set "Map Input" coordinates to UV; +a) Enter face mode and define uv coordinates for your mesh (do not forget to choose a development shape);<br> +b) Define its materials and textures;<br> c) Run this script and check the console. +Global variables: + +a) FRAME (integer): the last frame of the animation, autodocumented.<br> +b) LIMIT (integer): 0 or 1, uvcoords may exceed limits 0.0 to 1.0, this variable obliges the script to do a complete framing of the uvcoord. + Notes:<br> - This script was based on a suggestion by Martin (Theeth) Poirier;<br> + This script was based on a suggestion by Martin (Theeth) Poirier. """ #--------------------------------------------- -# Last release : 0.2.3 , 2004/12/30 , 22h13 +# Last release : 0.2.6 , 2005/05/29 , 22h00 #--------------------------------------------- #--------------------------------------------- # (c) jm soler 07/2004 : 'Procedural Texture Baker' -# Based on a Martin Theeth' Poirier's really -# good idea : -# it makes a rvk mesh with uv coords of the -# original mesh. -# released under Blender Artistic Licence +# Based on a Martin 'Theeth' Poirier's really +# good idea : makes a rvk mesh with uv coords +# of the original mesh. +# +# Released under Blender Artistic Licence +# +# 0.2.6 +# -- Creation of LAMP object is removed and replaced +# by the use of the shadeless option in material object +# +# -- helpmsg corrected : the aim of the script +# is to bake any type of textures so we have not +# to mapinput its textures on UV . +# +# --'pers' camera was replaced by an 'ortho' one. +# +# 0.2.5 +# -- if a image file with the same name exits the +# system returns an error +# +# 0.2.4 +# -- a LIMIT variable is added to unlock the uvcoords +# autoframing # # # 0.2.3 : @@ -85,7 +107,7 @@ Notes:<br> # #--------------------------------------------- # Official Page : -# http://jmsoler.free.fr/util/blenderfile/py/text2uvbaker.py +# http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_mesh3d2uv2d_en.htm # For problems and errors: # http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender #--------------------------------------------- @@ -93,9 +115,69 @@ Notes:<br> import Blender from Blender import NMesh, Draw, Object, Scene, Camera -FRAME = 100 -XYLIMIT = [0.0, 0.] +#----------------------------------- +# Last release : 0.2.5 , 2005/05/22 , 20h00 +#----------------------------------- +# la fonction Blender.sys.dirname pose un +# probleme lorsque la memoire est trop encombree +# --- +# It seems that the Blender.sys.dirname function +# poses a problem when the memory is too much encumbered +#----------------------------------- +try: + import nt + os = nt + os.sep='\\' +except: + import posix + os = posix + os.sep='/' +DIRNAME=Blender.Get('filename') +#----------------------------------- +# decoupage de la chaine en fragment +# de façon a isoler le nom du fichier +# du repertoire +# --- +# split string in fragments to isolate +# the file name from the path name +#----------------------------------- + +if DIRNAME.find(os.sep): + k0=DIRNAME.split(os.sep) +else: + k0=DIRNAME.split('/') +DIRNAME=DIRNAME.replace(k0[-1],'') +#----------------------------------- +# Last release : 0.2.5 , 2005/05/22 , end +#----------------------------------- + +#----------------------------------- +# Last release : 0.2.4 , 2005/05/22 , 15h00 +#----------------------------------- +FRAME = Blender.Get('endframe') +#----------------------------------- +# Last release : 0.2.4 , 2005/05/22 , end +#----------------------------------- + +#----------------------------------- +# Last release : 0.2.4 , 2005/05/18 , 11h00 +# +# Si LIMIT == 0 le script n'essaye pas de realiser +# un nouveau cadrage pour que l'image presente toute les +# coordonnées uv. +# --- +# if LIMIT == 0 the script do not try to make +# a new framing with all the uvcoord in only one +# shoot... +#----------------------------------- +LIMIT=0 +#----------------------------------- +# Last release : 0.2.4 , 2005/05/18 , END +#----------------------------------- + +XYLIMIT = [0.0, 0.0,1.0,1.0] OBJPOS = 100.0 +DEBUG=1 helpmsg = """ Texture Baker: @@ -106,23 +188,79 @@ normal image textures that can be edited with a 2d image manipulation program or used with the mesh in games and other 3d applications. Basic instructions: -- Enter face mode and define uv coordinates for your mesh; -- Define its materials and textures and set "Map Input" coordinates to UV; +- Enter face mode and define uv coordinates for your mesh (do not forget to + choose a development shape); +- Define its materials and textures ; - Run this script and check the console. + """ def GET_newobject (TYPE,NAME): + """ +# --------------------------- +# Function GET_newobject +# +# IN : TYPE string , object type ('Mesh','Empty',...) +# NAME string , name object +# OUT: OBJECT Blender objetc described in teh string TYPE +# SCENE Blender current scene object +# --------------------------- + Return and object and the current scene + """ SCENE = Blender.Scene.getCurrent() OBJECT = Blender.Object.New(TYPE,NAME) SCENE.link(OBJECT) return OBJECT, SCENE +def RenameImage(RDIR, MYDIR, FILENAME, name): + """ +# --------------------------- +# Function RenameImage +# +# IN : RDIR string , current render directory +# MYDIR string , new render dir for this shoot +# FILENAME string , last rendered image filename +# name string , new name for this image +# OUT: nothing +# --------------------------- + Rename the file pointed by the string name + recall the function if the file yet exists + """ + newfname = RDIR + MYDIR + name + if newfname.find('.png', -4) < 0 : newfname += '.png' + if not Blender.sys.exists(newfname): + os.rename(FILENAME, newfname) + else: + name = Draw.PupStrInput ('ReName Image, please :', name, 32) + RenameImage(RDIR, MYDIR, FILENAME, name) + def SAVE_image (rc, name, FRAME): + """ +# --------------------------- +# Function SAVE_image +# +# IN : rc current render context object +# name string , image name +# FRAME integer, last numbre of the curent animation +# OUT: nothing +# --------------------------- + """ + rc.enableExtensions(1) MYDIR = '' - RENDERDIR = rc.getRenderPath() + RENDERDIR = rc.getRenderPath().replace('\\','/') + if RENDERDIR.find('//')==0 : + print 'filename', Blender.Get('filename'),'/n', Blender.sys.dirname(Blender.Get('filename')) + RDIR=RENDERDIR.replace('//',DIRNAME) + else: + RDIR=RENDERDIR[:] + if DEBUG : print 'RDIR : ', RDIR + + HOMEDIR=Blender.Get('homedir') + if DEBUG : print 'HOMEDIR', HOMEDIR rc.setRenderPath(RENDERDIR + MYDIR) - print "Render folder:", RENDERDIR + MYDIR + if DEBUG : print "Render folder:", RENDERDIR + MYDIR IMAGETYPE = Blender.Scene.Render.PNG + if DEBUG : print 'IMAGETYPE : ',IMAGETYPE rc.setImageType(IMAGETYPE) NEWFRAME = FRAME OLDEFRAME = rc.endFrame() @@ -130,39 +268,37 @@ def SAVE_image (rc, name, FRAME): rc.startFrame(NEWFRAME) rc.endFrame(NEWFRAME) rc.renderAnim() - - try: - import nt - os = nt - - except: - import posix - os = posix + Blender.Scene.Render.CloseRenderWindow() FILENAME = "%04d" % NEWFRAME FILENAME = FILENAME.replace (' ', '0') - FILENAME = RENDERDIR + MYDIR + FILENAME + '.png' + FILENAME = RDIR + MYDIR + FILENAME + '.png' - try: - TRUE = os.stat(FILENAME) - newfname = RENDERDIR + MYDIR + name - if newfname.find('.png', -4) < 0: newfname += '.png' - os.rename(FILENAME, newfname) - print "Renamed to:", newfname - - except: - pass + RenameImage(RDIR, MYDIR, FILENAME, name) rc.endFrame(OLDEFRAME) rc.startFrame(OLDSFRAME) rc.setRenderPath(RENDERDIR) def SHOOT (XYlimit, frame, obj, name, FRAME): + """ +# --------------------------- +# Function SHOOT +# +# IN : XYlimit list of 4 floats, smallest and biggest +# uvcoords +# frame cureente frame +# obj for object location +# name image name +# FRAME the last animation's frame +# OUT: nothing +# --------------------------- + render and save the baked textures picture + """ try: CAM = Blender.Object.Get('UVCAMERA') Cam = CAM.getData() SC = Blender.Scene.getCurrent() - except: Cam = Blender.Camera.New() Cam.name = 'UVCamera' @@ -172,45 +308,29 @@ def SHOOT (XYlimit, frame, obj, name, FRAME): Cam.lens = 30 Cam.name = 'UVCamera' + Cam.setType('ortho') + Cam.setScale(1.0) + CAM.setLocation(obj.getLocation()) - CAM.LocX += XYlimit[0] / 2.0 - CAM.LocY += XYlimit[1] / 2.0 - CAM.LocZ += max (XYlimit[0], XYlimit[1]) + CAM.LocX += XYlimit[2] * 0.500 + CAM.LocY += XYlimit[3] * 0.500 + CAM.LocZ += max (XYlimit[2], XYlimit[3]) CAM.setEuler (0.0, 0.0, 0.0) - try: - LAMP = Blender.Object.Get('ECLAIRAGE') - lampe = LAMP.getData() - SC = Blender.Scene.getCurrent() - - except: - lampe = Blender.Lamp.New() - lampe.name = 'lumin' - LAMP, SC = GET_newobject('Lamp','ECLAIRAGE') - LAMP.link(lampe) - LAMP.setName('ECLAIRAGE') - - LAMP.setLocation(obj.getLocation()) - LAMP.LocX += XYlimit[0] / 2.0 - LAMP.LocY += XYlimit[1] / 2.0 - LAMP.LocZ += max (XYlimit[0], XYlimit[1]) - LAMP.setEuler (0.0, 0.0, 0.0) - context = SC.getRenderingContext() Camold = SC.getCurrentCamera() SC.setCurrentCamera(CAM) + OLDy = context.imageSizeY() OLDx = context.imageSizeX() - tres = Draw.PupMenu('TEXTURE OUT RESOLUTION : %t | 256 %x1 | 512 %x2 | 768 %x3 | 1024 %x4') - if (tres) == 1: res = 256 + tres = Draw.PupMenu('TEXTURE OUT RESOLUTION : %t | 256 %x1 | 512 %x2 | 768 %x3 | 1024 %x4 | 2048 %x5 ') + if (tres) == 1: res = 256 elif (tres) == 2: res = 512 - elif (tres) == 3: res = 768 - elif (tres) == 4: res = 1024 - + elif (tres) == 5: res = 2048 else: res = 512 context.imageSizeY(res) @@ -223,10 +343,58 @@ def SHOOT (XYlimit, frame, obj, name, FRAME): Blender.Set ('curframe', frame) -def Mesh2UVCoord (): - if 1:#try: - MESH3D = Object.GetSelected()[0] +#----------------------------------- +# release : 0.2.6 , 2005/05/29 , 00h00 +#----------------------------------- +def PROV_Shadeless(MATList): + """ +# --------------------------- +# Function PROV_Shadeless +# +# IN : MATList a list of the mesh's materials +# OUT: SHADEDict a dictionnary of the materials' shadeles value +# --------------------------- + """ + SHADEDict={} + for mat in MATList: + SHADEDict[mat.name]=mat.mode + mat.mode |= Blender.Material.Modes.SHADELESS + return SHADEDict +#----------------------------------- +# Last release : 0.2.6 , 2005/05/29 , end +#----------------------------------- + +#----------------------------------- +# release : 0.2.6 , 2005/05/29 , 00h00 +#----------------------------------- +def REST_Shadeless(SHADEDict): + """ +# --------------------------- +# Function REST_Shadeless +# +# IN : SHADEDict a dictionnary of the materials' shadeles value +# OUT : nothing +# --------------------------- + """ + for m in SHADEDict.keys(): + mat=Blender.Material.Get(m) + mat.mode=SHADEDict[m] +#----------------------------------- +# release : 0.2.6 , 2005/05/29 , end +#----------------------------------- + +def Mesh2UVCoord (LIMIT): + """ +# --------------------------- +# Function Mesh2UVCoord +# +# IN : LIMIT integer, create or not a new framing for uvcoords +# OUT: nothing +# --------------------------- + """ + try: + MESH3D = Object.GetSelected()[0] if MESH3D.getType() == 'Mesh': MESH = MESH3D.getData() @@ -234,12 +402,12 @@ def Mesh2UVCoord (): NewOBJECT=Blender.Object.Get('UVOBJECT') CurSCENE=Blender.Scene.getCurrent() MESH2 = NewOBJECT.getData() - MESH2.faces=[] - + except: NewOBJECT, CurSCENE = GET_newobject('Mesh','UVOBJECT') MESH2 = Blender.NMesh.GetRaw() + MESH2.faces=[] for f in MESH.faces: f1 = Blender.NMesh.Face() @@ -258,55 +426,73 @@ def Mesh2UVCoord (): MESH2.materials = MESH.materials[:] - - #NewOBJECT.link(MESH2) - NewOBJECT.setLocation (OBJPOS, OBJPOS, 0.0) NewOBJECT.setEuler (0.0, 0.0, 0.0) MESH2.removeAllKeys() + MESH2.update() + MESH2.insertKey (1, 'absolute') + MESH2.update() for f in MESH2.faces: for v in f.v: - for n in [0, 1]: + for n in [0,1]: v.co[n] = f.uv[f.v.index(v)][n] - exec "if v.co[%s] > XYLIMIT[%s]: XYLIMIT[%s] = v.co[%s]" % (n, n, n, n) - + exec "if v.co[%s] > XYLIMIT[%s]: XYLIMIT[%s] = v.co[%s]" % (n, n+2, n+2, n) + exec "if v.co[%s] < XYLIMIT[%s]: XYLIMIT[%s] = v.co[%s]" % (n, n, n, n) v.co[2] = 0.0 - print XYLIMIT - - MESH2.update() - MESH2.insertKey (1, 'absolute') - MESH2.update() + if DEBUG: print XYLIMIT MESH2.update() MESH2.insertKey (FRAME, 'absolute') MESH2.update() + imagename = 'uvtext' - name = "CHANGE IMAGE NAME ? %t | Replace it | No replace | Script help" + name = "CHANGE IMAGE NAME ? %t | Replace it | No replacing | Script help" result = Draw.PupMenu(name) if result == 1: imagename = Draw.PupStrInput ('Image Name:', imagename, 32) if result != 3: - SHOOT (XYLIMIT, FRAME, NewOBJECT, imagename, FRAME) + #----------------------------------- + # release : 0.2.6 , 2005/05/29 , 00h00 + #----------------------------------- + SHADEDict=PROV_Shadeless(MESH2.materials) + #----------------------------------- + # release : 0.2.6 , 2005/05/29 , end + #----------------------------------- + + if LIMIT : + SHOOT(XYLIMIT, FRAME, NewOBJECT, imagename, FRAME) + else : + SHOOT([0.0,0.0,1.0,1.0], FRAME, NewOBJECT, imagename, FRAME) + #----------------------------------- + # release : 0.2.6, 2005/05/29 , 00h00 + #----------------------------------- + REST_Shadeless(SHADEDict) + #----------------------------------- + # release : 0.2.6 , 2005/05/29 , end + #----------------------------------- + Blender.Redraw() + else: - Draw.PupMenu("Ready%t|Please check console for instructions") - print helpmsg + Blender.ShowHelp('tex2uvbaker.py') + #Draw.PupMenu("Ready%t|Please check console for instructions") + if DEBUG: print helpmsg else: - name = "Error%t|Active object is not a mesh or has no UV coordinates" + name = "ERROR: active object is not a mesh or has no UV coordinates" result = Draw.PupMenu(name) print 'problem : no object selected or not mesh' - #except: - # name = "Error%t|Active object is not a mesh or has no UV coordinates" - # result = Draw.PupMenu(name) + except: + name = "ERROR: active object is not a mesh or has no UV coordinates" + result = Draw.PupMenu(name) print 'problem : no object selected or not mesh' -Mesh2UVCoord() +Mesh2UVCoord(LIMIT) |