diff options
32 files changed, 1456 insertions, 514 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 5a23e77d9f8..0ea26750ec1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -183,9 +183,9 @@ IF(UNIX) SET(LLIBS "-lXi -lutil -lc -lm -lpthread -lstdc++") IF(WITH_OPENMP) - SET(LLIBS "${LLIBS} -lgomp ") - SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fopenmp ") - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fopenmp ") + SET(LLIBS "${LLIBS} -lgomp") + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fopenmp") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fopenmp") ENDIF(WITH_OPENMP) diff --git a/config/linux2-config.py b/config/linux2-config.py index 6bde0664fe5..fe4325361a8 100644 --- a/config/linux2-config.py +++ b/config/linux2-config.py @@ -139,7 +139,7 @@ BF_OPENJPEG_LIB = '' BF_OPENJPEG_INC = '${BF_OPENJPEG}/include' BF_OPENJPEG_LIBPATH='${BF_OPENJPEG}/lib' -WITH_BF_REDCODE = 'true' +WITH_BF_REDCODE = 'false' BF_REDCODE = '#extern/libredcode' BF_REDCODE_LIB = '' # Uncomment the following two lines to use system's ffmpeg diff --git a/intern/bmfont/intern/BDF2BMF.py b/intern/bmfont/intern/BDF2BMF.py new file mode 100644 index 00000000000..15b9e5b8eb4 --- /dev/null +++ b/intern/bmfont/intern/BDF2BMF.py @@ -0,0 +1,177 @@ +#!/usr/bin/python + +# ***** 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 ***** +# -------------------------------------------------------------------------- + +HELP_TXT = \ +''' +Convert BDF pixmap fonts into C++ files Blender can read. +Use to replace bitmap fonts or add new ones. + +Usage + python bdf2bmf.py -name=SomeName myfile.bdf + +Blender currently supports fonts with a maximum width of 8 pixels. +''' + +# -------- Simple BDF parser +import sys +def parse_bdf(f, MAX_CHARS=256): + lines = [l.strip().upper().split() for l in f.readlines()] + + is_bitmap = False + dummy = {'BITMAP':[]} + char_data = [dummy.copy() for i in xrange(MAX_CHARS)] + context_bitmap = [] + + for l in lines: + if l[0]=='ENCODING': enc = int(l[1]) + elif l[0]=='BBX': bbx = [int(c) for c in l[1:]] + elif l[0]=='DWIDTH': dwidth = int(l[1]) + elif l[0]=='BITMAP': is_bitmap = True + elif l[0]=='ENDCHAR': + if enc < MAX_CHARS: + char_data[enc]['BBX'] = bbx + char_data[enc]['DWIDTH'] = dwidth + char_data[enc]['BITMAP'] = context_bitmap + + context_bitmap = [] + enc = bbx = None + is_bitmap = False + else: + # None of the above, Ok, were reading a bitmap + if is_bitmap and enc < MAX_CHARS: + context_bitmap.append( int(l[0], 16) ) + + return char_data +# -------- end simple BDF parser + +def bdf2cpp_name(path): + return path.split('.')[0] + '.cpp' + +def convert_to_blender(bdf_dict, font_name, origfilename, MAX_CHARS=256): + + # first get a global width/height, also set the offsets + xmin = ymin = 10000000 + xmax = ymax = -10000000 + + bitmap_offsets = [-1] * MAX_CHARS + bitmap_tot = 0 + for i, c in enumerate(bdf_dict): + if c.has_key('BBX'): + bbx = c['BBX'] + xmax = max(bbx[0], xmax) + ymax = max(bbx[1], ymax) + xmin = min(bbx[2], xmin) + ymin = min(bbx[3], ymin) + + bitmap_offsets[i] = bitmap_tot + bitmap_tot += len(c['BITMAP']) + + c['BITMAP'].reverse() + + # Now we can write. Ok if we have no .'s in the path. + f = open(bdf2cpp_name(origfilename), 'w') + + f.write(''' +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "BMF_FontData.h" + +#include "BMF_Settings.h" +''') + + f.write('#if BMF_INCLUDE_%s\n\n' % font_name.upper()) + f.write('static unsigned char bitmap_data[]= {') + newline = 8 + + for i, c in enumerate(bdf_dict): + + for cdata in c['BITMAP']: + # Just formatting + newline+=1 + if newline >= 8: + newline = 0 + f.write('\n\t') + # End formatting + + f.write('0x%.2hx,' % cdata) # 0x80 <- format + + f.write("\n};\n") + + f.write("BMF_FontData BMF_font_%s = {\n" % font_name) + f.write('\t%d, %d,\n' % (xmin, ymin)) + f.write('\t%d, %d,\n' % (xmax, ymax)) + + f.write('\t{\n') + + + for i, c in enumerate(bdf_dict): + if bitmap_offsets[i] == -1 or c.has_key('BBX') == False: + f.write('\t\t{0,0,0,0,0, -1},\n') + else: + bbx = c['BBX'] + f.write('\t\t{%d,%d,%d,%d,%d, %d},\n' % (bbx[0], bbx[1], -bbx[2], -bbx[3], c['DWIDTH'], bitmap_offsets[i])) + + f.write(''' + }, + bitmap_data +}; + +#endif +''') + +def main(): + # replace "[-name=foo]" with "[-name] [foo]" + args = [] + for arg in sys.argv: + for a in arg.replace('=', ' ').split(): + args.append(a) + + name = 'untitled' + done_anything = False + for i, arg in enumerate(args): + if arg == '-name': + if i==len(args)-1: + print 'no arg given for -name, aborting' + return + else: + name = args[i+1] + + elif arg.lower().endswith('.bdf'): + try: + f = open(arg) + print '...Writing to:', bdf2cpp_name(arg) + except: + print 'could not open "%s", aborting' % arg + + + bdf_dict = parse_bdf(f) + convert_to_blender(bdf_dict, name, arg) + done_anything = True + + if not done_anything: + print HELP_TXT + print '...nothing to do' + +if __name__ == '__main__': + main() + diff --git a/projectfiles_vc7/blender/blenkernel/BKE_blenkernel.vcproj b/projectfiles_vc7/blender/blenkernel/BKE_blenkernel.vcproj index 8efff1742b0..0ea3503a289 100644 --- a/projectfiles_vc7/blender/blenkernel/BKE_blenkernel.vcproj +++ b/projectfiles_vc7/blender/blenkernel/BKE_blenkernel.vcproj @@ -366,6 +366,9 @@ RelativePath="..\..\..\source\blender\blenkernel\intern\brush.c"> </File> <File + RelativePath="..\..\..\source\blender\blenkernel\intern\bvhutils.c"> + </File> + <File RelativePath="..\..\..\source\blender\blenkernel\intern\CCGSubSurf.c"> </File> <File @@ -577,6 +580,9 @@ RelativePath="..\..\..\source\blender\blenkernel\BKE_brush.h"> </File> <File + RelativePath="..\..\..\source\blender\blenkernel\BKE_bvhutils.h"> + </File> + <File RelativePath="..\..\..\source\blender\blenkernel\BKE_cdderivedmesh.h"> </File> <File diff --git a/release/scripts/flt_export.py b/release/scripts/flt_export.py index 2b9db74c770..c099c8e62d1 100644 --- a/release/scripts/flt_export.py +++ b/release/scripts/flt_export.py @@ -525,8 +525,8 @@ class FaceDesc: def __init__(self): self.vertex_index_lst = [] self.mface = None - self.texture_index = -1 - self.material_index = -1 + self.texture_index = 65535 + self.material_index = 65535 self.color_index = 127 self.renderstyle = 0 self.twoside = 0 @@ -979,8 +979,14 @@ class FLTNode(Node): self.header.fw.write_char(0) # Reserved self.header.fw.write_char(alpha) # Template self.header.fw.write_short(-1) # Detail tex pat index - self.header.fw.write_short(face_desc.texture_index) # Tex pattern index - self.header.fw.write_short(face_desc.material_index) # material index + if face_desc.texture_index == -1: + self.header.fw.write_ushort(65535) + else: + self.header.fw.write_ushort(face_desc.texture_index) # Tex pattern index + if face_desc.material_index == -1: + self.header.fw.write_ushort(65535) + else: + self.header.fw.write_ushort(face_desc.material_index) # material index self.header.fw.write_short(0) # SMC code self.header.fw.write_short(0) # Feature code self.header.fw.write_int(0) # IR material code @@ -1015,7 +1021,10 @@ class FLTNode(Node): self.header.fw.write_ushort(8 + (mtex * 8)) # Length self.header.fw.write_uint(uvmask) # UV mask for i in xrange(mtex): - self.header.fw.write_ushort(face_desc.images[i]) # Tex pattern index + if face_desc.images[i] == -1: + self.header.fw.write_ushort(65535) + else: + self.header.fw.write_ushort(face_desc.images[i]) # Tex pattern index self.header.fw.write_ushort(0) # Tex effect self.header.fw.write_ushort(0) # Tex Mapping index self.header.fw.write_ushort(0) # Tex data. User defined @@ -1070,7 +1079,7 @@ class FLTNode(Node): if self.opcode == 63 and options.state['externalspath']: try: - exportdict['3t200!filename'] = os.path.join(options.state['externalspath'],self.object.DupGroup.name+'.flt') + exportdict['3t200!filename'] = os.path.join(options.state['externalspath'],self.object.DupGroup.name+'.flt').replace("\\", "/") self.header.xrefnames.append(self.object.DupGroup.name) except: pass @@ -1092,7 +1101,7 @@ class FLTNode(Node): write_prop(self.header.fw,ftype,self.object.properties['FLT']['EXT'][propname],length) #write extension data for i in xrange(datalen): - self.header.fw.write_char(self.object.properties['FLT']['EXT']['data'][i]) + self.header.fw.write_uchar(struct.unpack('>B', struct.pack('>B', self.object.properties['FLT']['EXT']['data'][i]))[0]) self.write_pop_extension() @@ -1180,8 +1189,8 @@ class Database(Node): desc = self.GRR.request_vertex_desc(i) self.fw.write_short(70) # Vertex with color normal and uv opcode. self.fw.write_ushort(64) # Length of record - self.fw.write_ushort(0) # Color name index - self.fw.write_short(0x20000000) # Flags + self.fw.write_ushort(0) # Color name index + self.fw.write_short(1 << 14) # Frozen Normal self.fw.write_double(desc.x) self.fw.write_double(desc.y) self.fw.write_double(desc.z) @@ -1245,7 +1254,7 @@ class Database(Node): cpalette = defaultp.pal count = len(cpalette) for i in xrange(count): - color = struct.unpack('>BBBB',struct.pack('>I',cpalette[i])) + color = struct.unpack('>BBBB',struct.pack('>i',cpalette[i])) self.fw.write_uchar(color[3]) # alpha self.fw.write_uchar(color[2]) # b self.fw.write_uchar(color[1]) # g diff --git a/release/scripts/flt_palettemanager.py b/release/scripts/flt_palettemanager.py index 6edaf2974ab..c2f1380a6fa 100644 --- a/release/scripts/flt_palettemanager.py +++ b/release/scripts/flt_palettemanager.py @@ -25,7 +25,7 @@ http://wiki.blender.org/index.php/Scripts/Manual/FLTools """ # -------------------------------------------------------------------------- -# flt_palettemanager.py version 0.1 2005/04/08 +# flt_palettemanager.py version 1.0 2005/04/08 # -------------------------------------------------------------------------- # ***** BEGIN GPL LICENSE BLOCK ***** # @@ -55,6 +55,75 @@ import flt_properties import flt_defaultp as defaultp from flt_properties import * +def RGBtoHSV( r, g, b): + minc = min( r, g, b ) + maxc = max( r, g, b ) + v = maxc + + delta = maxc - minc + + if( max != 0 ): + s = delta / maxc + else: + s = 0 + h = -1 + return (h,s,v) + + if( r == maxc ): + h = ( g - b ) / delta + elif( g == maxc ): + h = 2 + ( b - r ) / delta + else: + h = 4 + ( r - g ) / delta + + h *= 60 + if( h < 0 ): + h += 360 + + return(h,s,v) + +def HSVtoRGB(h,s,v): + + if( s == 0 ): + return (v,v,v) + + + h /= 60 + i = math.floor( h) + f = h - i + p = v * ( 1 - s ) + q = v * ( 1 - s * f ) + t = v * ( 1 - s * ( 1 - f ) ) + + if i == 0: + r = v + g = t + b = p + elif i == 1: + r = q + g = v + b = p + + elif i== 2: + r = p + g = v + b = t + elif i==3: + r = p + g = q + b = v + elif i==4: + r = t + g = p + b = v + + else: + r = v + g = p + b = q + + return(r,g,b) + palette_size = 12 palette_x = 0 @@ -68,6 +137,14 @@ cinc = 1.0 / 1024.0 cstep = 0.0 picker = None ptt = "" + + +ts1=None +ts2=None +ts3=None +ts4=None +ts5=None + for i in xrange(1024): colors.append([cstep,cstep,cstep]) cstep = cstep + cinc @@ -128,7 +205,7 @@ def event(evt,val): Draw.Redraw(1) #copy current color and intensity to selected faces. - elif evt == Draw.CKEY: + elif evt == Draw.VKEY: if Blender.Window.EditMode(): Blender.Window.EditMode(0) @@ -136,7 +213,7 @@ def event(evt,val): state = update_state() #retrieve color from palette - color = struct.unpack('>BBBB',struct.pack('>I',colors[curswatch])) + color = struct.unpack('>BBBB',struct.pack('>i',colors[curswatch])) actmesh = state["activeMesh"] if actmesh: if(Blender.Window.GetKeyQualifiers() != Blender.Window.Qual["CTRL"]): @@ -182,7 +259,7 @@ def event(evt,val): Blender.Window.RedrawAll() #grab color and intensity from active face - elif evt == Draw.VKEY: + elif evt == Draw.CKEY: if Blender.Window.EditMode(): Blender.Window.EditMode(0) editmode = 1 @@ -211,6 +288,23 @@ def event(evt,val): Blender.Window.EditMode(1) Blender.Window.RedrawAll() + + elif evt == Draw.GKEY: + if Blender.Window.EditMode(): + Blender.Window.EditMode(0) + editmode =1 + state = update_state() + + actmesh = state["activeMesh"] + activeFace = state["activeFace"] + + if activeFace and "FLT_COL" in actmesh.faces.properties: + (index,intensity) = unpack_face_index(activeFace.getProperty("FLT_COL")) + for face in actmesh.faces: + (index2, intensity2) = unpack_face_index(face.getProperty("FLT_COL")) + if index == index2: + face.sel = 1 + elif evt == Draw.ESCKEY: Draw.Exit() @@ -225,11 +319,11 @@ def update_all(): for object in state["activeScene"].objects: if object.type == "Mesh": mesh = object.getData(mesh=True) - if 'FLT_COL' in mesh.faces.properties: + if 'FLT_COL' in mesh.faces.properties and "FLT_Fcol" in mesh.getColorLayerNames(): mesh.activeColorLayer = "FLT_Fcol" for face in mesh.faces: (index,intensity) = unpack_face_index(face.getProperty('FLT_COL')) - color = struct.unpack('>BBBB',struct.pack('>I',colors[index])) + color = struct.unpack('>BBBB',struct.pack('>i',colors[index])) #update the vertex colors for this face for col in face.col: col.r = int(color[0] * intensity) @@ -284,8 +378,13 @@ def draw_palette(): global colors global curint global curswatch - global picker - + global picker + global ts1 + global ts2 + global ts3 + global ts4 + global ts5 + state = update_state() init_pal() @@ -297,7 +396,7 @@ def draw_palette(): for x in xrange(32): ypos = palette_y for y in xrange(32): - color = struct.unpack('>BBBB',struct.pack('>I',colors[cid])) + color = struct.unpack('>BBBB',struct.pack('>i',colors[cid])) glColor3f(color[0]/255.0,color[1]/255.0,color[2]/255.0) glBegin(GL_POLYGON) glVertex2i(xpos,ypos) @@ -328,7 +427,7 @@ def draw_palette(): xpos = xpos + ssize #draw intensity gradient - color = struct.unpack('>BBBB',struct.pack('>I',colors[curswatch])) + color = struct.unpack('>BBBB',struct.pack('>i',colors[curswatch])) color = [color[0]/255.0,color[1]/255.0,color[2]/255.0] colsteps = [color[0]/255.0,color[1]/255.0,color[2]/255.0] stripwidth = (palette_size * 32.0) / 256 @@ -355,15 +454,15 @@ def draw_palette(): xpos = ((palette_size*32) * (1.0 - curint)) + palette_x glColor3f(1.0,1.0,1.0) glBegin(GL_LINE_LOOP) - glVertex2i(xpos-6,grady-1) - glVertex2i(xpos+6,grady-1) - glVertex2i(xpos+6,grady+palette_size+1) - glVertex2i(xpos-6,grady+palette_size+1) + glVertex2i(int(xpos-6),int(grady-1)) + glVertex2i(int(xpos+6),int(grady-1)) + glVertex2i(int(xpos+6),int(grady+palette_size+1)) + glVertex2i(int(xpos-6),int(grady+palette_size+1)) #glVertex2i(xpos-6,grady+7) glEnd() #draw color picker - color = struct.unpack('>BBBB',struct.pack('>I',colors[curswatch])) + color = struct.unpack('>BBBB',struct.pack('>i',colors[curswatch])) pickcol = (color[0]/255.0,color[1]/255.0,color[2]/255.0) picker = Blender.Draw.ColorPicker(1,highlight[0][0]+1,highlight[0][1]+1,ssize-2,ssize-2,pickcol,ptt) @@ -377,6 +476,24 @@ def draw_palette(): glVertex2i(highlight[0][0],highlight[0][1]) glEnd() + #draw text string explanations + xpos = palette_size*32+20 + ypos = palette_size*32+10 + glRasterPos2d(xpos,ypos) + ts1 = Blender.Draw.Text("FLT Palette Manager V 1.0") + ypos = ypos - 20 + glRasterPos2d(xpos,ypos) + ts3 = Blender.Draw.Text("CKEY - Copy Active Face Color*") + ypos = ypos - 20 + glRasterPos2d(xpos,ypos) + ts2 = Blender.Draw.Text("VKEY - Paste Color to Selected Faces") + ypos = ypos - 20 + glRasterPos2d(xpos,ypos) + ts4 = Blender.Draw.Text("GKEY - Select Faces With Same Color") + ypos = ypos - 15 + glRasterPos2d(xpos,ypos) + ts5 = Blender.Draw.Text("(*Requires mesh with UV coordinates)", 'small') + def gui(): glClearColor(0.5,0.5,0.5,1.0) glClear(GL_COLOR_BUFFER_BIT) @@ -385,4 +502,4 @@ def gui(): init_pal() Draw.Register(gui,event,but_event) - +
\ No newline at end of file diff --git a/release/scripts/import_dxf.py b/release/scripts/import_dxf.py index 09e51c22a9f..bb0119a9a81 100644 --- a/release/scripts/import_dxf.py +++ b/release/scripts/import_dxf.py @@ -7,7 +7,7 @@ Group: 'Import' Tooltip: 'Import for DXF geometry data (Drawing eXchange Format).' """ __author__ = 'Kitsu(Ed Blake) & migius(Remigiusz Fiedler)' -__version__ = '1.12 - 2008.07.04 by migius' +__version__ = '1.12 - 2008.08.03 by migius' __url__ = ["http://blenderartists.org/forum/showthread.php?t=84319", "http://wiki.blender.org/index.php/Scripts/Manual/Import/DXF-3D"] __email__ = ["migius(at)4d-vectors.de","Kitsune_e(at)yahoo.com"] @@ -88,7 +88,7 @@ in creating new objects in scene database - probably a database management probl """ History: - v1.0 - 2008.01. by migius + v1.0 - 2007/2008 by migius planned tasks: -- (to see more, search for "--todo--" in script code) -- command-line-mode/batch-mode diff --git a/release/scripts/ply_export.py b/release/scripts/ply_export.py index cecde5a0b59..19a4a60674e 100644 --- a/release/scripts/ply_export.py +++ b/release/scripts/ply_export.py @@ -13,7 +13,7 @@ from Blender import Mesh, Scene, Window, sys, Image, Draw import BPyMesh __author__ = "Bruce Merry" -__version__ = "0.92" +__version__ = "0.93" __bpydoc__ = """\ This script exports Stanford PLY files from Blender. It supports normals, colours, and texture coordinates per face or per vertex. @@ -37,6 +37,8 @@ Only one mesh can be exported at a time. # Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # Vector rounding se we can use as keys # +# Updated on Aug 11, 2008 by Campbell Barton +# - added 'comment' prefix to comments - Needed to comply with the PLY spec. # # Updated on Jan 1, 2007 by Gabe Ghearing # - fixed normals so they are correctly smooth/flat @@ -162,7 +164,7 @@ def file_callback(filename): file.write('ply\n') file.write('format ascii 1.0\n') - file.write('Created by Blender3D %s - www.blender.org, source file: %s\n' % (Blender.Get('version'), Blender.Get('filename').split('/')[-1].split('\\')[-1] )) + file.write('comment Created by Blender3D %s - www.blender.org, source file: %s\n' % (Blender.Get('version'), Blender.Get('filename').split('/')[-1].split('\\')[-1] )) file.write('element vertex %d\n' % len(verts)) @@ -210,7 +212,6 @@ def file_callback(filename): if faceUV: uvcoord= rvec2d(uv[j]) elif vertexUV: uvcoord= rvec2d(v.uvco) if vertexColors: color= col[j].r, col[j].g, col[j].b - co = v.co file.write('%d ' % vdict[v.index][normal, uvcoord, color]) diff --git a/source/blender/blenkernel/BKE_bvhutils.h b/source/blender/blenkernel/BKE_bvhutils.h new file mode 100644 index 00000000000..dd9ea61f24b --- /dev/null +++ b/source/blender/blenkernel/BKE_bvhutils.h @@ -0,0 +1,98 @@ +/** + * + * $Id$ + * + * ***** 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. + * + * The Original Code is Copyright (C) 2006 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): André Pinto + * + * ***** END GPL LICENSE BLOCK ***** + */ +#ifndef BKE_BVHUTILS_H +#define BKE_BVHUTILS_H + +#include "BLI_kdopbvh.h" + +/* + * This header encapsulates necessary code to buld a BVH + */ + +struct DerivedMesh; +struct MVert; +struct MFace; + +/* + * struct that kepts basic information about a BVHTree build from a mesh + */ +typedef struct BVHTreeFromMesh +{ + struct BVHTree *tree; + + /* default callbacks to bvh nearest and raycast */ + BVHTree_NearestPointCallback nearest_callback; + BVHTree_RayCastCallback raycast_callback; + + /* Mesh represented on this BVHTree */ + struct DerivedMesh *mesh; + + /* Vertex array, so that callbacks have instante access to data */ + struct MVert *vert; + struct MFace *face; + + /* radius for raycast */ + float sphere_radius; + +} BVHTreeFromMesh; + +/* + * Builds a bvh tree where nodes are the vertexs of the given mesh. + * Configures BVHTreeFromMesh. + * + * The tree is build in mesh space coordinates, this means special care must be made on queries + * so that the coordinates and rays are first translated on the mesh local coordinates. + * Reason for this is that later bvh_from_mesh_* might use a cache system and so it becames possible to reuse + * a BVHTree. + * + * free_bvhtree_from_mesh should be called when the tree is no longer needed. + */ +void bvhtree_from_mesh_verts(struct BVHTreeFromMesh *data, struct DerivedMesh *mesh, float epsilon, int tree_type, int axis); + +/* + * Builds a bvh tree where nodes are the faces of the given mesh. + * Configures BVHTreeFromMesh. + * + * The tree is build in mesh space coordinates, this means special care must be made on queries + * so that the coordinates and rays are first translated on the mesh local coordinates. + * Reason for this is that later bvh_from_mesh_* might use a cache system and so it becames possible to reuse + * a BVHTree. + * + * free_bvhtree_from_mesh should be called when the tree is no longer needed. + */ +void bvhtree_from_mesh_faces(struct BVHTreeFromMesh *data, struct DerivedMesh *mesh, float epsilon, int tree_type, int axis); + +/* + * Frees data allocated by a call to bvhtree_from_mesh_*. + */ +void free_bvhtree_from_mesh(struct BVHTreeFromMesh *data); + +#endif + diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index 1f8dd74a6eb..1592c3e5504 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -734,9 +734,8 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, float par_ ParticleCacheKey *cache; ParticleSystemModifierData *psmd; float ctime, pa_time, scale = 1.0f; - float tmat[4][4], mat[4][4], obrotmat[4][4], pamat[4][4], size=0.0; + float tmat[4][4], mat[4][4], pamat[4][4], size=0.0; float (*obmat)[4], (*oldobmat)[4]; - float xvec[3] = {-1.0, 0.0, 0.0}, q[4]; int lay, a, b, k, step_nbr = 0, counter, hair = 0; int totpart, totchild, totgroup=0, pa_num; @@ -898,14 +897,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, float par_ /* to give ipos in object correct offset */ where_is_object_time(ob, ctime-pa_time); - if(!hair) { - vectoquat(xvec, ob->trackflag, ob->upflag, q); - QuatToMat4(q, obrotmat); - obrotmat[3][3]= 1.0f; - Mat4MulMat4(mat, obrotmat, pamat); - } - else - Mat4CpyMat4(mat, pamat); + Mat4CpyMat4(mat, pamat); Mat4MulMat4(tmat, obmat, mat); Mat4MulFloat3((float *)tmat, size*scale); diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c new file mode 100644 index 00000000000..10e92b8b705 --- /dev/null +++ b/source/blender/blenkernel/intern/bvhutils.c @@ -0,0 +1,433 @@ +/** + * + * $Id$ + * + * ***** 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. + * + * The Original Code is Copyright (C) Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): André Pinto. + * + * ***** END GPL LICENSE BLOCK ***** + */ +#include <stdio.h> +#include <string.h> +#include <math.h> + +#include "BKE_bvhutils.h" + +#include "DNA_object_types.h" +#include "DNA_modifier_types.h" +#include "DNA_meshdata_types.h" + +#include "BKE_DerivedMesh.h" +#include "BKE_utildefines.h" +#include "BKE_deform.h" +#include "BKE_cdderivedmesh.h" +#include "BKE_displist.h" +#include "BKE_global.h" + +#include "BLI_arithb.h" + +/* Math stuff for ray casting on mesh faces and for nearest surface */ + +static float nearest_point_in_tri_surface(const float *point, const float *v0, const float *v1, const float *v2, float *nearest); + +#define ISECT_EPSILON 1e-6 +static float ray_tri_intersection(const BVHTreeRay *ray, const float m_dist, const float *v0, const float *v1, const float *v2) +{ + float dist; + + if(RayIntersectsTriangle((float*)ray->origin, (float*)ray->direction, (float*)v0, (float*)v1, (float*)v2, &dist, NULL)) + return dist; + + return FLT_MAX; +} + +static float sphereray_tri_intersection(const BVHTreeRay *ray, float radius, const float m_dist, const float *v0, const float *v1, const float *v2) +{ + + float idist; + float p1[3]; + float plane_normal[3], hit_point[3]; + + CalcNormFloat((float*)v0, (float*)v1, (float*)v2, plane_normal); + + VECADDFAC( p1, ray->origin, ray->direction, m_dist); + if(SweepingSphereIntersectsTriangleUV((float*)ray->origin, p1, radius, (float*)v0, (float*)v1, (float*)v2, &idist, hit_point)) + { + return idist * m_dist; + } + + return FLT_MAX; +} + +/* + * This calculates the distance from point to the plane + * Distance is negative if point is on the back side of plane + */ +static float point_plane_distance(const float *point, const float *plane_point, const float *plane_normal) +{ + float pp[3]; + VECSUB(pp, point, plane_point); + return INPR(pp, plane_normal); +} +static float choose_nearest(const float v0[2], const float v1[2], const float point[2], float closest[2]) +{ + float d[2][2], sdist[2]; + VECSUB2D(d[0], v0, point); + VECSUB2D(d[1], v1, point); + + sdist[0] = d[0][0]*d[0][0] + d[0][1]*d[0][1]; + sdist[1] = d[1][0]*d[1][0] + d[1][1]*d[1][1]; + + if(sdist[0] < sdist[1]) + { + if(closest) + VECCOPY2D(closest, v0); + return sdist[0]; + } + else + { + if(closest) + VECCOPY2D(closest, v1); + return sdist[1]; + } +} +/* + * calculates the closest point between point-tri (2D) + * returns that tri must be right-handed + * Returns square distance + */ +static float closest_point_in_tri2D(const float point[2], /*const*/ float tri[3][2], float closest[2]) +{ + float edge_di[2]; + float v_point[2]; + float proj[2]; //point projected over edge-dir, edge-normal (witouth normalized edge) + const float *v0 = tri[2], *v1; + float edge_slen, d; //edge squared length + int i; + const float *nearest_vertex = NULL; + + + //for each edge + for(i=0, v0=tri[2], v1=tri[0]; i < 3; v0=tri[i++], v1=tri[i]) + { + VECSUB2D(edge_di, v1, v0); + VECSUB2D(v_point, point, v0); + + proj[1] = v_point[0]*edge_di[1] - v_point[1]*edge_di[0]; //dot product with edge normal + + //point inside this edge + if(proj[1] < 0) + continue; + + proj[0] = v_point[0]*edge_di[0] + v_point[1]*edge_di[1]; + + //closest to this edge is v0 + if(proj[0] < 0) + { + if(nearest_vertex == NULL || nearest_vertex == v0) + nearest_vertex = v0; + else + { + //choose nearest + return choose_nearest(nearest_vertex, v0, point, closest); + } + i++; //We can skip next edge + continue; + } + + edge_slen = edge_di[0]*edge_di[0] + edge_di[1]*edge_di[1]; //squared edge len + //closest to this edge is v1 + if(proj[0] > edge_slen) + { + if(nearest_vertex == NULL || nearest_vertex == v1) + nearest_vertex = v1; + else + { + return choose_nearest(nearest_vertex, v1, point, closest); + } + continue; + } + + //nearest is on this edge + d= proj[1] / edge_slen; + closest[0] = point[0] - edge_di[1] * d; + closest[1] = point[1] + edge_di[0] * d; + + return proj[1]*proj[1]/edge_slen; + } + + if(nearest_vertex) + { + VECSUB2D(v_point, nearest_vertex, point); + VECCOPY2D(closest, nearest_vertex); + return v_point[0]*v_point[0] + v_point[1]*v_point[1]; + } + else + { + VECCOPY(closest, point); //point is already inside + return 0.0f; + } +} + +/* + * Returns the square of the minimum distance between the point and a triangle surface + * If nearest is not NULL the nearest surface point is written on it + */ +static float nearest_point_in_tri_surface(const float *point, const float *v0, const float *v1, const float *v2, float *nearest) +{ + //Lets solve the 2D problem (closest point-tri) + float normal_dist, plane_sdist, plane_offset; + float du[3], dv[3], dw[3]; //orthogonal axis (du=(v0->v1), dw=plane normal) + + float p_2d[2], tri_2d[3][2], nearest_2d[2]; + + CalcNormFloat((float*)v0, (float*)v1, (float*)v2, dw); + + //point-plane distance and calculate axis + normal_dist = point_plane_distance(point, v0, dw); + + // OPTIMIZATION + // if we are only interested in nearest distance if its closer than some distance already found + // we can: + // if(normal_dist*normal_dist >= best_dist_so_far) return FLOAT_MAX; + // + + VECSUB(du, v1, v0); + Normalize(du); + Crossf(dv, dw, du); + plane_offset = INPR(v0, dw); + + //project stuff to 2d + tri_2d[0][0] = INPR(du, v0); + tri_2d[0][1] = INPR(dv, v0); + + tri_2d[1][0] = INPR(du, v1); + tri_2d[1][1] = INPR(dv, v1); + + tri_2d[2][0] = INPR(du, v2); + tri_2d[2][1] = INPR(dv, v2); + + p_2d[0] = INPR(du, point); + p_2d[1] = INPR(dv, point); + + //we always have a right-handed tri + //this should always happen because of the way normal is calculated + plane_sdist = closest_point_in_tri2D(p_2d, tri_2d, nearest_2d); + + //project back to 3d + if(nearest) + { + nearest[0] = du[0]*nearest_2d[0] + dv[0] * nearest_2d[1] + dw[0] * plane_offset; + nearest[1] = du[1]*nearest_2d[0] + dv[1] * nearest_2d[1] + dw[1] * plane_offset; + nearest[2] = du[2]*nearest_2d[0] + dv[2] * nearest_2d[1] + dw[2] * plane_offset; + } + + return plane_sdist + normal_dist*normal_dist; +} + + +/* + * BVH from meshs callbacks + */ + +// Callback to bvh tree nearest point. The tree must bust have been built using bvhtree_from_mesh_faces. +// userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree. +static void mesh_faces_nearest_point(void *userdata, int index, const float *co, BVHTreeNearest *nearest) +{ + const BVHTreeFromMesh *data = (BVHTreeFromMesh*) userdata; + MVert *vert = data->vert; + MFace *face = data->face + index; + + float *t0, *t1, *t2, *t3; + t0 = vert[ face->v1 ].co; + t1 = vert[ face->v2 ].co; + t2 = vert[ face->v3 ].co; + t3 = face->v4 ? vert[ face->v4].co : NULL; + + + do + { + float nearest_tmp[3], dist; + float vec[3][3]; + + // only insert valid triangles / quads with area > 0 + VECSUB(vec[0], t2, t1); + VECSUB(vec[1], t0, t1); + Crossf(vec[2], vec[0], vec[1]); + if(INPR(vec[2], vec[2]) >= FLT_EPSILON) + { + dist = nearest_point_in_tri_surface(co,t0, t1, t2, nearest_tmp); + if(dist < nearest->dist) + { + nearest->index = index; + nearest->dist = dist; + VECCOPY(nearest->co, nearest_tmp); + CalcNormFloat((float*)t0, (float*)t1, (float*)t2, nearest->no); //TODO.. (interpolate normals from the vertexs coordinates? + } + } + + t1 = t2; + t2 = t3; + t3 = NULL; + + } while(t2); +} + +// Callback to bvh tree raycast. The tree must bust have been built using bvhtree_from_mesh_faces. +// userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree. +static void mesh_faces_spherecast(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit) +{ + const BVHTreeFromMesh *data = (BVHTreeFromMesh*) userdata; + MVert *vert = data->vert; + MFace *face = data->face + index; + + float *t0, *t1, *t2, *t3; + t0 = vert[ face->v1 ].co; + t1 = vert[ face->v2 ].co; + t2 = vert[ face->v3 ].co; + t3 = face->v4 ? vert[ face->v4].co : NULL; + + + do + { + float dist; + if(data->sphere_radius == 0.0f) + dist = ray_tri_intersection(ray, hit->dist, t0, t1, t2); + else + dist = sphereray_tri_intersection(ray, data->sphere_radius, hit->dist, t0, t1, t2); + + if(dist >= 0 && dist < hit->dist) + { + hit->index = index; + hit->dist = dist; + VECADDFAC(hit->co, ray->origin, ray->direction, dist); + + CalcNormFloat(t0, t1, t2, hit->no); + } + + t1 = t2; + t2 = t3; + t3 = NULL; + + } while(t2); +} + +/* + * BVH builders + */ +// Builds a bvh tree.. where nodes are the vertexs of the given mesh +void bvhtree_from_mesh_verts(BVHTreeFromMesh *data, DerivedMesh *mesh, float epsilon, int tree_type, int axis) +{ + int i; + int numVerts= mesh->getNumVerts(mesh); + MVert *vert = mesh->getVertDataArray(mesh, CD_MVERT); + BVHTree *tree = NULL; + + memset(data, 0, sizeof(*data)); + + if(vert == NULL) + { + printf("bvhtree cant be build: cant get a vertex array"); + return; + } + + tree = BLI_bvhtree_new(numVerts, epsilon, tree_type, axis); + if(tree != NULL) + { + for(i = 0; i < numVerts; i++) + BLI_bvhtree_insert(tree, i, vert[i].co, 1); + + BLI_bvhtree_balance(tree); + + data->tree = tree; + + //a NULL nearest callback works fine + //remeber the min distance to point is the same as the min distance to BV of point + data->nearest_callback = NULL; + data->raycast_callback = NULL; + + data->mesh = mesh; + data->vert = mesh->getVertDataArray(mesh, CD_MVERT); + data->face = mesh->getFaceDataArray(mesh, CD_MFACE); + + data->sphere_radius = epsilon; + } +} + +// Builds a bvh tree.. where nodes are the faces of the given mesh. +void bvhtree_from_mesh_faces(BVHTreeFromMesh *data, DerivedMesh *mesh, float epsilon, int tree_type, int axis) +{ + int i; + int numFaces= mesh->getNumFaces(mesh); + MVert *vert = mesh->getVertDataArray(mesh, CD_MVERT); + MFace *face = mesh->getFaceDataArray(mesh, CD_MFACE); + BVHTree *tree = NULL; + + memset(data, 0, sizeof(*data)); + + if(vert == NULL && face == NULL) + { + printf("bvhtree cant be build: cant get a vertex/face array"); + return; + } + + /* Create a bvh-tree of the given target */ + tree = BLI_bvhtree_new(numFaces, epsilon, tree_type, axis); + if(tree != NULL) + { + for(i = 0; i < numFaces; i++) + { + float co[4][3]; + VECCOPY(co[0], vert[ face[i].v1 ].co); + VECCOPY(co[1], vert[ face[i].v2 ].co); + VECCOPY(co[2], vert[ face[i].v3 ].co); + if(face[i].v4) + VECCOPY(co[3], vert[ face[i].v4 ].co); + + BLI_bvhtree_insert(tree, i, co[0], face[i].v4 ? 4 : 3); + } + BLI_bvhtree_balance(tree); + + data->tree = tree; + data->nearest_callback = mesh_faces_nearest_point; + data->raycast_callback = mesh_faces_spherecast; + + data->mesh = mesh; + data->vert = mesh->getVertDataArray(mesh, CD_MVERT); + data->face = mesh->getFaceDataArray(mesh, CD_MFACE); + + data->sphere_radius = epsilon; + } +} + +// Frees data allocated by a call to bvhtree_from_mesh_*. +void free_bvhtree_from_mesh(struct BVHTreeFromMesh *data) +{ + if(data->tree) + { + BLI_bvhtree_free(data->tree); + memset( data, 0, sizeof(data) ); + } +} + + diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 7dca87d5c13..d1c0cdec71d 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -4653,7 +4653,7 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier PTCacheID pid; int totpart, oldtotpart, totchild, oldtotchild, p; float disp, *vg_vel= 0, *vg_tan= 0, *vg_rot= 0, *vg_size= 0; - int init= 0, distr= 0, alloc= 0, usecache= 0; + int init= 0, distr= 0, alloc= 0, usecache= 0, only_children_changed= 0; int framenr, framedelta, startframe, endframe; part= psys->part; @@ -4720,6 +4720,7 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier totchild = get_psys_tot_child(psys); if(oldtotpart != totpart || (psys->part->childtype && oldtotchild != totchild)) { + only_children_changed = (oldtotpart == totpart); realloc_particles(ob, psys, totpart); alloc = 1; distr= 1; @@ -4740,14 +4741,17 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier if((psys->part->type == PART_HAIR) && !(psys->flag & PSYS_HAIR_DONE)) /* don't generate children while growing hair - waste of time */ - psys_free_children(psys); - else if(get_psys_tot_child(psys)) - distribute_particles(ob, psys, PART_FROM_CHILD); + psys_free_children(psys); + else if(get_psys_tot_child(psys)) + distribute_particles(ob, psys, PART_FROM_CHILD); } - initialize_all_particles(ob, psys, psmd); - if(alloc) - reset_all_particles(ob, psys, psmd, 0.0, cfra, oldtotpart); + if(only_children_changed==0) { + initialize_all_particles(ob, psys, psmd); + + if(alloc) + reset_all_particles(ob, psys, psmd, 0.0, cfra, oldtotpart); + } /* flag for possible explode modifiers after this system */ psmd->flag |= eParticleSystemFlag_Pars; diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index da1dcfa6c5b..936381c85cc 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -545,6 +545,8 @@ Tex *copy_texture(Tex *tex) if(texn->type==TEX_IMAGE) id_us_plus((ID *)texn->ima); else texn->ima= 0; + id_us_plus((ID *)texn->ipo); + if(texn->plugin) { texn->plugin= MEM_dupallocN(texn->plugin); open_plugin_tex(texn->plugin); diff --git a/source/blender/blenlib/BLI_kdopbvh.h b/source/blender/blenlib/BLI_kdopbvh.h index 6d9c82a9626..6d9a17efebf 100644 --- a/source/blender/blenlib/BLI_kdopbvh.h +++ b/source/blender/blenlib/BLI_kdopbvh.h @@ -1,5 +1,7 @@ /** * + * $Id$ + * * ***** BEGIN GPL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index 7f634def386..9671551a7f1 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -43,6 +43,10 @@ #include <omp.h> #endif + + +#define MAX_TREETYPE 32 + typedef struct BVHNode { struct BVHNode **children; @@ -71,6 +75,7 @@ typedef struct BVHOverlapData BVHTree *tree1, *tree2; BVHTreeOverlap *overlap; int i, max_overlap; /* i is number of overlaps */ + int start_axis, stop_axis; } BVHOverlapData; typedef struct BVHNearestData @@ -489,7 +494,7 @@ static void verify_tree(BVHTree *tree) #endif //Helper data and structures to build a min-leaf generalized implicit tree -//This code can be easily reduced (basicly this is only method to calculate pow(k, n) in O(1).. and sutff like that) +//This code can be easily reduced (basicly this is only method to calculate pow(k, n) in O(1).. and stuff like that) typedef struct BVHBuildHelper { int tree_type; // @@ -647,7 +652,7 @@ static void non_recursive_bvh_div_nodes(BVHTree *tree, BVHNode *branches_array, int k; const int parent_level_index= j-i; BVHNode* parent = branches_array + j; - int nth_positions[ tree_type + 1 ]; + int nth_positions[ MAX_TREETYPE + 1]; char split_axis; int parent_leafs_begin = implicit_leafs_index(&data, depth, parent_level_index); @@ -712,6 +717,9 @@ BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis) // theres not support for trees below binary-trees :P if(tree_type < 2) return NULL; + + if(tree_type > MAX_TREETYPE) + return NULL; tree = (BVHTree *)MEM_callocN(sizeof(BVHTree), "BVHTree"); @@ -904,7 +912,7 @@ void BLI_bvhtree_update_tree(BVHTree *tree) BVHNode** root = tree->nodes + tree->totleaf; BVHNode** index = tree->nodes + tree->totleaf + tree->totbranch-1; - for (; index != root; index--) + for (; index >= root; index--) node_join(tree, *index); } @@ -942,7 +950,7 @@ static void traverse(BVHOverlapData *data, BVHNode *node1, BVHNode *node2) { int j; - if(tree_overlap(node1, node2, MIN2(data->tree1->start_axis, data->tree2->start_axis), MIN2(data->tree1->stop_axis, data->tree2->stop_axis))) + if(tree_overlap(node1, node2, data->start_axis, data->stop_axis)) { // check if node1 is a leaf if(!node1->totnode) @@ -1023,6 +1031,8 @@ BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, int *result) data[j]->tree2 = tree2; data[j]->max_overlap = MAX2(tree1->totleaf, tree2->totleaf); data[j]->i = 0; + data[j]->start_axis = MIN2(tree1->start_axis, tree2->start_axis); + data[j]->stop_axis = MIN2(tree1->stop_axis, tree2->stop_axis ); } #pragma omp parallel for private(j) schedule(static) diff --git a/source/blender/include/BIF_editarmature.h b/source/blender/include/BIF_editarmature.h index 13c16749612..07fc8f08b4a 100644 --- a/source/blender/include/BIF_editarmature.h +++ b/source/blender/include/BIF_editarmature.h @@ -114,6 +114,7 @@ void setflag_armature(short mode); void unique_editbone_name (struct ListBase *ebones, char *name); void auto_align_armature(short mode); +void switch_direction_armature(void); void create_vgroups_from_armature(struct Object *ob, struct Object *par); void add_verts_to_dgroups(struct Object *ob, struct Object *par, int heat, int mirror); @@ -135,7 +136,6 @@ void transform_armature_mirror_update(void); void hide_selected_armature_bones(void); void hide_unselected_armature_bones(void); void show_all_armature_bones(void); -void set_locks_armature_bones(short lock); #define BONESEL_ROOT 0x10000000 #define BONESEL_TIP 0x20000000 @@ -144,6 +144,10 @@ void set_locks_armature_bones(short lock); #define BONESEL_NOSEL 0x80000000 /* Indicates a negative number */ +/* useful macros */ +#define EBONE_VISIBLE(arm, ebone) ((arm->layer & ebone->layer) && !(ebone->flag & BONE_HIDDEN_A)) +#define EBONE_EDITABLE(ebone) ((ebone->flag & BONE_SELECTED) && !(ebone->flag & BONE_EDITMODE_LOCKED)) + /* used in bone_select_hierachy() */ #define BONE_SELECT_PARENT 0 #define BONE_SELECT_CHILD 1 diff --git a/source/blender/include/BIF_editmesh.h b/source/blender/include/BIF_editmesh.h index ca9f3d6a378..9354a577ac1 100644 --- a/source/blender/include/BIF_editmesh.h +++ b/source/blender/include/BIF_editmesh.h @@ -132,7 +132,7 @@ extern int EM_check_backbuf(unsigned int index); extern void EM_free_backbuf(void); extern void EM_selectmode_menu(void); - +extern void EM_mesh_copy_face(short type); extern void vertexnoise(void); extern void vertexsmooth(void); diff --git a/source/blender/include/butspace.h b/source/blender/include/butspace.h index af74946f0e6..b8c3584a45e 100644 --- a/source/blender/include/butspace.h +++ b/source/blender/include/butspace.h @@ -593,7 +593,7 @@ void curvemap_buttons(struct uiBlock *block, struct CurveMapping *cumap, char la #define B_VPCOLSLI 2801 #define B_VPGAMMA 2802 - +#define B_COPY_TF_TRANSP 2803 #define B_COPY_TF_MODE 2804 #define B_COPY_TF_UV 2805 #define B_COPY_TF_COL 2806 diff --git a/source/blender/python/api2_2x/doc/Render.py b/source/blender/python/api2_2x/doc/Render.py index d4dc83e84a0..5300fdab808 100644 --- a/source/blender/python/api2_2x/doc/Render.py +++ b/source/blender/python/api2_2x/doc/Render.py @@ -170,17 +170,6 @@ def SetRenderWinPos(locationList): the location of the Render window on the screen. """ -def EnableEdgeShift(): - """ - Globally with the unified renderer enabled the outlines of the render - are shifted a bit. - """ - -def EnableEdgeAll(): - """ - Globally consider transparent faces for edge-rendering with the unified renderer. - """ - class RenderData: """ The RenderData object @@ -772,7 +761,7 @@ class RenderData: """ Get/set the starting frame for sequence rendering. @type frame: int (optional) - @param frame: must be between 1 - 18000 + @param frame: must be a valid Blender frame number. @rtype: int (if prototype is empty) @return: Current starting frame for the scene. """ @@ -781,7 +770,7 @@ class RenderData: """ Get/set the ending frame for sequence rendering. @type frame: int (optional) - @param frame: must be between 1 - 18000 + @param frame: must be a valid Blender frame number. @rtype: int (if prototype is empty) @return: Current ending frame for the scene. """ diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index 1155d2ea817..c352a83d0f4 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -263,7 +263,12 @@ static void shade_ray(Isect *is, ShadeInput *shi, ShadeResult *shr) shade_input_set_shade_texco(shi); if(is->mode==RE_RAY_SHADOW_TRA) - shade_color(shi, shr); + if(shi->mat->nodetree && shi->mat->use_nodes) { + ntreeShaderExecTree(shi->mat->nodetree, shi, shr); + shi->mat= vlr->mat; /* shi->mat is being set in nodetree */ + } + else + shade_color(shi, shr); else { if(shi->mat->nodetree && shi->mat->use_nodes) { ntreeShaderExecTree(shi->mat->nodetree, shi, shr); diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index 63ef31b6062..bfdd4f0c9a0 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -5825,13 +5825,9 @@ void sculptmode_draw_interface_textures(uiBlock *block, unsigned short cx, unsig void do_fpaintbuts(unsigned short event) { - Mesh *me; Object *ob; bDeformGroup *defGroup; - MTFace *activetf, *tf; - MFace *mf; - MCol *activemcol; - int a; + MTFace *activetf; SculptData *sd= &G.scene->sculptdata; ID *id, *idtest; extern VPaint Gwp; /* from vpaint */ @@ -5849,45 +5845,19 @@ void do_fpaintbuts(unsigned short event) vpaint_dogamma(); break; case B_COPY_TF_MODE: + EM_mesh_copy_face(4); /* todo, get rid of magic numbers */ + break; + case B_COPY_TF_TRANSP: + EM_mesh_copy_face(5); + break; case B_COPY_TF_UV: + EM_mesh_copy_face(3); + break; case B_COPY_TF_COL: + EM_mesh_copy_face(6); + break; case B_COPY_TF_TEX: - me= get_mesh(OBACT); - activetf= get_active_mtface(NULL, &activemcol, 0); - - if(me && activetf) { - for (a=0, tf=me->mtface, mf=me->mface; a < me->totface; a++, tf++, mf++) { - if(tf!=activetf && (mf->flag & ME_FACE_SEL)) { - if(event==B_COPY_TF_MODE) { - tf->mode= activetf->mode; - tf->transp= activetf->transp; - } - else if(event==B_COPY_TF_UV) { - memcpy(tf->uv, activetf->uv, sizeof(tf->uv)); - tf->tpage= activetf->tpage; - tf->tile= activetf->tile; - - if(activetf->mode & TF_TILES) tf->mode |= TF_TILES; - else tf->mode &= ~TF_TILES; - - } - else if(event==B_COPY_TF_TEX) { - tf->tpage= activetf->tpage; - tf->tile= activetf->tile; - - if(activetf->mode & TF_TILES) tf->mode |= TF_TILES; - else tf->mode &= ~TF_TILES; - } - else if(event==B_COPY_TF_COL && activemcol) - memcpy(&me->mcol[a*4], activemcol, sizeof(MCol)*4); - } - } - - DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); - do_shared_vertexcol(me); - allqueue(REDRAWVIEW3D, 0); - allqueue(REDRAWIMAGE, 0); - } + EM_mesh_copy_face(2); break; case B_SET_VCOL: if(FACESEL_PAINT_TEST) @@ -6324,8 +6294,20 @@ static void editing_panel_mesh_texface(void) if(uiNewPanel(curarea, block, "Texture Face", "Editing", 960, 0, 318, 204)==0) return; tf = get_active_mtface(NULL, NULL, 0); + if(tf) { + uiDefBut(block, LABEL, B_NOP, "Active Face Mode", 600,185,300,19, NULL, 0.0, 0.0, 0, 0, "Face mode its used for TexFace display and the game engine "); + uiDefBut(block, BUT,B_COPY_TF_MODE, "Copy", 850,185,50,19, 0, 0, 0, 0, 0, "Copy active faces mode to other selected (View3D Ctrl+C)"); + + /* Other copy buttons, layout isnt that nice */ uiBlockBeginAlign(block); + uiDefBut(block, BUT,B_COPY_TF_UV, "CopyUV", 600,15,100,19, 0, 0, 0, 0, 0, "Copy active faces UVs to other selected (View3D Ctrl+C)"); + uiDefBut(block, BUT,B_COPY_TF_TEX, "CopyTex", 700,15,100,19, 0, 0, 0, 0, 0, "Copy active faces Texture to other selected (View3D Ctrl+C)"); + uiDefBut(block, BUT,B_COPY_TF_COL, "CopyColor", 800,15,100,19, 0, 0, 0, 0, 0, "Copy active faces Color to other selected (View3D Ctrl+C)"); + uiBlockEndAlign(block); + + uiBlockBeginAlign(block); + uiDefButBitS(block, TOG, TF_TEX, B_REDR_3D_IMA, "Tex", 600,160,60,19, &tf->mode, 0, 0, 0, 0, "Render face with texture"); uiDefButBitS(block, TOG, TF_TILES, B_REDR_3D_IMA, "Tiles", 660,160,60,19, &tf->mode, 0, 0, 0, 0, "Use tilemode for face"); uiDefButBitS(block, TOG, TF_LIGHT, REDRAWVIEW3D, "Light", 720,160,60,19, &tf->mode, 0, 0, 0, 0, "Use light for face"); @@ -6336,24 +6318,30 @@ static void editing_panel_mesh_texface(void) uiDefButBitS(block, TOG, TF_SHAREDCOL, REDRAWVIEW3D, "Shared", 600,135,60,19, &tf->mode, 0, 0, 0, 0, "Blend vertex colors across face when vertices are shared"); uiDefButBitS(block, TOG, TF_TWOSIDE, REDRAWVIEW3D, "Twoside",660,135,60,19, &tf->mode, 0, 0, 0, 0, "Render face twosided"); uiDefButBitS(block, TOG, TF_OBCOL, REDRAWVIEW3D, "ObColor",720,135,60,19, &tf->mode, 0, 0, 0, 0, "Use ObColor instead of vertex colors"); - - uiBlockBeginAlign(block); + uiBlockEndAlign(block); + uiBlockBeginAlign(block); uiDefButBitS(block, TOG, TF_BILLBOARD, B_TFACE_HALO, "Halo", 600,110,60,19, &tf->mode, 0, 0, 0, 0, "Screen aligned billboard"); uiDefButBitS(block, TOG, TF_BILLBOARD2, B_TFACE_BILLB, "Billboard",660,110,60,19, &tf->mode, 0, 0, 0, 0, "Billboard with Z-axis constraint"); uiDefButBitS(block, TOG, TF_SHADOW, REDRAWVIEW3D, "Shadow", 720,110,60,19, &tf->mode, 0, 0, 0, 0, "Face is used for shadow"); uiDefButBitS(block, TOG, TF_BMFONT, REDRAWVIEW3D, "Text", 780,110,60,19, &tf->mode, 0, 0, 0, 0, "Enable bitmap text on face"); uiDefButBitS(block, TOG, TF_ALPHASORT, REDRAWVIEW3D, "Sort", 840,110,60,19, &tf->mode, 0, 0, 0, 0, "Enable sorting of faces for correct alpha drawing (slow, use Clip Alpha instead when possible)"); - + uiBlockEndAlign(block); + + uiDefBut(block, LABEL, B_NOP, "Active Face Alpha Blending (Transp)", 600,75,300,19, NULL, 0.0, 0.0, 0, 0, "Face mode its used for TexFace display and the game engine"); + uiDefBut(block, BUT,B_COPY_TF_TRANSP, "Copy", 850,75,50,19, 0, 0, 0, 0, 0, "Copy active faces transp to other selected (View3D Ctrl+C)"); + uiBlockBeginAlign(block); uiBlockSetCol(block, TH_BUT_SETTING1); - uiDefButC(block, ROW, REDRAWVIEW3D, "Opaque", 600,80,60,19, &tf->transp, 2.0, (float)TF_SOLID,0, 0, "Render color of textured face as color"); - uiDefButC(block, ROW, REDRAWVIEW3D, "Add", 660,80,60,19, &tf->transp, 2.0, (float)TF_ADD, 0, 0, "Render face transparent and add color of face"); - uiDefButC(block, ROW, REDRAWVIEW3D, "Alpha", 720,80,60,19, &tf->transp, 2.0, (float)TF_ALPHA,0, 0, "Render polygon transparent, depending on alpha channel of the texture"); - uiDefButC(block, ROW, REDRAWVIEW3D, "Clip Alpha", 780,80,80,19, &tf->transp, 2.0, (float)TF_CLIP,0, 0, "Use the images alpha values clipped with no blending (binary alpha)"); - } - else + uiDefButC(block, ROW, REDRAWVIEW3D, "Opaque", 600,50,60,19, &tf->transp, 2.0, (float)TF_SOLID,0, 0, "Render color of textured face as color"); + uiDefButC(block, ROW, REDRAWVIEW3D, "Add", 660,50,60,19, &tf->transp, 2.0, (float)TF_ADD, 0, 0, "Render face transparent and add color of face"); + uiDefButC(block, ROW, REDRAWVIEW3D, "Alpha", 720,50,60,19, &tf->transp, 2.0, (float)TF_ALPHA,0, 0, "Render polygon transparent, depending on alpha channel of the texture"); + uiDefButC(block, ROW, REDRAWVIEW3D, "Clip Alpha", 780,50,80,19, &tf->transp, 2.0, (float)TF_CLIP,0, 0, "Use the images alpha values clipped with no blending (binary alpha)"); + uiBlockEndAlign(block); + + } else { uiDefBut(block,LABEL,B_NOP, "(No Active Face)", 10,200,150,19,0,0,0,0,0,""); + } } diff --git a/source/blender/src/editarmature.c b/source/blender/src/editarmature.c index 80c24f3a989..35986fcff4a 100644 --- a/source/blender/src/editarmature.c +++ b/source/blender/src/editarmature.c @@ -854,6 +854,7 @@ static void separate_armature_bones (Object *ob, short sel) BLI_freelistN(&edbo); } +/* separate selected bones into their armature */ void separate_armature (void) { Object *oldob, *newob; @@ -1094,13 +1095,13 @@ void armature_select_hierarchy(short direction, short add_to_sel) arm= (bArmature *)ob->data; for (curbone= G.edbo.first; curbone; curbone= curbone->next) { - if (arm->layer & curbone->layer) { + if (EBONE_VISIBLE(arm, curbone)) { if (curbone->flag & (BONE_ACTIVE)) { if (direction == BONE_SELECT_PARENT) { if (curbone->parent == NULL) continue; else pabone = curbone->parent; - if ((arm->layer & pabone->layer) && !(pabone->flag & BONE_HIDDEN_A)) { + if (EBONE_VISIBLE(arm, pabone)) { pabone->flag |= (BONE_ACTIVE|BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL); if (pabone->parent) pabone->parent->flag |= BONE_TIPSEL; @@ -1109,11 +1110,12 @@ void armature_select_hierarchy(short direction, short add_to_sel) break; } - } else { // BONE_SELECT_CHILD + } + else { // BONE_SELECT_CHILD chbone = editbone_get_child(curbone, 1); if (chbone == NULL) continue; - if ((arm->layer & chbone->layer) && !(chbone->flag & BONE_HIDDEN_A)) { + if (EBONE_VISIBLE(arm, chbone)) { chbone->flag |= (BONE_ACTIVE|BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL); if (!add_to_sel) { @@ -1159,17 +1161,18 @@ void setflag_armature (short mode) /* get flag to set (sync these with the ones used in eBone_Flag */ if (mode == 2) - flag= pupmenu("Disable Setting%t|Draw Wire%x1|Deform%x2|Mult VG%x3|Hinge%x4|No Scale%x5"); + flag= pupmenu("Disable Setting%t|Draw Wire%x1|Deform%x2|Mult VG%x3|Hinge%x4|No Scale%x5|Locked%x6"); else if (mode == 1) - flag= pupmenu("Enable Setting%t|Draw Wire%x1|Deform%x2|Mult VG%x3|Hinge%x4|No Scale%x5"); + flag= pupmenu("Enable Setting%t|Draw Wire%x1|Deform%x2|Mult VG%x3|Hinge%x4|No Scale%x5|Locked%x6"); else - flag= pupmenu("Toggle Setting%t|Draw Wire%x1|Deform%x2|Mult VG%x3|Hinge%x4|No Scale%x5"); + flag= pupmenu("Toggle Setting%t|Draw Wire%x1|Deform%x2|Mult VG%x3|Hinge%x4|No Scale%x5|Locked%x6"); switch (flag) { case 1: flag = BONE_DRAWWIRE; break; case 2: flag = BONE_NO_DEFORM; break; case 3: flag = BONE_MULT_VG_ENV; break; case 4: flag = BONE_HINGE; break; case 5: flag = BONE_NO_SCALE; break; + case 6: flag = BONE_EDITMODE_LOCKED; break; default: return; } @@ -1725,12 +1728,12 @@ void auto_align_armature(short mode) float *cursor= give_cursor(); for (ebone = G.edbo.first; ebone; ebone=ebone->next) { - if (arm->layer & ebone->layer) { + if (EBONE_VISIBLE(arm, ebone)) { if (arm->flag & ARM_MIRROR_EDIT) flipbone = armature_bone_get_mirrored(ebone); if ((ebone->flag & BONE_SELECTED) || - (flipbone && flipbone->flag & BONE_SELECTED)) + (flipbone && (flipbone->flag & BONE_SELECTED))) { /* specific method used to calculate roll depends on mode */ if (mode == 1) { @@ -1975,7 +1978,7 @@ void addvert_armature(void) /* find the active or selected bone */ for (ebone = G.edbo.first; ebone; ebone=ebone->next) { - if (arm->layer & ebone->layer) { + if (EBONE_VISIBLE(arm, ebone)) { if (ebone->flag & (BONE_ACTIVE|BONE_TIPSEL)) break; } @@ -1983,7 +1986,7 @@ void addvert_armature(void) if (ebone==NULL) { for (ebone = G.edbo.first; ebone; ebone=ebone->next) { - if (arm->layer & ebone->layer) { + if (EBONE_VISIBLE(arm, ebone)) { if (ebone->flag & (BONE_ACTIVE|BONE_ROOTSEL)) break; } @@ -2066,11 +2069,12 @@ static EditBone *get_named_editbone(char *name) { EditBone *eBone; - if (name) + if (name) { for (eBone=G.edbo.first; eBone; eBone=eBone->next) { if (!strcmp(name, eBone->name)) return eBone; } + } return NULL; } @@ -2136,7 +2140,7 @@ void adduplicate_armature(void) /* Select mirrored bones */ if (arm->flag & ARM_MIRROR_EDIT) { for (curBone=G.edbo.first; curBone; curBone=curBone->next) { - if (arm->layer & curBone->layer) { + if (EBONE_VISIBLE(arm, curBone)) { if (curBone->flag & BONE_SELECTED) { eBone = armature_bone_get_mirrored(curBone); if (eBone) @@ -2148,13 +2152,13 @@ void adduplicate_armature(void) /* Find the selected bones and duplicate them as needed */ for (curBone=G.edbo.first; curBone && curBone!=firstDup; curBone=curBone->next) { - if (arm->layer & curBone->layer) { + if (EBONE_VISIBLE(arm, curBone)) { if (curBone->flag & BONE_SELECTED) { eBone=MEM_callocN(sizeof(EditBone), "addup_editbone"); eBone->flag |= BONE_SELECTED; /* Copy data from old bone to new bone */ - memcpy (eBone, curBone, sizeof(EditBone)); + memcpy(eBone, curBone, sizeof(EditBone)); curBone->temp = eBone; eBone->temp = curBone; @@ -2204,7 +2208,7 @@ void adduplicate_armature(void) /* Run though the list and fix the pointers */ for (curBone=G.edbo.first; curBone && curBone!=firstDup; curBone=curBone->next) { - if (arm->layer & curBone->layer) { + if (EBONE_VISIBLE(arm, curBone)) { if (curBone->flag & BONE_SELECTED) { eBone=(EditBone*) curBone->temp; @@ -2236,7 +2240,7 @@ void adduplicate_armature(void) /* Deselect the old bones and select the new ones */ for (curBone=G.edbo.first; curBone && curBone!=firstDup; curBone=curBone->next) { - if (arm->layer & curBone->layer) + if (EBONE_VISIBLE(arm, curBone)) curBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL | BONE_ACTIVE); } @@ -2373,7 +2377,7 @@ void fill_bones_armature(void) /* loop over all bones, and only consider if visible */ for (ebo= G.edbo.first; ebo; ebo= ebo->next) { - if ((arm->layer & ebo->layer) && !(ebo->flag & BONE_HIDDEN_A)) { + if (EBONE_VISIBLE(arm, ebo)) { if (!(ebo->flag & BONE_CONNECTED) && (ebo->flag & BONE_ROOTSEL)) fill_add_joint(ebo, 0, &points); if (ebo->flag & BONE_TIPSEL) @@ -2608,7 +2612,7 @@ void merge_armature(void) /* only consider bones that are visible and selected */ for (ebo=chain->data; ebo; child=ebo, ebo=ebo->parent) { /* check if visible + selected */ - if ( (arm->layer & ebo->layer) && !(ebo->flag & BONE_HIDDEN_A) && + if ( EBONE_VISIBLE(arm, ebo) && ((ebo->flag & BONE_CONNECTED) || (ebo->parent==NULL)) && (ebo->flag & (BONE_SELECTED|BONE_ACTIVE)) ) { @@ -2659,7 +2663,7 @@ void hide_selected_armature_bones(void) EditBone *ebone; for (ebone = G.edbo.first; ebone; ebone=ebone->next) { - if (arm->layer & ebone->layer) { + if (EBONE_VISIBLE(arm, ebone)) { if (ebone->flag & (BONE_SELECTED)) { ebone->flag &= ~(BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL|BONE_ACTIVE); ebone->flag |= BONE_HIDDEN_A; @@ -2678,7 +2682,7 @@ void hide_unselected_armature_bones(void) for (ebone = G.edbo.first; ebone; ebone=ebone->next) { bArmature *arm= G.obedit->data; - if (arm->layer & ebone->layer) { + if (EBONE_VISIBLE(arm, ebone)) { if (ebone->flag & (BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL)); else { ebone->flag &= ~BONE_ACTIVE; @@ -2711,32 +2715,6 @@ void show_all_armature_bones(void) BIF_undo_push("Reveal Bones"); } -/* Sets editmode transform locks for bones (adds if lock==1, clears otherwise) */ -void set_locks_armature_bones(short lock) -{ - bArmature *arm= G.obedit->data; - EditBone *ebone; - - for (ebone = G.edbo.first; ebone; ebone=ebone->next) { - if (arm->layer & ebone->layer) { - if (ebone->flag & BONE_SELECTED) { - if (lock) - ebone->flag |= BONE_EDITMODE_LOCKED; - else - ebone->flag &= ~BONE_EDITMODE_LOCKED; - } - } - } - countall(); - allqueue(REDRAWVIEW3D, 0); - allqueue(REDRAWBUTSEDIT, 0); - - if (lock) - BIF_undo_push("Lock Bones"); - else - BIF_undo_push("Unlock Bones"); -} - /* check for null, before calling! */ static void bone_connect_to_existing_parent(EditBone *bone) { @@ -2803,7 +2781,7 @@ void make_bone_parent(void) /* find active bone to parent to */ for (actbone = G.edbo.first; actbone; actbone=actbone->next) { - if (arm->layer & actbone->layer) { + if (EBONE_VISIBLE(arm, actbone)) { if (actbone->flag & BONE_ACTIVE) break; } @@ -2815,7 +2793,7 @@ void make_bone_parent(void) /* find selected bones */ for (ebone = G.edbo.first; ebone; ebone=ebone->next) { - if (arm->layer & ebone->layer) { + if (EBONE_VISIBLE(arm, ebone)) { if ((ebone->flag & BONE_SELECTED) && (ebone != actbone)) { foundselbone++; if (ebone->parent != actbone) allchildbones= 1; @@ -2851,7 +2829,7 @@ void make_bone_parent(void) else { /* loop through all editbones, parenting all selected bones to the active bone */ for (selbone = G.edbo.first; selbone; selbone=selbone->next) { - if (arm->layer & selbone->layer) { + if (EBONE_VISIBLE(arm, selbone)) { if ((selbone->flag & BONE_SELECTED) && (selbone!=actbone)) { /* parent selbone to actbone */ bone_connect_to_new_parent(selbone, actbone, val); @@ -2909,7 +2887,7 @@ void clear_bone_parent(void) if (val<1) return; for (ebone = G.edbo.first; ebone; ebone=ebone->next) { - if (arm->layer & ebone->layer) { + if (EBONE_VISIBLE(arm, ebone)) { if (ebone->flag & BONE_SELECTED) { if (arm->flag & ARM_MIRROR_EDIT) flipbone = armature_bone_get_mirrored(ebone); @@ -2959,7 +2937,7 @@ void unique_editbone_name (ListBase *ebones, char *name) } for (number = 1; number <=999; number++) { - sprintf (tempname, "%s.%03d", name, number); + sprintf(tempname, "%s.%03d", name, number); if (!editbone_name_exists(ebones, tempname)) { BLI_strncpy(name, tempname, 32); return; @@ -2980,7 +2958,7 @@ void extrude_armature(int forked) /* since we allow root extrude too, we have to make sure selection is OK */ for (ebone = G.edbo.first; ebone; ebone=ebone->next) { - if (arm->layer & ebone->layer) { + if (EBONE_VISIBLE(arm, ebone)) { if (ebone->flag & BONE_ROOTSEL) { if (ebone->parent && (ebone->flag & BONE_CONNECTED)) { if (ebone->parent->flag & BONE_TIPSEL) @@ -2992,7 +2970,7 @@ void extrude_armature(int forked) /* Duplicate the necessary bones */ for (ebone = G.edbo.first; ((ebone) && (ebone!=first)); ebone=ebone->next) { - if (arm->layer & ebone->layer) { + if (EBONE_VISIBLE(arm, ebone)) { /* we extrude per definition the tip */ do_extrude= 0; if (ebone->flag & (BONE_TIPSEL|BONE_SELECTED)) @@ -3006,7 +2984,7 @@ void extrude_armature(int forked) if (do_extrude) { /* we re-use code for mirror editing... */ flipbone= NULL; - if(arm->flag & ARM_MIRROR_EDIT) { + if (arm->flag & ARM_MIRROR_EDIT) { flipbone= armature_bone_get_mirrored(ebone); if (flipbone) { forked= 0; // we extrude 2 different bones @@ -3036,7 +3014,7 @@ void extrude_armature(int forked) newbone->parent = ebone; newbone->flag = ebone->flag & BONE_TIPSEL; // copies it, in case mirrored bone - + if (newbone->parent) newbone->flag |= BONE_CONNECTED; } else { @@ -3046,7 +3024,7 @@ void extrude_armature(int forked) newbone->flag= BONE_TIPSEL; - if (newbone->parent && ebone->flag & BONE_CONNECTED) { + if (newbone->parent && (ebone->flag & BONE_CONNECTED)) { newbone->flag |= BONE_CONNECTED; } } @@ -3065,8 +3043,8 @@ void extrude_armature(int forked) BLI_strncpy (newbone->name, ebone->name, 32); if (flipbone && forked) { // only set if mirror edit - if(strlen(newbone->name)<30) { - if(a==0) strcat(newbone->name, "_L"); + if (strlen(newbone->name)<30) { + if (a==0) strcat(newbone->name, "_L"); else strcat(newbone->name, "_R"); } } @@ -3111,7 +3089,7 @@ void subdivide_armature(int numcuts) if (numcuts < 1) return; for (mbone = G.edbo.last; mbone; mbone= mbone->prev) { - if (arm->layer & mbone->layer) { + if (EBONE_VISIBLE(arm, mbone)) { if (mbone->flag & BONE_SELECTED) { for (i=numcuts+1; i>1; i--) { /* compute cut ratio first */ @@ -3176,6 +3154,59 @@ void subdivide_armature(int numcuts) else BIF_undo_push("Subdivide multi"); } +/* switch direction of bone chains */ +void switch_direction_armature (void) +{ + bArmature *arm= (G.obedit) ? G.obedit->data : NULL; + ListBase chains = {NULL, NULL}; + LinkData *chain; + + /* error checking paranoia */ + if (arm == NULL) + return; + + /* get chains of bones (ends on chains) */ + chains_find_tips(&chains); + if (chains.first == NULL) return; + + /* loop over chains, only considering selected and visible bones */ + for (chain= chains.first; chain; chain= chain->next) { + EditBone *ebo, *child=NULL, *parent=NULL; + + /* loop over bones in chain */ + for (ebo= chain->data; ebo; child= ebo, ebo=parent) { + parent= ebo->parent; + + /* only if selected and editable */ + if (EBONE_VISIBLE(arm, ebo) && EBONE_EDITABLE(ebo)) { + /* swap head and tail coordinates */ + SWAP(float, ebo->head[0], ebo->tail[0]); + SWAP(float, ebo->head[1], ebo->tail[1]); + SWAP(float, ebo->head[2], ebo->tail[2]); + + /* do parent swapping: + * - use 'child' as new parent + * - connected flag is only set if points are coincidental + */ + ebo->parent= child; + if ((child) && VecEqual(ebo->head, child->tail)) + ebo->flag |= BONE_CONNECTED; + else + ebo->flag &= ~BONE_CONNECTED; + + /* FIXME: other things that need fixing? + * i.e. roll? + */ + } + } + } + + /* free chains */ + BLI_freelistN(&chains); + + BIF_undo_push("Switch Direction"); +} + /* ***************** Pose tools ********************* */ void clear_armature(Object *ob, char mode) diff --git a/source/blender/src/editmesh_mods.c b/source/blender/src/editmesh_mods.c index c7a75b32df1..6dfbd67720b 100644 --- a/source/blender/src/editmesh_mods.c +++ b/source/blender/src/editmesh_mods.c @@ -1432,361 +1432,398 @@ int mesh_layers_menu(CustomData *data, int type) { return ret; } -/* ctrl+c in mesh editmode */ -void mesh_copy_menu(void) +void EM_mesh_copy_edge(short type) { EditMesh *em = G.editMesh; EditSelection *ese; - short ret, change=0; + short change=0; + + EditEdge *eed, *eed_act; + float vec[3], vec_mid[3], eed_len, eed_len_act; if (!em) return; ese = em->selected.last; + if (!ese) return; - /* Faces can have a NULL ese, so dont return on a NULL ese here */ + eed_act = (EditEdge*)ese->data; - if(ese && ese->type == EDITVERT) { - - if (!ese) return; - /*EditVert *ev, *ev_act = (EditVert*)ese->data; - ret= pupmenu("");*/ - } else if(ese && ese->type == EDITEDGE) { - EditEdge *eed, *eed_act; - float vec[3], vec_mid[3], eed_len, eed_len_act; - - if (!ese) return; - - eed_act = (EditEdge*)ese->data; - - ret= pupmenu("Copy Active Edge to Selected%t|Crease%x1|Bevel Weight%x2|Length%x3"); - if (ret<1) return; - - eed_len_act = VecLenf(eed_act->v1->co, eed_act->v2->co); - - switch (ret) { - case 1: /* copy crease */ - for(eed=em->edges.first; eed; eed=eed->next) { - if (eed->f & SELECT && eed != eed_act && eed->crease != eed_act->crease) { - eed->crease = eed_act->crease; - change = 1; - } + switch (type) { + case 1: /* copy crease */ + for(eed=em->edges.first; eed; eed=eed->next) { + if (eed->f & SELECT && eed != eed_act && eed->crease != eed_act->crease) { + eed->crease = eed_act->crease; + change = 1; } - break; - case 2: /* copy bevel weight */ - for(eed=em->edges.first; eed; eed=eed->next) { - if (eed->f & SELECT && eed != eed_act && eed->bweight != eed_act->bweight) { - eed->bweight = eed_act->bweight; - change = 1; - } + } + break; + case 2: /* copy bevel weight */ + for(eed=em->edges.first; eed; eed=eed->next) { + if (eed->f & SELECT && eed != eed_act && eed->bweight != eed_act->bweight) { + eed->bweight = eed_act->bweight; + change = 1; } - break; - - case 3: /* copy length */ - - for(eed=em->edges.first; eed; eed=eed->next) { - if (eed->f & SELECT && eed != eed_act) { - - eed_len = VecLenf(eed->v1->co, eed->v2->co); - - if (eed_len == eed_len_act) continue; - /* if this edge is zero length we cont do anything with it*/ - if (eed_len == 0.0f) continue; - if (eed_len_act == 0.0f) { - VecAddf(vec_mid, eed->v1->co, eed->v2->co); - VecMulf(vec_mid, 0.5); - VECCOPY(eed->v1->co, vec_mid); - VECCOPY(eed->v2->co, vec_mid); - } else { - /* copy the edge length */ - VecAddf(vec_mid, eed->v1->co, eed->v2->co); - VecMulf(vec_mid, 0.5); - - /* SCALE 1 */ - VecSubf(vec, eed->v1->co, vec_mid); - VecMulf(vec, eed_len_act/eed_len); - VecAddf(eed->v1->co, vec, vec_mid); - - /* SCALE 2 */ - VecSubf(vec, eed->v2->co, vec_mid); - VecMulf(vec, eed_len_act/eed_len); - VecAddf(eed->v2->co, vec, vec_mid); - } - change = 1; + } + break; + + case 3: /* copy length */ + eed_len_act = VecLenf(eed_act->v1->co, eed_act->v2->co); + for(eed=em->edges.first; eed; eed=eed->next) { + if (eed->f & SELECT && eed != eed_act) { + + eed_len = VecLenf(eed->v1->co, eed->v2->co); + + if (eed_len == eed_len_act) continue; + /* if this edge is zero length we cont do anything with it*/ + if (eed_len == 0.0f) continue; + if (eed_len_act == 0.0f) { + VecAddf(vec_mid, eed->v1->co, eed->v2->co); + VecMulf(vec_mid, 0.5); + VECCOPY(eed->v1->co, vec_mid); + VECCOPY(eed->v2->co, vec_mid); + } else { + /* copy the edge length */ + VecAddf(vec_mid, eed->v1->co, eed->v2->co); + VecMulf(vec_mid, 0.5); + + /* SCALE 1 */ + VecSubf(vec, eed->v1->co, vec_mid); + VecMulf(vec, eed_len_act/eed_len); + VecAddf(eed->v1->co, vec, vec_mid); + + /* SCALE 2 */ + VecSubf(vec, eed->v2->co, vec_mid); + VecMulf(vec, eed_len_act/eed_len); + VecAddf(eed->v2->co, vec, vec_mid); } + change = 1; } - - if (change) - recalc_editnormals(); - - - break; } + + if (change) + recalc_editnormals(); + + break; + } + + if (change) { + DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA); + allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWBUTSEDIT, 0); - } else if(ese==NULL || ese->type == EDITFACE) { - EditFace *efa, *efa_act; - MTFace *tf, *tf_act = NULL; - MCol *mcol, *mcol_act = NULL; - - efa_act = EM_get_actFace(0); - - if (efa_act) { - ret= pupmenu( - "Copy Face Selected%t|" - "Active Material%x1|Active Image%x2|Active UV Coords%x3|" - "Active Mode%x4|Active Transp%x5|Active Vertex Colors%x6|%l|" - - "TexFace UVs from layer%x7|" - "TexFace Images from layer%x8|" - "TexFace All from layer%x9|" - "Vertex Colors from layer%x10"); - if (ret<1) return; - tf_act = CustomData_em_get(&em->fdata, efa_act->data, CD_MTFACE); - mcol_act = CustomData_em_get(&em->fdata, efa_act->data, CD_MCOL); - } else { - ret= pupmenu( - "Copy Face Selected%t|" - - /* Make sure these are always the same as above */ - "TexFace UVs from layer%x7|" - "TexFace Images from layer%x8|" - "TexFace All from layer%x9|" - "Vertex Colors from layer%x10"); - if (ret<1) return; + BIF_undo_push("Copy Edge Attribute"); + } +} + +void EM_mesh_copy_face(short type) +{ + EditMesh *em = G.editMesh; + short change=0; + + EditFace *efa, *efa_act; + MTFace *tf, *tf_act = NULL; + MCol *mcol, *mcol_act = NULL; + if (!em) return; + efa_act = EM_get_actFace(0); + + if (!efa_act) return; + + tf_act = CustomData_em_get(&em->fdata, efa_act->data, CD_MTFACE); + mcol_act = CustomData_em_get(&em->fdata, efa_act->data, CD_MCOL); + + switch (type) { + case 1: /* copy material */ + for(efa=em->faces.first; efa; efa=efa->next) { + if (efa->f & SELECT && efa->mat_nr != efa_act->mat_nr) { + efa->mat_nr = efa_act->mat_nr; + change = 1; + } } - - switch (ret) { - case 1: /* copy material */ - for(efa=em->faces.first; efa; efa=efa->next) { - if (efa->f & SELECT && efa->mat_nr != efa_act->mat_nr) { - efa->mat_nr = efa_act->mat_nr; - change = 1; + break; + case 2: /* copy image */ + if (!tf_act) { + error("mesh has no uv/image layers"); + return; + } + for(efa=em->faces.first; efa; efa=efa->next) { + if (efa->f & SELECT && efa != efa_act) { + tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); + if (tf_act->tpage) { + tf->tpage = tf_act->tpage; + tf->mode |= TF_TEX; + } else { + tf->tpage = NULL; + tf->mode &= ~TF_TEX; } + tf->tile= tf_act->tile; + change = 1; } - break; - case 2: /* copy image */ - if (!tf_act) { - error("mesh has no uv/image layers"); - return; + } + break; + + case 3: /* copy UV's */ + if (!tf_act) { + error("mesh has no uv/image layers"); + return; + } + for(efa=em->faces.first; efa; efa=efa->next) { + if (efa->f & SELECT && efa != efa_act) { + tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); + memcpy(tf->uv, tf_act->uv, sizeof(tf->uv)); + change = 1; } - for(efa=em->faces.first; efa; efa=efa->next) { - if (efa->f & SELECT && efa != efa_act) { - tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - if (tf_act->tpage) { - tf->tpage = tf_act->tpage; - tf->mode |= TF_TEX; - } else { - tf->tpage = NULL; - tf->mode &= ~TF_TEX; - } - tf->tile= tf_act->tile; - change = 1; - } + } + break; + case 4: /* mode's */ + if (!tf_act) { + error("mesh has no uv/image layers"); + return; + } + for(efa=em->faces.first; efa; efa=efa->next) { + if (efa->f & SELECT && efa != efa_act) { + tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); + tf->mode= tf_act->mode; + change = 1; } - break; - - case 3: /* copy UV's */ - if (!tf_act) { - error("mesh has no uv/image layers"); - return; + } + break; + case 5: /* copy transp's */ + if (!tf_act) { + error("mesh has no uv/image layers"); + return; + } + for(efa=em->faces.first; efa; efa=efa->next) { + if (efa->f & SELECT && efa != efa_act) { + tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); + tf->transp= tf_act->transp; + change = 1; } + } + break; + + case 6: /* copy vcols's */ + if (!mcol_act) { + error("mesh has no color layers"); + return; + } else { + /* guess the 4th color if needs be */ + float val =- 1; + + if (!efa_act->v4) { + /* guess the othe vale, we may need to use it + * + * Modifying the 4th value of the mcol is ok here since its not seen + * on a triangle + * */ + val = ((float)(mcol_act->r + (mcol_act+1)->r + (mcol_act+2)->r)) / 3; CLAMP(val, 0, 255); + (mcol_act+3)->r = (char)val; + + val = ((float)(mcol_act->g + (mcol_act+1)->g + (mcol_act+2)->g)) / 3; CLAMP(val, 0, 255); + (mcol_act+3)->g = (char)val; + + val = ((float)(mcol_act->b + (mcol_act+1)->b + (mcol_act+2)->b)) / 3; CLAMP(val, 0, 255); + (mcol_act+3)->b = (char)val; + } + + for(efa=em->faces.first; efa; efa=efa->next) { if (efa->f & SELECT && efa != efa_act) { - tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - memcpy(tf->uv, tf_act->uv, sizeof(tf->uv)); + /* TODO - make copy from tri to quad guess the 4th vert */ + mcol = CustomData_em_get(&em->fdata, efa->data, CD_MCOL); + memcpy(mcol, mcol_act, sizeof(MCol)*4); change = 1; } } - break; - case 4: /* mode's */ - if (!tf_act) { - error("mesh has no uv/image layers"); + } + break; + } + + if (change) { + DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA); + allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWBUTSEDIT, 0); + if (type==3) { + allqueue(REDRAWIMAGE, 0); + } + + BIF_undo_push("Copy Face Attribute"); + } +} + + +void EM_mesh_copy_face_layer(short type) +{ + EditMesh *em = G.editMesh; + short change=0; + + EditFace *efa; + MTFace *tf, *tf_from; + MCol *mcol, *mcol_from; + + if (!em) return; + + switch(type) { + case 7: + case 8: + case 9: + if (CustomData_number_of_layers(&em->fdata, CD_MTFACE)<2) { + error("mesh does not have multiple uv/image layers"); + return; + } else { + int layer_orig_idx, layer_idx; + + layer_idx = mesh_layers_menu(&em->fdata, CD_MTFACE); + if (layer_idx<0) return; + + /* warning, have not updated mesh pointers however this is not needed since we swicth back */ + layer_orig_idx = CustomData_get_active_layer(&em->fdata, CD_MTFACE); + if (layer_idx==layer_orig_idx) return; - } + + /* get the tfaces */ + CustomData_set_layer_active(&em->fdata, CD_MTFACE, (int)layer_idx); + /* store the tfaces in our temp */ for(efa=em->faces.first; efa; efa=efa->next) { - if (efa->f & SELECT && efa != efa_act) { - tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - tf->mode= tf_act->mode; - change = 1; - } + if (efa->f & SELECT) { + efa->tmp.p = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); + } } - break; - case 5: /* copy transp's */ - if (!tf_act) { - error("mesh has no uv/image layers"); + CustomData_set_layer_active(&em->fdata, CD_MTFACE, layer_orig_idx); + } + break; + + case 10: /* select vcol layers - make sure this stays in sync with above code */ + if (CustomData_number_of_layers(&em->fdata, CD_MCOL)<2) { + error("mesh does not have multiple color layers"); + return; + } else { + int layer_orig_idx, layer_idx; + + layer_idx = mesh_layers_menu(&em->fdata, CD_MCOL); + if (layer_idx<0) return; + + /* warning, have not updated mesh pointers however this is not needed since we swicth back */ + layer_orig_idx = CustomData_get_active_layer(&em->fdata, CD_MCOL); + if (layer_idx==layer_orig_idx) return; - } + + /* get the tfaces */ + CustomData_set_layer_active(&em->fdata, CD_MCOL, (int)layer_idx); + /* store the tfaces in our temp */ for(efa=em->faces.first; efa; efa=efa->next) { - if (efa->f & SELECT && efa != efa_act) { - tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - tf->transp= tf_act->transp; - change = 1; - } - } - break; - - case 6: /* copy vcols's */ - if (!mcol_act) { - error("mesh has no color layers"); - return; - } else { - /* guess the 4th color if needs be */ - float val =- 1; - - if (!efa_act->v4) { - /* guess the othe vale, we may need to use it - * - * Modifying the 4th value of the mcol is ok here since its not seen - * on a triangle - * */ - val = ((float)(mcol_act->r + (mcol_act+1)->r + (mcol_act+2)->r)) / 3; CLAMP(val, 0, 255); - (mcol_act+3)->r = (char)val; - - val = ((float)(mcol_act->g + (mcol_act+1)->g + (mcol_act+2)->g)) / 3; CLAMP(val, 0, 255); - (mcol_act+3)->g = (char)val; - - val = ((float)(mcol_act->b + (mcol_act+1)->b + (mcol_act+2)->b)) / 3; CLAMP(val, 0, 255); - (mcol_act+3)->b = (char)val; - } - - - for(efa=em->faces.first; efa; efa=efa->next) { - if (efa->f & SELECT && efa != efa_act) { - /* TODO - make copy from tri to quad guess the 4th vert */ - mcol = CustomData_em_get(&em->fdata, efa->data, CD_MCOL); - memcpy(mcol, mcol_act, sizeof(MCol)*4); - change = 1; - } - } - } - - break; - - /* Copy from layer - Warning! tf_act and mcol_act will be NULL here */ - case 7: - case 8: - case 9: - if (CustomData_number_of_layers(&em->fdata, CD_MTFACE)<2) { - error("mesh does not have multiple uv/image layers"); - return; - } else { - int layer_orig_idx, layer_idx; - - layer_idx = mesh_layers_menu(&em->fdata, CD_MTFACE); - if (layer_idx<0) return; - - /* warning, have not updated mesh pointers however this is not needed since we swicth back */ - layer_orig_idx = CustomData_get_active_layer(&em->fdata, CD_MTFACE); - if (layer_idx==layer_orig_idx) - return; - - /* get the tfaces */ - CustomData_set_layer_active(&em->fdata, CD_MTFACE, (int)layer_idx); - /* store the tfaces in our temp */ - for(efa=em->faces.first; efa; efa=efa->next) { - if (efa->f & SELECT) { - efa->tmp.p = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - } - } - CustomData_set_layer_active(&em->fdata, CD_MTFACE, layer_orig_idx); - } - break; - - case 10: /* select vcol layers - make sure this stays in sync with above code */ - if (CustomData_number_of_layers(&em->fdata, CD_MCOL)<2) { - error("mesh does not have multiple color layers"); - return; - } else { - int layer_orig_idx, layer_idx; - - layer_idx = mesh_layers_menu(&em->fdata, CD_MCOL); - if (layer_idx<0) return; - - /* warning, have not updated mesh pointers however this is not needed since we swicth back */ - layer_orig_idx = CustomData_get_active_layer(&em->fdata, CD_MCOL); - if (layer_idx==layer_orig_idx) - return; - - /* get the tfaces */ - CustomData_set_layer_active(&em->fdata, CD_MCOL, (int)layer_idx); - /* store the tfaces in our temp */ - for(efa=em->faces.first; efa; efa=efa->next) { - if (efa->f & SELECT) { - efa->tmp.p = CustomData_em_get(&em->fdata, efa->data, CD_MCOL); - } - } - CustomData_set_layer_active(&em->fdata, CD_MCOL, layer_orig_idx); - + if (efa->f & SELECT) { + efa->tmp.p = CustomData_em_get(&em->fdata, efa->data, CD_MCOL); + } } - break; + CustomData_set_layer_active(&em->fdata, CD_MCOL, layer_orig_idx); + } - - /* layer copy only - sanity checks done above */ - switch (ret) { - case 7: /* copy UV's only */ - for(efa=em->faces.first; efa; efa=efa->next) { - if (efa->f & SELECT) { - tf_act = (MTFace *)efa->tmp.p; /* not active but easier to use this way */ - tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - memcpy(tf->uv, tf_act->uv, sizeof(tf->uv)); - change = 1; - } + break; + } + + /* layer copy only - sanity checks done above */ + switch (type) { + case 7: /* copy UV's only */ + for(efa=em->faces.first; efa; efa=efa->next) { + if (efa->f & SELECT) { + tf_from = (MTFace *)efa->tmp.p; /* not active but easier to use this way */ + tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); + memcpy(tf->uv, tf_from->uv, sizeof(tf->uv)); + change = 1; } - break; - case 8: /* copy image settings only */ - for(efa=em->faces.first; efa; efa=efa->next) { - if (efa->f & SELECT) { - tf_act = (MTFace *)efa->tmp.p; /* not active but easier to use this way */ - tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - if (tf_act->tpage) { - tf->tpage = tf_act->tpage; - tf->mode |= TF_TEX; - } else { - tf->tpage = NULL; - tf->mode &= ~TF_TEX; - } - tf->tile= tf_act->tile; - change = 1; + } + break; + case 8: /* copy image settings only */ + for(efa=em->faces.first; efa; efa=efa->next) { + if (efa->f & SELECT) { + tf_from = (MTFace *)efa->tmp.p; /* not active but easier to use this way */ + tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); + if (tf_from->tpage) { + tf->tpage = tf_from->tpage; + tf->mode |= TF_TEX; + } else { + tf->tpage = NULL; + tf->mode &= ~TF_TEX; } + tf->tile= tf_from->tile; + change = 1; } - break; - case 9: /* copy all tface info */ - for(efa=em->faces.first; efa; efa=efa->next) { - if (efa->f & SELECT) { - tf_act = (MTFace *)efa->tmp.p; /* not active but easier to use this way */ - tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - memcpy(tf->uv, ((MTFace *)efa->tmp.p)->uv, sizeof(tf->uv)); - tf->tpage = tf_act->tpage; - tf->mode = tf_act->mode; - tf->transp = tf_act->transp; - change = 1; - } + } + break; + case 9: /* copy all tface info */ + for(efa=em->faces.first; efa; efa=efa->next) { + if (efa->f & SELECT) { + tf_from = (MTFace *)efa->tmp.p; /* not active but easier to use this way */ + tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); + memcpy(tf->uv, ((MTFace *)efa->tmp.p)->uv, sizeof(tf->uv)); + tf->tpage = tf_from->tpage; + tf->mode = tf_from->mode; + tf->transp = tf_from->transp; + change = 1; } - break; - case 10: - for(efa=em->faces.first; efa; efa=efa->next) { - if (efa->f & SELECT) { - mcol_act = (MCol *)efa->tmp.p; - mcol = CustomData_em_get(&em->fdata, efa->data, CD_MCOL); - memcpy(mcol, mcol_act, sizeof(MCol)*4); - change = 1; - } + } + break; + case 10: + for(efa=em->faces.first; efa; efa=efa->next) { + if (efa->f & SELECT) { + mcol_from = (MCol *)efa->tmp.p; + mcol = CustomData_em_get(&em->fdata, efa->data, CD_MCOL); + memcpy(mcol, mcol_from, sizeof(MCol)*4); + change = 1; } - break; } - + break; } - + if (change) { DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA); allqueue(REDRAWVIEW3D, 0); allqueue(REDRAWBUTSEDIT, 0); - if (ese==NULL || ese->type == EDITFACE) BIF_undo_push("Copy Face Attribute"); - else if ( ese->type == EDITEDGE) BIF_undo_push("Copy Edge Attribute"); - else if ( ese->type == EDITVERT) BIF_undo_push("Copy Vert Attribute"); - + BIF_undo_push("Copy Face Layer"); } +} + + +/* ctrl+c in mesh editmode */ +void mesh_copy_menu(void) +{ + EditMesh *em = G.editMesh; + EditSelection *ese; + int ret; + if (!em) return; + ese = em->selected.last; + + /* Faces can have a NULL ese, so dont return on a NULL ese here */ + + if(ese && ese->type == EDITVERT) { + /* EditVert *ev, *ev_act = (EditVert*)ese->data; + ret= pupmenu(""); */ + } else if(ese && ese->type == EDITEDGE) { + ret= pupmenu("Copy Active Edge to Selected%t|Crease%x1|Bevel Weight%x2|Length%x3"); + if (ret<1) return; + + EM_mesh_copy_edge(ret); + + } else if(ese==NULL || ese->type == EDITFACE) { + ret= pupmenu( + "Copy Face Selected%t|" + "Active Material%x1|Active Image%x2|Active UV Coords%x3|" + "Active Mode%x4|Active Transp%x5|Active Vertex Colors%x6|%l|" + + "TexFace UVs from layer%x7|" + "TexFace Images from layer%x8|" + "TexFace All from layer%x9|" + "Vertex Colors from layer%x10"); + if (ret<1) return; + + if (ret<=6) { + EM_mesh_copy_face(ret); + } else { + EM_mesh_copy_face_layer(ret); + } + } } diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c index cbf7691754d..fee967bcd9a 100644 --- a/source/blender/src/editobject.c +++ b/source/blender/src/editobject.c @@ -2760,7 +2760,7 @@ void special_editmenu(void) DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA); } else if(G.obedit->type==OB_ARMATURE) { - nr= pupmenu("Specials%t|Subdivide %x1|Subdivide Multi%x2|Flip Left-Right Names%x3|%l|AutoName Left-Right%x4|AutoName Front-Back%x5|AutoName Top-Bottom%x6|%l|Lock%x7|Unlock%x8"); + nr= pupmenu("Specials%t|Subdivide %x1|Subdivide Multi%x2|Switch Direction%x7|Flip Left-Right Names%x3|%l|AutoName Left-Right%x4|AutoName Front-Back%x5|AutoName Top-Bottom%x6"); if(nr==1) subdivide_armature(1); if(nr==2) { @@ -2773,10 +2773,8 @@ void special_editmenu(void) else if(ELEM3(nr, 4, 5, 6)) { armature_autoside_names(nr-4); } - else if(nr==7) - set_locks_armature_bones(1); - else if(nr==8) - set_locks_armature_bones(0); + else if(nr == 7) + switch_direction_armature(); } else if(G.obedit->type==OB_LATTICE) { static float weight= 1.0f; diff --git a/source/blender/src/poselib.c b/source/blender/src/poselib.c index fb2bfe5b605..6aeef7c75c2 100644 --- a/source/blender/src/poselib.c +++ b/source/blender/src/poselib.c @@ -312,7 +312,7 @@ void poselib_add_current_pose (Object *ob, int val) /* mode - add new or replace existing */ if (val == 0) { if ((ob->poselib) && (ob->poselib->markers.first)) { - val= pupmenu("PoseLib Add Current Pose%t|Add New%x1|Replace Existing%x2"); + val= pupmenu("PoseLib Add Current Pose%t|Add New%x1|Add New (Current Frame)%x3|Replace Existing%x2"); if (val <= 0) return; } else @@ -347,7 +347,10 @@ void poselib_add_current_pose (Object *ob, int val) act= poselib_validate(ob); /* get frame */ - frame= poselib_get_free_index(act); + if (val == 3) + frame= CFRA; + else /* if (val == 1) */ + frame= poselib_get_free_index(act); /* add pose to poselib - replaces any existing pose there */ for (marker= act->markers.first; marker; marker= marker->next) { diff --git a/source/blender/src/transform_conversions.c b/source/blender/src/transform_conversions.c index 8f83434e528..9f2f58d0cdb 100644 --- a/source/blender/src/transform_conversions.c +++ b/source/blender/src/transform_conversions.c @@ -913,8 +913,8 @@ static void createTransPose(TransInfo *t, Object *ob) if (arm==NULL || ob->pose==NULL) return; if (arm->flag & ARM_RESTPOS) { - if(t->mode!=TFM_BONESIZE) { - notice ("Pose edit not possible while Rest Position is enabled"); + if(ELEM(t->mode, TFM_DUMMY, TFM_BONESIZE)==0) { + notice("Pose edit not possible while Rest Position is enabled"); return; } } diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index f44318120e8..a6337403cd1 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -1939,7 +1939,17 @@ void BL_ConvertBlenderObjects(struct Main* maggie, float* fl = (float*) blenderobject->parentinv; MT_Transform parinvtrans(fl); parentinversenode->SetLocalPosition(parinvtrans.getOrigin()); - parentinversenode->SetLocalOrientation(parinvtrans.getBasis()); + // problem here: the parent inverse transform combines scaling and rotation + // in the basis but the scenegraph needs separate rotation and scaling. + // This is not important for OpenGL (it uses 4x4 matrix) but it is important + // for the physic engine that needs a separate scaling + //parentinversenode->SetLocalOrientation(parinvtrans.getBasis()); + + // Extract the rotation and the scaling from the basis + MT_Matrix3x3 inverseOrientation(parinvtrans.getRotation()); + parentinversenode->SetLocalOrientation(inverseOrientation); + MT_Matrix3x3 scale(inverseOrientation.transposed()*parinvtrans.getBasis()); + parentinversenode->SetLocalScale(MT_Vector3(scale[0][0], scale[1][1], scale[2][2])); parentinversenode->AddChild(gameobj->GetSGNode()); } diff --git a/source/gameengine/Ketsji/CMakeLists.txt b/source/gameengine/Ketsji/CMakeLists.txt index 3b907d8d530..be009d94701 100644 --- a/source/gameengine/Ketsji/CMakeLists.txt +++ b/source/gameengine/Ketsji/CMakeLists.txt @@ -25,6 +25,17 @@ # ***** END GPL LICENSE BLOCK ***** FILE(GLOB SRC *.cpp) +SET(SRC + ${SRC} + ../../../source/blender/python/api2_2x/Mathutils.c + ../../../source/blender/python/api2_2x/constant.c + ../../../source/blender/python/api2_2x/euler.c + ../../../source/blender/python/api2_2x/gen_utils.c + ../../../source/blender/python/api2_2x/matrix.c + ../../../source/blender/python/api2_2x/point.c + ../../../source/blender/python/api2_2x/quat.c + ../../../source/blender/python/api2_2x/vector.c +) SET(INC . @@ -39,7 +50,8 @@ SET(INC ../../../intern/moto/include ../../../source/gameengine/Ketsji ../../../source/blender/blenlib - ../../../source/blender/blenkernel + ../../../source/blender/blenkernel + ../../../source/blender/python/api2_2x ../../../source/blender ../../../source/blender/include ../../../source/blender/makesdna diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index 661bf17ef23..989cdabd491 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -1491,7 +1491,7 @@ PyObject* KX_GameObject::PyAlignAxisToVect(PyObject* self, if (PyVecTo(pyvect, vect)) { if (fac<=0.0) Py_RETURN_NONE; // Nothing to do. - if (fac< 1.0) fac= 1.0; + if (fac> 1.0) fac= 1.0; AlignAxisToVect(vect,axis,fac); NodeUpdateGS(0.f,true); diff --git a/source/gameengine/Ketsji/KX_RadarSensor.cpp b/source/gameengine/Ketsji/KX_RadarSensor.cpp index de4979ac4c9..d371626b597 100644 --- a/source/gameengine/Ketsji/KX_RadarSensor.cpp +++ b/source/gameengine/Ketsji/KX_RadarSensor.cpp @@ -147,23 +147,23 @@ void KX_RadarSensor::SynchronizeTransform() }; case 3: // -X Axis { - MT_Quaternion rotquatje(MT_Vector3(0,0,1),MT_radians(90)); + MT_Quaternion rotquatje(MT_Vector3(0,0,1),MT_radians(-90)); trans.rotate(rotquatje); - trans.translate(MT_Vector3 (0, m_coneheight/2.0 ,0)); + trans.translate(MT_Vector3 (0, -m_coneheight/2.0 ,0)); break; }; case 4: // -Y Axis { - MT_Quaternion rotquatje(MT_Vector3(1,0,0),MT_radians(-180)); - trans.rotate(rotquatje); - trans.translate(MT_Vector3 (0, m_coneheight/2.0 ,0)); + //MT_Quaternion rotquatje(MT_Vector3(1,0,0),MT_radians(-180)); + //trans.rotate(rotquatje); + trans.translate(MT_Vector3 (0, -m_coneheight/2.0 ,0)); break; }; case 5: // -Z Axis { - MT_Quaternion rotquatje(MT_Vector3(1,0,0),MT_radians(-90)); + MT_Quaternion rotquatje(MT_Vector3(1,0,0),MT_radians(90)); trans.rotate(rotquatje); - trans.translate(MT_Vector3 (0, m_coneheight/2.0 ,0)); + trans.translate(MT_Vector3 (0, -m_coneheight/2.0 ,0)); break; }; default: diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp index 08f40424323..dfbcf115fd7 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp @@ -956,13 +956,16 @@ void CcdPhysicsEnvironment::CallbackTriggers() if (m_triggerCallbacks[PHY_OBJECT_RESPONSE] || (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawContactPoints))) { //walk over all overlapping pairs, and if one of the involved bodies is registered for trigger callback, perform callback - int numManifolds = m_dynamicsWorld->getDispatcher()->getNumManifolds(); + btDispatcher* dispatcher = m_dynamicsWorld->getDispatcher(); + int numManifolds = dispatcher->getNumManifolds(); for (int i=0;i<numManifolds;i++) { - btPersistentManifold* manifold = m_dynamicsWorld->getDispatcher()->getManifoldByIndexInternal(i); + btPersistentManifold* manifold = dispatcher->getManifoldByIndexInternal(i); int numContacts = manifold->getNumContacts(); if (numContacts) { + btRigidBody* rb0 = static_cast<btRigidBody*>(manifold->getBody0()); + btRigidBody* rb1 = static_cast<btRigidBody*>(manifold->getBody1()); if (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawContactPoints)) { for (int j=0;j<numContacts;j++) @@ -973,8 +976,8 @@ void CcdPhysicsEnvironment::CallbackTriggers() m_debugDrawer->drawContactPoint(cp.m_positionWorldOnB,cp.m_normalWorldOnB,cp.getDistance(),cp.getLifeTime(),color); } } - btRigidBody* obj0 = static_cast<btRigidBody* >(manifold->getBody0()); - btRigidBody* obj1 = static_cast<btRigidBody* >(manifold->getBody1()); + btRigidBody* obj0 = rb0; + btRigidBody* obj1 = rb1; //m_internalOwner is set in 'addPhysicsController' CcdPhysicsController* ctrl0 = static_cast<CcdPhysicsController*>(obj0->getUserPointer()); @@ -991,6 +994,15 @@ void CcdPhysicsEnvironment::CallbackTriggers() m_triggerCallbacks[PHY_OBJECT_RESPONSE](m_triggerCallbacksUserPtrs[PHY_OBJECT_RESPONSE], ctrl0,ctrl1,0); } + // Bullet does not refresh the manifold contact point for object without contact response + // may need to remove this when a newer Bullet version is integrated + if (!dispatcher->needsResponse(rb0, rb1)) + { + // Refresh algorithm fails sometimes when there is penetration + // (usuall the case with ghost and sensor objects) + // Let's just clear the manifold, in any case, it is recomputed on each frame. + manifold->clearManifold(); //refreshContactPoints(rb0->getCenterOfMassTransform(),rb1->getCenterOfMassTransform()); + } } } diff --git a/tools/btools.py b/tools/btools.py index ad4cf71c3e8..a25120f6c4b 100755 --- a/tools/btools.py +++ b/tools/btools.py @@ -332,6 +332,8 @@ def read_opts(cfg, args): ('BF_X264_CONFIG', 'configuration flags for x264', ''), ('BF_XVIDCORE_CONFIG', 'configuration flags for xvidcore', ''), + + ('BF_CONFIG', 'SCons python config file used to set default options', 'user_config.py'), ) # end of opts.AddOptions() |