merge with trunk/2.5 at r25907
authorJoseph Eagar <joeedh@gmail.com>
Wed, 13 Jan 2010 07:26:11 +0000 (07:26 +0000)
committerJoseph Eagar <joeedh@gmail.com>
Wed, 13 Jan 2010 07:26:11 +0000 (07:26 +0000)
103 files changed:
1  2 
intern/ghost/intern/GHOST_SystemCocoa.h
intern/ghost/intern/GHOST_SystemCocoa.mm
intern/ghost/intern/GHOST_WindowCocoa.h
intern/ghost/intern/GHOST_WindowCocoa.mm
projectfiles_vc9/blender/editors/ED_editors.vcproj
source/blender/blenkernel/BKE_DerivedMesh.h
source/blender/blenkernel/BKE_key.h
source/blender/blenkernel/BKE_utildefines.h
source/blender/blenkernel/intern/DerivedMesh.c
source/blender/blenkernel/intern/anim.c
source/blender/blenkernel/intern/armature.c
source/blender/blenkernel/intern/cdderivedmesh.c
source/blender/blenkernel/intern/constraint.c
source/blender/blenkernel/intern/editderivedbmesh.c
source/blender/blenkernel/intern/key.c
source/blender/blenkernel/intern/library.c
source/blender/blenkernel/intern/mesh.c
source/blender/blenkernel/intern/modifier.c
source/blender/blenkernel/intern/node.c
source/blender/blenkernel/intern/object.c
source/blender/blenkernel/intern/particle.c
source/blender/blenkernel/intern/particle_system.c
source/blender/blenkernel/intern/softbody.c
source/blender/blenkernel/intern/subsurf_ccg.c
source/blender/blenlib/intern/math_vector_inline.c
source/blender/blenlib/intern/pbvh.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/editors/CMakeLists.txt
source/blender/editors/armature/editarmature.c
source/blender/editors/armature/poseobject.c
source/blender/editors/curve/editcurve.c
source/blender/editors/curve/editfont.c
source/blender/editors/include/ED_view3d.h
source/blender/editors/include/UI_resources.h
source/blender/editors/interface/interface_handlers.c
source/blender/editors/interface/resources.c
source/blender/editors/mesh/editmesh_add.c
source/blender/editors/mesh/editmesh_loop.c
source/blender/editors/mesh/editmesh_mods.c
source/blender/editors/mesh/loopcut.c
source/blender/editors/mesh/mesh_intern.h
source/blender/editors/mesh/mesh_ops.c
source/blender/editors/mesh/meshtools.c
source/blender/editors/object/SConscript
source/blender/editors/object/object_add.c
source/blender/editors/object/object_edit.c
source/blender/editors/object/object_relations.c
source/blender/editors/physics/particle_edit.c
source/blender/editors/screen/Makefile
source/blender/editors/screen/screen_ops.c
source/blender/editors/sculpt_paint/paint_image.c
source/blender/editors/sculpt_paint/paint_utils.c
source/blender/editors/sculpt_paint/sculpt.c
source/blender/editors/space_image/image_header.c
source/blender/editors/space_image/space_image.c
source/blender/editors/space_view3d/drawarmature.c
source/blender/editors/space_view3d/drawobject.c
source/blender/editors/space_view3d/view3d_buttons.c
source/blender/editors/space_view3d/view3d_draw.c
source/blender/editors/space_view3d/view3d_edit.c
source/blender/editors/space_view3d/view3d_header.c
source/blender/editors/space_view3d/view3d_select.c
source/blender/editors/space_view3d/view3d_snap.c
source/blender/editors/space_view3d/view3d_view.c
source/blender/editors/transform/transform.c
source/blender/editors/transform/transform.h
source/blender/editors/transform/transform_conversions.c
source/blender/editors/transform/transform_generics.c
source/blender/editors/transform/transform_manipulator.c
source/blender/editors/transform/transform_ops.c
source/blender/editors/transform/transform_orientations.c
source/blender/makesdna/DNA_mesh_types.h
source/blender/makesdna/DNA_object_types.h
source/blender/makesdna/DNA_userdef_types.h
source/blender/makesrna/intern/Makefile
source/blender/makesrna/intern/rna_image_api.c
source/blender/makesrna/intern/rna_main_api.c
source/blender/makesrna/intern/rna_mesh.c
source/blender/makesrna/intern/rna_mesh_api.c
source/blender/makesrna/intern/rna_object.c
source/blender/makesrna/intern/rna_scene.c
source/blender/makesrna/intern/rna_userdef.c
source/blender/makesrna/intern/rna_wm_api.c
source/blender/python/generic/Geometry.c
source/blender/python/generic/bpy_internal_import.c
source/blender/python/generic/euler.c
source/blender/python/generic/matrix.c
source/blender/python/generic/quat.c
source/blender/python/generic/vector.c
source/blender/python/intern/bpy_interface.c
source/blender/python/intern/bpy_operator.c
source/blender/python/intern/bpy_operator_wrap.c
source/blender/python/intern/bpy_operator_wrap.h
source/blender/render/intern/source/convertblender.c
source/blender/render/intern/source/shadeoutput.c
source/blender/windowmanager/intern/wm_init_exit.c
source/blender/windowmanager/intern/wm_operators.c
source/creator/creator.c
source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
source/gameengine/Converter/BL_BlenderDataConversion.cpp
source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
tools/btools.py

index cacacd368bb0f477ceec53c2b0a825719e66d569,735efcda3958df6c74a0c41128d09e237305e670..c2d3b56ce59d6f5030c04587fd53d9e534a074bc
 -/**
 - * $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) 2001-2002 by NaN Holding BV.
 - * All rights reserved.
 - *
 - * The Original Code is: all of this file.
 - *
 - * Contributor(s):    Maarten Gribnau 05/2001
 - *                                    Damien Plisson 09/2009
 - *
 - * ***** END GPL LICENSE BLOCK *****
 - */
 -
 -#import <Cocoa/Cocoa.h>
 -
 -#include <sys/time.h>
 -#include <sys/types.h>
 -#include <sys/sysctl.h>
 -
 -#include "GHOST_SystemCocoa.h"
 -
 -#include "GHOST_DisplayManagerCocoa.h"
 -#include "GHOST_EventKey.h"
 -#include "GHOST_EventButton.h"
 -#include "GHOST_EventCursor.h"
 -#include "GHOST_EventWheel.h"
 -#include "GHOST_EventNDOF.h"
 +/**\r
 + * $Id: GHOST_SystemCocoa.mm 23854 2009-10-15 08:27:31Z damien78 $\r
 + * ***** BEGIN GPL LICENSE BLOCK *****\r
 + *\r
 + * This program is free software; you can redistribute it and/or\r
 + * modify it under the terms of the GNU General Public License\r
 + * as published by the Free Software Foundation; either version 2\r
 + * of the License, or (at your option) any later version.\r
 + *\r
 + * This program is distributed in the hope that it will be useful,\r
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
 + * GNU General Public License for more details.\r
 + *\r
 + * You should have received a copy of the GNU General Public License\r
 + * along with this program; if not, write to the Free Software Foundation,\r
 + * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.\r
 + *\r
 + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.\r
 + * All rights reserved.\r
 + *\r
 + * The Original Code is: all of this file.\r
 + *\r
 + * Contributor(s):    Maarten Gribnau 05/2001\r
 + *                                    Damien Plisson 09/2009\r
 + *\r
 + * ***** END GPL LICENSE BLOCK *****\r
 + */\r
 +\r
 +#import <Cocoa/Cocoa.h>\r
 +\r
 +#include <sys/time.h>\r
 +#include <sys/types.h>\r
 +#include <sys/sysctl.h>\r
 +\r
 +#include "GHOST_SystemCocoa.h"\r
 +\r
 +#include "GHOST_DisplayManagerCocoa.h"\r
 +#include "GHOST_EventKey.h"\r
 +#include "GHOST_EventButton.h"\r
 +#include "GHOST_EventCursor.h"\r
 +#include "GHOST_EventWheel.h"\r
 +#include "GHOST_EventNDOF.h"\r
+ #include "GHOST_EventTrackpad.h"
  #include "GHOST_EventDragnDrop.h"
 -
 -#include "GHOST_TimerManager.h"
 -#include "GHOST_TimerTask.h"
 -#include "GHOST_WindowManager.h"
 -#include "GHOST_WindowCocoa.h"
 -#include "GHOST_NDOFManager.h"
 -#include "AssertMacros.h"
 -
 -#pragma mark KeyMap, mouse converters
 -
 -
 -/* Keycodes from Carbon include file */
 -/*  
 - *  Summary:
 - *    Virtual keycodes
 - *  
 - *  Discussion:
 - *    These constants are the virtual keycodes defined originally in
 - *    Inside Mac Volume V, pg. V-191. They identify physical keys on a
 - *    keyboard. Those constants with "ANSI" in the name are labeled
 - *    according to the key position on an ANSI-standard US keyboard.
 - *    For example, kVK_ANSI_A indicates the virtual keycode for the key
 - *    with the letter 'A' in the US keyboard layout. Other keyboard
 - *    layouts may have the 'A' key label on a different physical key;
 - *    in this case, pressing 'A' will generate a different virtual
 - *    keycode.
 - */
 -enum {
 -      kVK_ANSI_A                    = 0x00,
 -      kVK_ANSI_S                    = 0x01,
 -      kVK_ANSI_D                    = 0x02,
 -      kVK_ANSI_F                    = 0x03,
 -      kVK_ANSI_H                    = 0x04,
 -      kVK_ANSI_G                    = 0x05,
 -      kVK_ANSI_Z                    = 0x06,
 -      kVK_ANSI_X                    = 0x07,
 -      kVK_ANSI_C                    = 0x08,
 -      kVK_ANSI_V                    = 0x09,
 -      kVK_ANSI_B                    = 0x0B,
 -      kVK_ANSI_Q                    = 0x0C,
 -      kVK_ANSI_W                    = 0x0D,
 -      kVK_ANSI_E                    = 0x0E,
 -      kVK_ANSI_R                    = 0x0F,
 -      kVK_ANSI_Y                    = 0x10,
 -      kVK_ANSI_T                    = 0x11,
 -      kVK_ANSI_1                    = 0x12,
 -      kVK_ANSI_2                    = 0x13,
 -      kVK_ANSI_3                    = 0x14,
 -      kVK_ANSI_4                    = 0x15,
 -      kVK_ANSI_6                    = 0x16,
 -      kVK_ANSI_5                    = 0x17,
 -      kVK_ANSI_Equal                = 0x18,
 -      kVK_ANSI_9                    = 0x19,
 -      kVK_ANSI_7                    = 0x1A,
 -      kVK_ANSI_Minus                = 0x1B,
 -      kVK_ANSI_8                    = 0x1C,
 -      kVK_ANSI_0                    = 0x1D,
 -      kVK_ANSI_RightBracket         = 0x1E,
 -      kVK_ANSI_O                    = 0x1F,
 -      kVK_ANSI_U                    = 0x20,
 -      kVK_ANSI_LeftBracket          = 0x21,
 -      kVK_ANSI_I                    = 0x22,
 -      kVK_ANSI_P                    = 0x23,
 -      kVK_ANSI_L                    = 0x25,
 -      kVK_ANSI_J                    = 0x26,
 -      kVK_ANSI_Quote                = 0x27,
 -      kVK_ANSI_K                    = 0x28,
 -      kVK_ANSI_Semicolon            = 0x29,
 -      kVK_ANSI_Backslash            = 0x2A,
 -      kVK_ANSI_Comma                = 0x2B,
 -      kVK_ANSI_Slash                = 0x2C,
 -      kVK_ANSI_N                    = 0x2D,
 -      kVK_ANSI_M                    = 0x2E,
 -      kVK_ANSI_Period               = 0x2F,
 -      kVK_ANSI_Grave                = 0x32,
 -      kVK_ANSI_KeypadDecimal        = 0x41,
 -      kVK_ANSI_KeypadMultiply       = 0x43,
 -      kVK_ANSI_KeypadPlus           = 0x45,
 -      kVK_ANSI_KeypadClear          = 0x47,
 -      kVK_ANSI_KeypadDivide         = 0x4B,
 -      kVK_ANSI_KeypadEnter          = 0x4C,
 -      kVK_ANSI_KeypadMinus          = 0x4E,
 -      kVK_ANSI_KeypadEquals         = 0x51,
 -      kVK_ANSI_Keypad0              = 0x52,
 -      kVK_ANSI_Keypad1              = 0x53,
 -      kVK_ANSI_Keypad2              = 0x54,
 -      kVK_ANSI_Keypad3              = 0x55,
 -      kVK_ANSI_Keypad4              = 0x56,
 -      kVK_ANSI_Keypad5              = 0x57,
 -      kVK_ANSI_Keypad6              = 0x58,
 -      kVK_ANSI_Keypad7              = 0x59,
 -      kVK_ANSI_Keypad8              = 0x5B,
 -      kVK_ANSI_Keypad9              = 0x5C
 -};
 -
 -/* keycodes for keys that are independent of keyboard layout*/
 -enum {
 -      kVK_Return                    = 0x24,
 -      kVK_Tab                       = 0x30,
 -      kVK_Space                     = 0x31,
 -      kVK_Delete                    = 0x33,
 -      kVK_Escape                    = 0x35,
 -      kVK_Command                   = 0x37,
 -      kVK_Shift                     = 0x38,
 -      kVK_CapsLock                  = 0x39,
 -      kVK_Option                    = 0x3A,
 -      kVK_Control                   = 0x3B,
 -      kVK_RightShift                = 0x3C,
 -      kVK_RightOption               = 0x3D,
 -      kVK_RightControl              = 0x3E,
 -      kVK_Function                  = 0x3F,
 -      kVK_F17                       = 0x40,
 -      kVK_VolumeUp                  = 0x48,
 -      kVK_VolumeDown                = 0x49,
 -      kVK_Mute                      = 0x4A,
 -      kVK_F18                       = 0x4F,
 -      kVK_F19                       = 0x50,
 -      kVK_F20                       = 0x5A,
 -      kVK_F5                        = 0x60,
 -      kVK_F6                        = 0x61,
 -      kVK_F7                        = 0x62,
 -      kVK_F3                        = 0x63,
 -      kVK_F8                        = 0x64,
 -      kVK_F9                        = 0x65,
 -      kVK_F11                       = 0x67,
 -      kVK_F13                       = 0x69,
 -      kVK_F16                       = 0x6A,
 -      kVK_F14                       = 0x6B,
 -      kVK_F10                       = 0x6D,
 -      kVK_F12                       = 0x6F,
 -      kVK_F15                       = 0x71,
 -      kVK_Help                      = 0x72,
 -      kVK_Home                      = 0x73,
 -      kVK_PageUp                    = 0x74,
 -      kVK_ForwardDelete             = 0x75,
 -      kVK_F4                        = 0x76,
 -      kVK_End                       = 0x77,
 -      kVK_F2                        = 0x78,
 -      kVK_PageDown                  = 0x79,
 -      kVK_F1                        = 0x7A,
 -      kVK_LeftArrow                 = 0x7B,
 -      kVK_RightArrow                = 0x7C,
 -      kVK_DownArrow                 = 0x7D,
 -      kVK_UpArrow                   = 0x7E
 -};
 -
 -/* ISO keyboards only*/
 -enum {
 -      kVK_ISO_Section               = 0x0A
 -};
 -
 -/* JIS keyboards only*/
 -enum {
 -      kVK_JIS_Yen                   = 0x5D,
 -      kVK_JIS_Underscore            = 0x5E,
 -      kVK_JIS_KeypadComma           = 0x5F,
 -      kVK_JIS_Eisu                  = 0x66,
 -      kVK_JIS_Kana                  = 0x68
 -};
 -
 -
 -static GHOST_TButtonMask convertButton(int button)
 -{
 -      switch (button) {
 -              case 0:
 -                      return GHOST_kButtonMaskLeft;
 -              case 1:
 -                      return GHOST_kButtonMaskRight;
 -              case 2:
 -                      return GHOST_kButtonMaskMiddle;
 -              case 3:
 -                      return GHOST_kButtonMaskButton4;
 -              case 4:
 -                      return GHOST_kButtonMaskButton5;
 -              default:
 -                      return GHOST_kButtonMaskLeft;
 -      }
 -}
 -
 -/**
 - * Converts Mac rawkey codes (same for Cocoa & Carbon)
 - * into GHOST key codes
 - * @param rawCode The raw physical key code
 - * @param recvChar the character ignoring modifiers (except for shift)
 - * @return Ghost key code
 - */
 -static GHOST_TKey convertKey(int rawCode, unichar recvChar) 
 -{     
 -      
 -      //printf("\nrecvchar %c 0x%x",recvChar,recvChar);
 -      switch (rawCode) {
 -              /*Physical keycodes not used due to map changes in int'l keyboards
 -              case kVK_ANSI_A:        return GHOST_kKeyA;
 -              case kVK_ANSI_B:        return GHOST_kKeyB;
 -              case kVK_ANSI_C:        return GHOST_kKeyC;
 -              case kVK_ANSI_D:        return GHOST_kKeyD;
 -              case kVK_ANSI_E:        return GHOST_kKeyE;
 -              case kVK_ANSI_F:        return GHOST_kKeyF;
 -              case kVK_ANSI_G:        return GHOST_kKeyG;
 -              case kVK_ANSI_H:        return GHOST_kKeyH;
 -              case kVK_ANSI_I:        return GHOST_kKeyI;
 -              case kVK_ANSI_J:        return GHOST_kKeyJ;
 -              case kVK_ANSI_K:        return GHOST_kKeyK;
 -              case kVK_ANSI_L:        return GHOST_kKeyL;
 -              case kVK_ANSI_M:        return GHOST_kKeyM;
 -              case kVK_ANSI_N:        return GHOST_kKeyN;
 -              case kVK_ANSI_O:        return GHOST_kKeyO;
 -              case kVK_ANSI_P:        return GHOST_kKeyP;
 -              case kVK_ANSI_Q:        return GHOST_kKeyQ;
 -              case kVK_ANSI_R:        return GHOST_kKeyR;
 -              case kVK_ANSI_S:        return GHOST_kKeyS;
 -              case kVK_ANSI_T:        return GHOST_kKeyT;
 -              case kVK_ANSI_U:        return GHOST_kKeyU;
 -              case kVK_ANSI_V:        return GHOST_kKeyV;
 -              case kVK_ANSI_W:        return GHOST_kKeyW;
 -              case kVK_ANSI_X:        return GHOST_kKeyX;
 -              case kVK_ANSI_Y:        return GHOST_kKeyY;
 -              case kVK_ANSI_Z:        return GHOST_kKeyZ;*/
 -              
 -              /* Numbers keys mapped to handle some int'l keyboard (e.g. French)*/
 -              case kVK_ISO_Section: return    GHOST_kKeyUnknown;
 -              case kVK_ANSI_1:        return GHOST_kKey1;
 -              case kVK_ANSI_2:        return GHOST_kKey2;
 -              case kVK_ANSI_3:        return GHOST_kKey3;
 -              case kVK_ANSI_4:        return GHOST_kKey4;
 -              case kVK_ANSI_5:        return GHOST_kKey5;
 -              case kVK_ANSI_6:        return GHOST_kKey6;
 -              case kVK_ANSI_7:        return GHOST_kKey7;
 -              case kVK_ANSI_8:        return GHOST_kKey8;
 -              case kVK_ANSI_9:        return GHOST_kKey9;
 -              case kVK_ANSI_0:        return GHOST_kKey0;
 -      
 -              case kVK_ANSI_Keypad0:                  return GHOST_kKeyNumpad0;
 -              case kVK_ANSI_Keypad1:                  return GHOST_kKeyNumpad1;
 -              case kVK_ANSI_Keypad2:                  return GHOST_kKeyNumpad2;
 -              case kVK_ANSI_Keypad3:                  return GHOST_kKeyNumpad3;
 -              case kVK_ANSI_Keypad4:                  return GHOST_kKeyNumpad4;
 -              case kVK_ANSI_Keypad5:                  return GHOST_kKeyNumpad5;
 -              case kVK_ANSI_Keypad6:                  return GHOST_kKeyNumpad6;
 -              case kVK_ANSI_Keypad7:                  return GHOST_kKeyNumpad7;
 -              case kVK_ANSI_Keypad8:                  return GHOST_kKeyNumpad8;
 -              case kVK_ANSI_Keypad9:                  return GHOST_kKeyNumpad9;
 -              case kVK_ANSI_KeypadDecimal:    return GHOST_kKeyNumpadPeriod;
 -              case kVK_ANSI_KeypadEnter:              return GHOST_kKeyNumpadEnter;
 -              case kVK_ANSI_KeypadPlus:               return GHOST_kKeyNumpadPlus;
 -              case kVK_ANSI_KeypadMinus:              return GHOST_kKeyNumpadMinus;
 -              case kVK_ANSI_KeypadMultiply:   return GHOST_kKeyNumpadAsterisk;
 -              case kVK_ANSI_KeypadDivide:     return GHOST_kKeyNumpadSlash;
 -              case kVK_ANSI_KeypadClear:              return GHOST_kKeyUnknown;
 -
 -              case kVK_F1:                            return GHOST_kKeyF1;
 -              case kVK_F2:                            return GHOST_kKeyF2;
 -              case kVK_F3:                            return GHOST_kKeyF3;
 -              case kVK_F4:                            return GHOST_kKeyF4;
 -              case kVK_F5:                            return GHOST_kKeyF5;
 -              case kVK_F6:                            return GHOST_kKeyF6;
 -              case kVK_F7:                            return GHOST_kKeyF7;
 -              case kVK_F8:                            return GHOST_kKeyF8;
 -              case kVK_F9:                            return GHOST_kKeyF9;
 -              case kVK_F10:                           return GHOST_kKeyF10;
 -              case kVK_F11:                           return GHOST_kKeyF11;
 -              case kVK_F12:                           return GHOST_kKeyF12;
 -              case kVK_F13:                           return GHOST_kKeyF13;
 -              case kVK_F14:                           return GHOST_kKeyF14;
 -              case kVK_F15:                           return GHOST_kKeyF15;
 -              case kVK_F16:                           return GHOST_kKeyF16;
 -              case kVK_F17:                           return GHOST_kKeyF17;
 -              case kVK_F18:                           return GHOST_kKeyF18;
 -              case kVK_F19:                           return GHOST_kKeyF19;
 -              case kVK_F20:                           return GHOST_kKeyF20;
 -                      
 -              case kVK_UpArrow:                       return GHOST_kKeyUpArrow;
 -              case kVK_DownArrow:                     return GHOST_kKeyDownArrow;
 -              case kVK_LeftArrow:                     return GHOST_kKeyLeftArrow;
 -              case kVK_RightArrow:            return GHOST_kKeyRightArrow;
 -                      
 -              case kVK_Return:                        return GHOST_kKeyEnter;
 -              case kVK_Delete:                        return GHOST_kKeyBackSpace;
 -              case kVK_ForwardDelete:         return GHOST_kKeyDelete;
 -              case kVK_Escape:                        return GHOST_kKeyEsc;
 -              case kVK_Tab:                           return GHOST_kKeyTab;
 -              case kVK_Space:                         return GHOST_kKeySpace;
 -                      
 -              case kVK_Home:                          return GHOST_kKeyHome;
 -              case kVK_End:                           return GHOST_kKeyEnd;
 -              case kVK_PageUp:                        return GHOST_kKeyUpPage;
 -              case kVK_PageDown:                      return GHOST_kKeyDownPage;
 -                      
 -              /*case kVK_ANSI_Minus:          return GHOST_kKeyMinus;
 -              case kVK_ANSI_Equal:            return GHOST_kKeyEqual;
 -              case kVK_ANSI_Comma:            return GHOST_kKeyComma;
 -              case kVK_ANSI_Period:           return GHOST_kKeyPeriod;
 -              case kVK_ANSI_Slash:            return GHOST_kKeySlash;
 -              case kVK_ANSI_Semicolon:        return GHOST_kKeySemicolon;
 -              case kVK_ANSI_Quote:            return GHOST_kKeyQuote;
 -              case kVK_ANSI_Backslash:        return GHOST_kKeyBackslash;
 -              case kVK_ANSI_LeftBracket:      return GHOST_kKeyLeftBracket;
 -              case kVK_ANSI_RightBracket:     return GHOST_kKeyRightBracket;
 -              case kVK_ANSI_Grave:            return GHOST_kKeyAccentGrave;*/
 -                      
 -              case kVK_VolumeUp:
 -              case kVK_VolumeDown:
 -              case kVK_Mute:
 -                      return GHOST_kKeyUnknown;
 -                      
 -              default:
 -                      /*Then detect on character value for "remappable" keys in int'l keyboards*/
 -                      if ((recvChar >= 'A') && (recvChar <= 'Z')) {
 -                              return (GHOST_TKey) (recvChar - 'A' + GHOST_kKeyA);
 -                      } else if ((recvChar >= 'a') && (recvChar <= 'z')) {
 -                              return (GHOST_TKey) (recvChar - 'a' + GHOST_kKeyA);
 -                      } else
 -                      switch (recvChar) {
 -                              case '-':       return GHOST_kKeyMinus;
 -                              case '=':       return GHOST_kKeyEqual;
 -                              case ',':       return GHOST_kKeyComma;
 -                              case '.':       return GHOST_kKeyPeriod;
 -                              case '/':       return GHOST_kKeySlash;
 -                              case ';':       return GHOST_kKeySemicolon;
 -                              case '\'':      return GHOST_kKeyQuote;
 -                              case '\\':      return GHOST_kKeyBackslash;
 -                              case '[':       return GHOST_kKeyLeftBracket;
 -                              case ']':       return GHOST_kKeyRightBracket;
 -                              case '`':       return GHOST_kKeyAccentGrave;
 -                              default:
 -                                      return GHOST_kKeyUnknown;
 -                      }
 -      }
 -      return GHOST_kKeyUnknown;
 -}
 -
 -
 +\r
 +#include "GHOST_TimerManager.h"\r
 +#include "GHOST_TimerTask.h"\r
 +#include "GHOST_WindowManager.h"\r
 +#include "GHOST_WindowCocoa.h"\r
 +#include "GHOST_NDOFManager.h"\r
 +#include "AssertMacros.h"\r
 +\r
 +#pragma mark KeyMap, mouse converters\r
 +\r
 +\r
 +/* Keycodes from Carbon include file */\r
 +/*  \r
 + *  Summary:\r
 + *    Virtual keycodes\r
 + *  \r
 + *  Discussion:\r
 + *    These constants are the virtual keycodes defined originally in\r
 + *    Inside Mac Volume V, pg. V-191. They identify physical keys on a\r
 + *    keyboard. Those constants with "ANSI" in the name are labeled\r
 + *    according to the key position on an ANSI-standard US keyboard.\r
 + *    For example, kVK_ANSI_A indicates the virtual keycode for the key\r
 + *    with the letter 'A' in the US keyboard layout. Other keyboard\r
 + *    layouts may have the 'A' key label on a different physical key;\r
 + *    in this case, pressing 'A' will generate a different virtual\r
 + *    keycode.\r
 + */\r
 +enum {\r
 +      kVK_ANSI_A                    = 0x00,\r
 +      kVK_ANSI_S                    = 0x01,\r
 +      kVK_ANSI_D                    = 0x02,\r
 +      kVK_ANSI_F                    = 0x03,\r
 +      kVK_ANSI_H                    = 0x04,\r
 +      kVK_ANSI_G                    = 0x05,\r
 +      kVK_ANSI_Z                    = 0x06,\r
 +      kVK_ANSI_X                    = 0x07,\r
 +      kVK_ANSI_C                    = 0x08,\r
 +      kVK_ANSI_V                    = 0x09,\r
 +      kVK_ANSI_B                    = 0x0B,\r
 +      kVK_ANSI_Q                    = 0x0C,\r
 +      kVK_ANSI_W                    = 0x0D,\r
 +      kVK_ANSI_E                    = 0x0E,\r
 +      kVK_ANSI_R                    = 0x0F,\r
 +      kVK_ANSI_Y                    = 0x10,\r
 +      kVK_ANSI_T                    = 0x11,\r
 +      kVK_ANSI_1                    = 0x12,\r
 +      kVK_ANSI_2                    = 0x13,\r
 +      kVK_ANSI_3                    = 0x14,\r
 +      kVK_ANSI_4                    = 0x15,\r
 +      kVK_ANSI_6                    = 0x16,\r
 +      kVK_ANSI_5                    = 0x17,\r
 +      kVK_ANSI_Equal                = 0x18,\r
 +      kVK_ANSI_9                    = 0x19,\r
 +      kVK_ANSI_7                    = 0x1A,\r
 +      kVK_ANSI_Minus                = 0x1B,\r
 +      kVK_ANSI_8                    = 0x1C,\r
 +      kVK_ANSI_0                    = 0x1D,\r
 +      kVK_ANSI_RightBracket         = 0x1E,\r
 +      kVK_ANSI_O                    = 0x1F,\r
 +      kVK_ANSI_U                    = 0x20,\r
 +      kVK_ANSI_LeftBracket          = 0x21,\r
 +      kVK_ANSI_I                    = 0x22,\r
 +      kVK_ANSI_P                    = 0x23,\r
 +      kVK_ANSI_L                    = 0x25,\r
 +      kVK_ANSI_J                    = 0x26,\r
 +      kVK_ANSI_Quote                = 0x27,\r
 +      kVK_ANSI_K                    = 0x28,\r
 +      kVK_ANSI_Semicolon            = 0x29,\r
 +      kVK_ANSI_Backslash            = 0x2A,\r
 +      kVK_ANSI_Comma                = 0x2B,\r
 +      kVK_ANSI_Slash                = 0x2C,\r
 +      kVK_ANSI_N                    = 0x2D,\r
 +      kVK_ANSI_M                    = 0x2E,\r
 +      kVK_ANSI_Period               = 0x2F,\r
 +      kVK_ANSI_Grave                = 0x32,\r
 +      kVK_ANSI_KeypadDecimal        = 0x41,\r
 +      kVK_ANSI_KeypadMultiply       = 0x43,\r
 +      kVK_ANSI_KeypadPlus           = 0x45,\r
 +      kVK_ANSI_KeypadClear          = 0x47,\r
 +      kVK_ANSI_KeypadDivide         = 0x4B,\r
 +      kVK_ANSI_KeypadEnter          = 0x4C,\r
 +      kVK_ANSI_KeypadMinus          = 0x4E,\r
 +      kVK_ANSI_KeypadEquals         = 0x51,\r
 +      kVK_ANSI_Keypad0              = 0x52,\r
 +      kVK_ANSI_Keypad1              = 0x53,\r
 +      kVK_ANSI_Keypad2              = 0x54,\r
 +      kVK_ANSI_Keypad3              = 0x55,\r
 +      kVK_ANSI_Keypad4              = 0x56,\r
 +      kVK_ANSI_Keypad5              = 0x57,\r
 +      kVK_ANSI_Keypad6              = 0x58,\r
 +      kVK_ANSI_Keypad7              = 0x59,\r
 +      kVK_ANSI_Keypad8              = 0x5B,\r
 +      kVK_ANSI_Keypad9              = 0x5C\r
 +};\r
 +\r
 +/* keycodes for keys that are independent of keyboard layout*/\r
 +enum {\r
 +      kVK_Return                    = 0x24,\r
 +      kVK_Tab                       = 0x30,\r
 +      kVK_Space                     = 0x31,\r
 +      kVK_Delete                    = 0x33,\r
 +      kVK_Escape                    = 0x35,\r
 +      kVK_Command                   = 0x37,\r
 +      kVK_Shift                     = 0x38,\r
 +      kVK_CapsLock                  = 0x39,\r
 +      kVK_Option                    = 0x3A,\r
 +      kVK_Control                   = 0x3B,\r
 +      kVK_RightShift                = 0x3C,\r
 +      kVK_RightOption               = 0x3D,\r
 +      kVK_RightControl              = 0x3E,\r
 +      kVK_Function                  = 0x3F,\r
 +      kVK_F17                       = 0x40,\r
 +      kVK_VolumeUp                  = 0x48,\r
 +      kVK_VolumeDown                = 0x49,\r
 +      kVK_Mute                      = 0x4A,\r
 +      kVK_F18                       = 0x4F,\r
 +      kVK_F19                       = 0x50,\r
 +      kVK_F20                       = 0x5A,\r
 +      kVK_F5                        = 0x60,\r
 +      kVK_F6                        = 0x61,\r
 +      kVK_F7                        = 0x62,\r
 +      kVK_F3                        = 0x63,\r
 +      kVK_F8                        = 0x64,\r
 +      kVK_F9                        = 0x65,\r
 +      kVK_F11                       = 0x67,\r
 +      kVK_F13                       = 0x69,\r
 +      kVK_F16                       = 0x6A,\r
 +      kVK_F14                       = 0x6B,\r
 +      kVK_F10                       = 0x6D,\r
 +      kVK_F12                       = 0x6F,\r
 +      kVK_F15                       = 0x71,\r
 +      kVK_Help                      = 0x72,\r
 +      kVK_Home                      = 0x73,\r
 +      kVK_PageUp                    = 0x74,\r
 +      kVK_ForwardDelete             = 0x75,\r
 +      kVK_F4                        = 0x76,\r
 +      kVK_End                       = 0x77,\r
 +      kVK_F2                        = 0x78,\r
 +      kVK_PageDown                  = 0x79,\r
 +      kVK_F1                        = 0x7A,\r
 +      kVK_LeftArrow                 = 0x7B,\r
 +      kVK_RightArrow                = 0x7C,\r
 +      kVK_DownArrow                 = 0x7D,\r
 +      kVK_UpArrow                   = 0x7E\r
 +};\r
 +\r
 +/* ISO keyboards only*/\r
 +enum {\r
 +      kVK_ISO_Section               = 0x0A\r
 +};\r
 +\r
 +/* JIS keyboards only*/\r
 +enum {\r
 +      kVK_JIS_Yen                   = 0x5D,\r
 +      kVK_JIS_Underscore            = 0x5E,\r
 +      kVK_JIS_KeypadComma           = 0x5F,\r
 +      kVK_JIS_Eisu                  = 0x66,\r
 +      kVK_JIS_Kana                  = 0x68\r
 +};\r
 +\r
 +\r
 +static GHOST_TButtonMask convertButton(int button)\r
 +{\r
 +      switch (button) {\r
 +              case 0:\r
 +                      return GHOST_kButtonMaskLeft;\r
 +              case 1:\r
 +                      return GHOST_kButtonMaskRight;\r
 +              case 2:\r
 +                      return GHOST_kButtonMaskMiddle;\r
 +              case 3:\r
 +                      return GHOST_kButtonMaskButton4;\r
 +              case 4:\r
 +                      return GHOST_kButtonMaskButton5;\r
 +              default:\r
 +                      return GHOST_kButtonMaskLeft;\r
 +      }\r
 +}\r
 +\r
 +/**\r
 + * Converts Mac rawkey codes (same for Cocoa & Carbon)\r
 + * into GHOST key codes\r
 + * @param rawCode The raw physical key code\r
 + * @param recvChar the character ignoring modifiers (except for shift)\r
 + * @return Ghost key code\r
 + */\r
 +static GHOST_TKey convertKey(int rawCode, unichar recvChar) \r
 +{     \r
 +      \r
 +      //printf("\nrecvchar %c 0x%x",recvChar,recvChar);\r
 +      switch (rawCode) {\r
 +              /*Physical keycodes not used due to map changes in int'l keyboards\r
 +              case kVK_ANSI_A:        return GHOST_kKeyA;\r
 +              case kVK_ANSI_B:        return GHOST_kKeyB;\r
 +              case kVK_ANSI_C:        return GHOST_kKeyC;\r
 +              case kVK_ANSI_D:        return GHOST_kKeyD;\r
 +              case kVK_ANSI_E:        return GHOST_kKeyE;\r
 +              case kVK_ANSI_F:        return GHOST_kKeyF;\r
 +              case kVK_ANSI_G:        return GHOST_kKeyG;\r
 +              case kVK_ANSI_H:        return GHOST_kKeyH;\r
 +              case kVK_ANSI_I:        return GHOST_kKeyI;\r
 +              case kVK_ANSI_J:        return GHOST_kKeyJ;\r
 +              case kVK_ANSI_K:        return GHOST_kKeyK;\r
 +              case kVK_ANSI_L:        return GHOST_kKeyL;\r
 +              case kVK_ANSI_M:        return GHOST_kKeyM;\r
 +              case kVK_ANSI_N:        return GHOST_kKeyN;\r
 +              case kVK_ANSI_O:        return GHOST_kKeyO;\r
 +              case kVK_ANSI_P:        return GHOST_kKeyP;\r
 +              case kVK_ANSI_Q:        return GHOST_kKeyQ;\r
 +              case kVK_ANSI_R:        return GHOST_kKeyR;\r
 +              case kVK_ANSI_S:        return GHOST_kKeyS;\r
 +              case kVK_ANSI_T:        return GHOST_kKeyT;\r
 +              case kVK_ANSI_U:        return GHOST_kKeyU;\r
 +              case kVK_ANSI_V:        return GHOST_kKeyV;\r
 +              case kVK_ANSI_W:        return GHOST_kKeyW;\r
 +              case kVK_ANSI_X:        return GHOST_kKeyX;\r
 +              case kVK_ANSI_Y:        return GHOST_kKeyY;\r
 +              case kVK_ANSI_Z:        return GHOST_kKeyZ;*/\r
 +              \r
 +              /* Numbers keys mapped to handle some int'l keyboard (e.g. French)*/\r
 +              case kVK_ISO_Section: return    GHOST_kKeyUnknown;\r
 +              case kVK_ANSI_1:        return GHOST_kKey1;\r
 +              case kVK_ANSI_2:        return GHOST_kKey2;\r
 +              case kVK_ANSI_3:        return GHOST_kKey3;\r
 +              case kVK_ANSI_4:        return GHOST_kKey4;\r
 +              case kVK_ANSI_5:        return GHOST_kKey5;\r
 +              case kVK_ANSI_6:        return GHOST_kKey6;\r
 +              case kVK_ANSI_7:        return GHOST_kKey7;\r
 +              case kVK_ANSI_8:        return GHOST_kKey8;\r
 +              case kVK_ANSI_9:        return GHOST_kKey9;\r
 +              case kVK_ANSI_0:        return GHOST_kKey0;\r
 +      \r
 +              case kVK_ANSI_Keypad0:                  return GHOST_kKeyNumpad0;\r
 +              case kVK_ANSI_Keypad1:                  return GHOST_kKeyNumpad1;\r
 +              case kVK_ANSI_Keypad2:                  return GHOST_kKeyNumpad2;\r
 +              case kVK_ANSI_Keypad3:                  return GHOST_kKeyNumpad3;\r
 +              case kVK_ANSI_Keypad4:                  return GHOST_kKeyNumpad4;\r
 +              case kVK_ANSI_Keypad5:                  return GHOST_kKeyNumpad5;\r
 +              case kVK_ANSI_Keypad6:                  return GHOST_kKeyNumpad6;\r
 +              case kVK_ANSI_Keypad7:                  return GHOST_kKeyNumpad7;\r
 +              case kVK_ANSI_Keypad8:                  return GHOST_kKeyNumpad8;\r
 +              case kVK_ANSI_Keypad9:                  return GHOST_kKeyNumpad9;\r
 +              case kVK_ANSI_KeypadDecimal:    return GHOST_kKeyNumpadPeriod;\r
 +              case kVK_ANSI_KeypadEnter:              return GHOST_kKeyNumpadEnter;\r
 +              case kVK_ANSI_KeypadPlus:               return GHOST_kKeyNumpadPlus;\r
 +              case kVK_ANSI_KeypadMinus:              return GHOST_kKeyNumpadMinus;\r
 +              case kVK_ANSI_KeypadMultiply:   return GHOST_kKeyNumpadAsterisk;\r
 +              case kVK_ANSI_KeypadDivide:     return GHOST_kKeyNumpadSlash;\r
 +              case kVK_ANSI_KeypadClear:              return GHOST_kKeyUnknown;\r
 +\r
 +              case kVK_F1:                            return GHOST_kKeyF1;\r
 +              case kVK_F2:                            return GHOST_kKeyF2;\r
 +              case kVK_F3:                            return GHOST_kKeyF3;\r
 +              case kVK_F4:                            return GHOST_kKeyF4;\r
 +              case kVK_F5:                            return GHOST_kKeyF5;\r
 +              case kVK_F6:                            return GHOST_kKeyF6;\r
 +              case kVK_F7:                            return GHOST_kKeyF7;\r
 +              case kVK_F8:                            return GHOST_kKeyF8;\r
 +              case kVK_F9:                            return GHOST_kKeyF9;\r
 +              case kVK_F10:                           return GHOST_kKeyF10;\r
 +              case kVK_F11:                           return GHOST_kKeyF11;\r
 +              case kVK_F12:                           return GHOST_kKeyF12;\r
 +              case kVK_F13:                           return GHOST_kKeyF13;\r
 +              case kVK_F14:                           return GHOST_kKeyF14;\r
 +              case kVK_F15:                           return GHOST_kKeyF15;\r
 +              case kVK_F16:                           return GHOST_kKeyF16;\r
 +              case kVK_F17:                           return GHOST_kKeyF17;\r
 +              case kVK_F18:                           return GHOST_kKeyF18;\r
 +              case kVK_F19:                           return GHOST_kKeyF19;\r
 +              case kVK_F20:                           return GHOST_kKeyF20;\r
 +                      \r
 +              case kVK_UpArrow:                       return GHOST_kKeyUpArrow;\r
 +              case kVK_DownArrow:                     return GHOST_kKeyDownArrow;\r
 +              case kVK_LeftArrow:                     return GHOST_kKeyLeftArrow;\r
 +              case kVK_RightArrow:            return GHOST_kKeyRightArrow;\r
 +                      \r
 +              case kVK_Return:                        return GHOST_kKeyEnter;\r
 +              case kVK_Delete:                        return GHOST_kKeyBackSpace;\r
 +              case kVK_ForwardDelete:         return GHOST_kKeyDelete;\r
 +              case kVK_Escape:                        return GHOST_kKeyEsc;\r
 +              case kVK_Tab:                           return GHOST_kKeyTab;\r
 +              case kVK_Space:                         return GHOST_kKeySpace;\r
 +                      \r
 +              case kVK_Home:                          return GHOST_kKeyHome;\r
 +              case kVK_End:                           return GHOST_kKeyEnd;\r
 +              case kVK_PageUp:                        return GHOST_kKeyUpPage;\r
 +              case kVK_PageDown:                      return GHOST_kKeyDownPage;\r
 +                      \r
 +              /*case kVK_ANSI_Minus:          return GHOST_kKeyMinus;\r
 +              case kVK_ANSI_Equal:            return GHOST_kKeyEqual;\r
 +              case kVK_ANSI_Comma:            return GHOST_kKeyComma;\r
 +              case kVK_ANSI_Period:           return GHOST_kKeyPeriod;\r
 +              case kVK_ANSI_Slash:            return GHOST_kKeySlash;\r
 +              case kVK_ANSI_Semicolon:        return GHOST_kKeySemicolon;\r
 +              case kVK_ANSI_Quote:            return GHOST_kKeyQuote;\r
 +              case kVK_ANSI_Backslash:        return GHOST_kKeyBackslash;\r
 +              case kVK_ANSI_LeftBracket:      return GHOST_kKeyLeftBracket;\r
 +              case kVK_ANSI_RightBracket:     return GHOST_kKeyRightBracket;\r
 +              case kVK_ANSI_Grave:            return GHOST_kKeyAccentGrave;*/\r
 +                      \r
 +              case kVK_VolumeUp:\r
 +              case kVK_VolumeDown:\r
 +              case kVK_Mute:\r
 +                      return GHOST_kKeyUnknown;\r
 +                      \r
 +              default:\r
 +                      /*Then detect on character value for "remappable" keys in int'l keyboards*/\r
 +                      if ((recvChar >= 'A') && (recvChar <= 'Z')) {\r
 +                              return (GHOST_TKey) (recvChar - 'A' + GHOST_kKeyA);\r
 +                      } else if ((recvChar >= 'a') && (recvChar <= 'z')) {\r
 +                              return (GHOST_TKey) (recvChar - 'a' + GHOST_kKeyA);\r
 +                      } else\r
 +                      switch (recvChar) {\r
 +                              case '-':       return GHOST_kKeyMinus;\r
 +                              case '=':       return GHOST_kKeyEqual;\r
 +                              case ',':       return GHOST_kKeyComma;\r
 +                              case '.':       return GHOST_kKeyPeriod;\r
 +                              case '/':       return GHOST_kKeySlash;\r
 +                              case ';':       return GHOST_kKeySemicolon;\r
 +                              case '\'':      return GHOST_kKeyQuote;\r
 +                              case '\\':      return GHOST_kKeyBackslash;\r
 +                              case '[':       return GHOST_kKeyLeftBracket;\r
 +                              case ']':       return GHOST_kKeyRightBracket;\r
 +                              case '`':       return GHOST_kKeyAccentGrave;\r
 +                              default:\r
 +                                      return GHOST_kKeyUnknown;\r
 +                      }\r
 +      }\r
 +      return GHOST_kKeyUnknown;\r
 +}\r
 +\r
 +\r
+ #pragma mark defines for 10.6 api not documented in 10.5
+ #ifndef MAC_OS_X_VERSION_10_6
+ enum {
+       /* The following event types are available on some hardware on 10.5.2 and later */
+       NSEventTypeGesture          = 29,
+       NSEventTypeMagnify          = 30,
+       NSEventTypeSwipe            = 31,
+       NSEventTypeRotate           = 18,
+       NSEventTypeBeginGesture     = 19,
+       NSEventTypeEndGesture       = 20
+ };
+ @interface NSEvent(GestureEvents)
+ /* This message is valid for events of type NSEventTypeMagnify, on 10.5.2 or later */
+ #if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4
+ - (float)magnification;       // change in magnification.
+ #else
+ - (CGFloat)magnification;       // change in magnification.
+ #endif
+ @end 
+ @interface NSEvent(SnowLeopardEvents)
+ /* modifier keys currently down.  This returns the state of devices combined
+  with synthesized events at the moment, independent of which events
+  have been delivered via the event stream. */
+ #if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4
+ + (unsigned int)modifierFlags; //NSUInteger is defined only from 10.5
+ #else
+ + (NSUInteger)modifierFlags;
+ #endif
+ @end
+ #endif
+ #pragma mark Utility functions
 -#define FIRSTFILEBUFLG 512
 -static bool g_hasFirstFile = false;
 -static char g_firstFileBuf[512];
 -
 -//TODO:Need to investigate this. Function called too early in creator.c to have g_hasFirstFile == true
 -extern "C" int GHOST_HACK_getFirstFile(char buf[FIRSTFILEBUFLG]) { 
 -      if (g_hasFirstFile) {
 -              strncpy(buf, g_firstFileBuf, FIRSTFILEBUFLG - 1);
 -              buf[FIRSTFILEBUFLG - 1] = '\0';
 -              return 1;
 -      } else {
 -              return 0; 
 -      }
 -}
 -
 +#define FIRSTFILEBUFLG 512\r
 +static bool g_hasFirstFile = false;\r
 +static char g_firstFileBuf[512];\r
 +\r
 +//TODO:Need to investigate this. Function called too early in creator.c to have g_hasFirstFile == true\r
 +extern "C" int GHOST_HACK_getFirstFile(char buf[FIRSTFILEBUFLG]) { \r
 +      if (g_hasFirstFile) {\r
 +              strncpy(buf, g_firstFileBuf, FIRSTFILEBUFLG - 1);\r
 +              buf[FIRSTFILEBUFLG - 1] = '\0';\r
 +              return 1;\r
 +      } else {\r
 +              return 0; \r
 +      }\r
 +}\r
 +\r
  #if defined(WITH_QUICKTIME) && !defined(USE_QTKIT)
  //Need to place this quicktime function in an ObjC file
  //It is used to avoid memory leak when raising the quicktime "compression settings" standard dialog
@@@ -559,144 -597,145 +597,145 @@@ GHOST_TSuccess GHOST_SystemCocoa::init(
                                menuItem = [windowMenu addItemWithTitle:@"Close" action:@selector(performClose:) keyEquivalent:@"w"];
                                [menuItem setKeyEquivalentModifierMask:NSCommandKeyMask];
                                
 -                              menuItem = [[NSMenuItem alloc] init];
 -                              [menuItem setSubmenu:windowMenu];
 -                              
 -                              [mainMenubar addItem:menuItem];
 -                              [menuItem release];
 -                              
 -                              [NSApp setMainMenu:mainMenubar];
 -                              [NSApp setWindowsMenu:windowMenu];
 -                              [windowMenu release];
 -                      }
 -              }
 -              if ([NSApp delegate] == nil) {
 -                      CocoaAppDelegate *appDelegate = [[CocoaAppDelegate alloc] init];
 -                      [appDelegate setSystemCocoa:this];
 -                      [NSApp setDelegate:appDelegate];
 -              }
 +                              menuItem = [[NSMenuItem alloc] init];\r
 +                              [menuItem setSubmenu:windowMenu];\r
 +                              \r
 +                              [mainMenubar addItem:menuItem];\r
 +                              [menuItem release];\r
 +                              \r
 +                              [NSApp setMainMenu:mainMenubar];\r
 +                              [NSApp setWindowsMenu:windowMenu];\r
 +                              [windowMenu release];\r
 +                      }\r
 +              }\r
 +              if ([NSApp delegate] == nil) {\r
 +                      CocoaAppDelegate *appDelegate = [[CocoaAppDelegate alloc] init];\r
 +                      [appDelegate setSystemCocoa:this];\r
 +                      [NSApp setDelegate:appDelegate];\r
 +              }\r
                
                [NSApp finishLaunching];
-                               \r
+               
 -              [pool drain];
 -    }
 -    return success;
 -}
 -
 -
 -#pragma mark window management
 -
 -GHOST_TUns64 GHOST_SystemCocoa::getMilliSeconds() const
 -{
 -      //Cocoa equivalent exists in 10.6 ([[NSProcessInfo processInfo] systemUptime])
 +              [pool drain];\r
 +    }\r
 +    return success;\r
 +}\r
 +\r
 +\r
 +#pragma mark window management\r
 +\r
 +GHOST_TUns64 GHOST_SystemCocoa::getMilliSeconds() const\r
 +{\r
 +      //Cocoa equivalent exists in 10.6 ([[NSProcessInfo processInfo] systemUptime])\r
        struct timeval currentTime;
 -      
 +      \r
        gettimeofday(&currentTime, NULL);
 -      
 +      \r
        //Return timestamp of system uptime
        
        return ((currentTime.tv_sec*1000)+(currentTime.tv_usec/1000)-m_start_time);
 -}
 -
 -
 -GHOST_TUns8 GHOST_SystemCocoa::getNumDisplays() const
 -{
 -      //Note that OS X supports monitor hot plug
 -      // We do not support multiple monitors at the moment
 -      NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 -
 -      GHOST_TUns8 count = [[NSScreen screens] count];
 -
 -      [pool drain];
 -      return count;
 -}
 -
 -
 -void GHOST_SystemCocoa::getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const
 -{
 -      NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 -      //Get visible frame, that is frame excluding dock and top menu bar
 -      NSRect frame = [[NSScreen mainScreen] visibleFrame];
 -      
 -      //Returns max window contents (excluding title bar...)
 -      NSRect contentRect = [NSWindow contentRectForFrameRect:frame
 -                                                                                               styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask)];
 -      
 -      width = contentRect.size.width;
 -      height = contentRect.size.height;
 -
 -      [pool drain];
 -}
 -
 -
 -GHOST_IWindow* GHOST_SystemCocoa::createWindow(
 -      const STR_String& title, 
 -      GHOST_TInt32 left,
 -      GHOST_TInt32 top,
 -      GHOST_TUns32 width,
 -      GHOST_TUns32 height,
 -      GHOST_TWindowState state,
 -      GHOST_TDrawingContextType type,
 -      bool stereoVisual,
 +}\r
 +\r
 +\r
 +GHOST_TUns8 GHOST_SystemCocoa::getNumDisplays() const\r
 +{\r
 +      //Note that OS X supports monitor hot plug\r
 +      // We do not support multiple monitors at the moment\r
 +      NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];\r
 +\r
 +      GHOST_TUns8 count = [[NSScreen screens] count];\r
 +\r
 +      [pool drain];\r
 +      return count;\r
 +}\r
 +\r
 +\r
 +void GHOST_SystemCocoa::getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const\r
 +{\r
 +      NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];\r
 +      //Get visible frame, that is frame excluding dock and top menu bar\r
 +      NSRect frame = [[NSScreen mainScreen] visibleFrame];\r
 +      \r
 +      //Returns max window contents (excluding title bar...)\r
 +      NSRect contentRect = [NSWindow contentRectForFrameRect:frame\r
 +                                                                                               styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask)];\r
 +      \r
 +      width = contentRect.size.width;\r
 +      height = contentRect.size.height;\r
 +\r
 +      [pool drain];\r
 +}\r
 +\r
 +\r
 +GHOST_IWindow* GHOST_SystemCocoa::createWindow(\r
 +      const STR_String& title, \r
 +      GHOST_TInt32 left,\r
 +      GHOST_TInt32 top,\r
 +      GHOST_TUns32 width,\r
 +      GHOST_TUns32 height,\r
 +      GHOST_TWindowState state,\r
 +      GHOST_TDrawingContextType type,\r
 +      bool stereoVisual,\r
+       const GHOST_TUns16 numOfAASamples,
 -      const GHOST_TEmbedderWindowID parentWindow
 -)
 -{
 -    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 -      GHOST_IWindow* window = 0;
 -      
 -      //Get the available rect for including window contents
 -      NSRect frame = [[NSScreen mainScreen] visibleFrame];
 -      NSRect contentRect = [NSWindow contentRectForFrameRect:frame
 -                                                                                               styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask)];
 -      
 -      //Ensures window top left is inside this available rect
 -      left = left > contentRect.origin.x ? left : contentRect.origin.x;
 -      top = top > contentRect.origin.y ? top : contentRect.origin.y;
 -      
 +      const GHOST_TEmbedderWindowID parentWindow\r
 +)\r
 +{\r
 +    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];\r
 +      GHOST_IWindow* window = 0;\r
 +      \r
 +      //Get the available rect for including window contents\r
 +      NSRect frame = [[NSScreen mainScreen] visibleFrame];\r
 +      NSRect contentRect = [NSWindow contentRectForFrameRect:frame\r
 +                                                                                               styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask)];\r
 +      \r
 +      //Ensures window top left is inside this available rect\r
 +      left = left > contentRect.origin.x ? left : contentRect.origin.x;\r
 +      top = top > contentRect.origin.y ? top : contentRect.origin.y;\r
 +      \r
-       window = new GHOST_WindowCocoa (this, title, left, top, width, height, state, type);\r
+       window = new GHOST_WindowCocoa (this, title, left, top, width, height, state, type, stereoVisual, numOfAASamples);
 -
 -    if (window) {
 -        if (window->getValid()) {
 -            // Store the pointer to the window 
 -            GHOST_ASSERT(m_windowManager, "m_windowManager not initialized");
 -            m_windowManager->addWindow(window);
 -            m_windowManager->setActiveWindow(window);
 -                      //Need to tell window manager the new window is the active one (Cocoa does not send the event activate upon window creation)
 -            pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowActivate, window));
 -                      pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window));
 -
 -        }
 -        else {
 -                      GHOST_PRINT("GHOST_SystemCocoa::createWindow(): window invalid\n");
 -            delete window;
 -            window = 0;
 -        }
 -    }
 -      else {
 -              GHOST_PRINT("GHOST_SystemCocoa::createWindow(): could not create window\n");
 -      }
 -      [pool drain];
 -    return window;
 -}
 -
 -GHOST_TSuccess GHOST_SystemCocoa::beginFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow** window, const bool stereoVisual)
 -{     
 -      GHOST_IWindow* currentWindow = m_windowManager->getActiveWindow();
 -
 -      *window = currentWindow;
 -      
 -      return currentWindow->setState(GHOST_kWindowStateFullScreen);
 -}
 -
 -GHOST_TSuccess GHOST_SystemCocoa::endFullScreen(void)
 -{     
 -      GHOST_IWindow* currentWindow = m_windowManager->getActiveWindow();
 -      
 -      return currentWindow->setState(GHOST_kWindowStateNormal);
 -}
 -
 -
 -      
 +\r
 +    if (window) {\r
 +        if (window->getValid()) {\r
 +            // Store the pointer to the window \r
 +            GHOST_ASSERT(m_windowManager, "m_windowManager not initialized");\r
 +            m_windowManager->addWindow(window);\r
 +            m_windowManager->setActiveWindow(window);\r
 +                      //Need to tell window manager the new window is the active one (Cocoa does not send the event activate upon window creation)\r
 +            pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowActivate, window));\r
 +                      pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window));\r
 +\r
 +        }\r
 +        else {\r
 +                      GHOST_PRINT("GHOST_SystemCocoa::createWindow(): window invalid\n");\r
 +            delete window;\r
 +            window = 0;\r
 +        }\r
 +    }\r
 +      else {\r
 +              GHOST_PRINT("GHOST_SystemCocoa::createWindow(): could not create window\n");\r
 +      }\r
 +      [pool drain];\r
 +    return window;\r
 +}\r
 +\r
 +GHOST_TSuccess GHOST_SystemCocoa::beginFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow** window, const bool stereoVisual)\r
 +{     \r
 +      GHOST_IWindow* currentWindow = m_windowManager->getActiveWindow();\r
 +\r
 +      *window = currentWindow;\r
 +      \r
 +      return currentWindow->setState(GHOST_kWindowStateFullScreen);\r
 +}\r
 +\r
 +GHOST_TSuccess GHOST_SystemCocoa::endFullScreen(void)\r
 +{     \r
 +      GHOST_IWindow* currentWindow = m_windowManager->getActiveWindow();\r
 +      \r
 +      return currentWindow->setState(GHOST_kWindowStateNormal);\r
 +}\r
 +\r
 +\r
 +      \r
  /**
   * @note : returns coordinates in Cocoa screen coordinates
   */
@@@ -739,129 -778,129 +778,129 @@@ GHOST_TSuccess GHOST_SystemCocoa::getMo
        keys.set(GHOST_kModifierKeyLeftAlt, (m_modifierMask & NSAlternateKeyMask) ? true : false);
        keys.set(GHOST_kModifierKeyLeftShift, (m_modifierMask & NSShiftKeyMask) ? true : false);
        keys.set(GHOST_kModifierKeyLeftControl, (m_modifierMask & NSControlKeyMask) ? true : false);
 -      
 -    return GHOST_kSuccess;
 -}
 -
 -GHOST_TSuccess GHOST_SystemCocoa::getButtons(GHOST_Buttons& buttons) const
 -{
 -      buttons.clear();
 -    buttons.set(GHOST_kButtonMaskLeft, m_pressedMouseButtons & GHOST_kButtonMaskLeft);
 -      buttons.set(GHOST_kButtonMaskRight, m_pressedMouseButtons & GHOST_kButtonMaskRight);
 -      buttons.set(GHOST_kButtonMaskMiddle, m_pressedMouseButtons & GHOST_kButtonMaskMiddle);
 -      buttons.set(GHOST_kButtonMaskButton4, m_pressedMouseButtons & GHOST_kButtonMaskButton4);
 -      buttons.set(GHOST_kButtonMaskButton5, m_pressedMouseButtons & GHOST_kButtonMaskButton5);
 -    return GHOST_kSuccess;
 -}
 -
 -
 -
 -#pragma mark Event handlers
 -
 -/**
 - * The event queue polling function
 - */
 -bool GHOST_SystemCocoa::processEvents(bool waitForEvent)
 -{
 -      bool anyProcessed = false;
 -      NSEvent *event;
 -      
 -      //      SetMouseCoalescingEnabled(false, NULL);
 -      //TODO : implement timer ??
 -      
 -      /*do {
 -              GHOST_TimerManager* timerMgr = getTimerManager();
 -              
 -               if (waitForEvent) {
 -               GHOST_TUns64 next = timerMgr->nextFireTime();
 -               double timeOut;
 -               
 -               if (next == GHOST_kFireTimeNever) {
 -               timeOut = kEventDurationForever;
 -               } else {
 -               timeOut = (double)(next - getMilliSeconds())/1000.0;
 -               if (timeOut < 0.0)
 -               timeOut = 0.0;
 -               }
 -               
 -               ::ReceiveNextEvent(0, NULL, timeOut, false, &event);
 -               }
 -               
 -               if (timerMgr->fireTimers(getMilliSeconds())) {
 -               anyProcessed = true;
 -               }*/
 -              
 -              do {
 -                      NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
 -                      event = [NSApp nextEventMatchingMask:NSAnyEventMask
 -                                                                         untilDate:[NSDate distantPast]
 -                                                                                inMode:NSDefaultRunLoopMode
 -                                                                               dequeue:YES];
 -                      if (event==nil) {
 -                              [pool drain];
 -                              break;
 -                      }
 -                      
 -                      anyProcessed = true;
 -                      
 -                      switch ([event type]) {
 -                              case NSKeyDown:
 -                              case NSKeyUp:
 -                              case NSFlagsChanged:
 -                                      handleKeyEvent(event);
 -                                      
 +      \r
 +    return GHOST_kSuccess;\r
 +}\r
 +\r
 +GHOST_TSuccess GHOST_SystemCocoa::getButtons(GHOST_Buttons& buttons) const\r
 +{\r
 +      buttons.clear();\r
 +    buttons.set(GHOST_kButtonMaskLeft, m_pressedMouseButtons & GHOST_kButtonMaskLeft);\r
 +      buttons.set(GHOST_kButtonMaskRight, m_pressedMouseButtons & GHOST_kButtonMaskRight);\r
 +      buttons.set(GHOST_kButtonMaskMiddle, m_pressedMouseButtons & GHOST_kButtonMaskMiddle);\r
 +      buttons.set(GHOST_kButtonMaskButton4, m_pressedMouseButtons & GHOST_kButtonMaskButton4);\r
 +      buttons.set(GHOST_kButtonMaskButton5, m_pressedMouseButtons & GHOST_kButtonMaskButton5);\r
 +    return GHOST_kSuccess;\r
 +}\r
 +\r
 +\r
 +\r
 +#pragma mark Event handlers\r
 +\r
 +/**\r
 + * The event queue polling function\r
 + */\r
 +bool GHOST_SystemCocoa::processEvents(bool waitForEvent)\r
 +{\r
 +      bool anyProcessed = false;\r
 +      NSEvent *event;\r
 +      \r
 +      //      SetMouseCoalescingEnabled(false, NULL);\r
 +      //TODO : implement timer ??\r
 +      \r
 +      /*do {\r
 +              GHOST_TimerManager* timerMgr = getTimerManager();\r
 +              \r
 +               if (waitForEvent) {\r
 +               GHOST_TUns64 next = timerMgr->nextFireTime();\r
 +               double timeOut;\r
 +               \r
 +               if (next == GHOST_kFireTimeNever) {\r
 +               timeOut = kEventDurationForever;\r
 +               } else {\r
 +               timeOut = (double)(next - getMilliSeconds())/1000.0;\r
 +               if (timeOut < 0.0)\r
 +               timeOut = 0.0;\r
 +               }\r
 +               \r
 +               ::ReceiveNextEvent(0, NULL, timeOut, false, &event);\r
 +               }\r
 +               \r
 +               if (timerMgr->fireTimers(getMilliSeconds())) {\r
 +               anyProcessed = true;\r
 +               }*/\r
 +              \r
 +              do {\r
 +                      NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];\r
 +                      event = [NSApp nextEventMatchingMask:NSAnyEventMask\r
 +                                                                         untilDate:[NSDate distantPast]\r
 +                                                                                inMode:NSDefaultRunLoopMode\r
 +                                                                               dequeue:YES];\r
 +                      if (event==nil) {\r
 +                              [pool drain];\r
 +                              break;\r
 +                      }\r
 +                      \r
 +                      anyProcessed = true;\r
 +                      \r
 +                      switch ([event type]) {\r
 +                              case NSKeyDown:\r
 +                              case NSKeyUp:\r
 +                              case NSFlagsChanged:\r
 +                                      handleKeyEvent(event);\r
 +                                      \r
                                        /* Support system-wide keyboard shortcuts, like Expos√©, ...) =>included in always NSApp sendEvent */
 -                                      /*              if (([event modifierFlags] & NSCommandKeyMask) || [event type] == NSFlagsChanged) {
 -                                       [NSApp sendEvent:event];
 -                                       }*/
 -                                      break;
 -                                      
 -                              case NSLeftMouseDown:
 -                              case NSLeftMouseUp:
 -                              case NSRightMouseDown:
 -                              case NSRightMouseUp:
 -                              case NSMouseMoved:
 -                              case NSLeftMouseDragged:
 -                              case NSRightMouseDragged:
 -                              case NSScrollWheel:
 -                              case NSOtherMouseDown:
 -                              case NSOtherMouseUp:
 +                                      /*              if (([event modifierFlags] & NSCommandKeyMask) || [event type] == NSFlagsChanged) {\r
 +                                       [NSApp sendEvent:event];\r
 +                                       }*/\r
 +                                      break;\r
 +                                      \r
 +                              case NSLeftMouseDown:\r
 +                              case NSLeftMouseUp:\r
 +                              case NSRightMouseDown:\r
 +                              case NSRightMouseUp:\r
 +                              case NSMouseMoved:\r
 +                              case NSLeftMouseDragged:\r
 +                              case NSRightMouseDragged:\r
 +                              case NSScrollWheel:\r
 +                              case NSOtherMouseDown:\r
 +                              case NSOtherMouseUp:\r
-                               case NSOtherMouseDragged:                               \r
+                               case NSOtherMouseDragged:
+                               case NSEventTypeMagnify:
+                               case NSEventTypeRotate:
 -                                      handleMouseEvent(event);
 -                                      break;
 -                                      
 -                              case NSTabletPoint:
 -                              case NSTabletProximity:
 -                                      handleTabletEvent(event,[event type]);
 -                                      break;
 -                                      
 +                                      handleMouseEvent(event);\r
 +                                      break;\r
 +                                      \r
 +                              case NSTabletPoint:\r
 +                              case NSTabletProximity:\r
 +                                      handleTabletEvent(event,[event type]);\r
 +                                      break;\r
 +                                      \r
-                                       /* Trackpad features, will need OS X 10.6 for implementation\r
+                                       /* Trackpad features, fired only from OS X 10.5.2
 -                                       case NSEventTypeGesture:
 -                                       case NSEventTypeSwipe:
 -                                       case NSEventTypeBeginGesture:
 -                                       case NSEventTypeEndGesture:
 -                                       break; */
 -                                      
 -                                      /*Unused events
 -                                       NSMouseEntered       = 8,
 -                                       NSMouseExited        = 9,
 -                                       NSAppKitDefined      = 13,
 -                                       NSSystemDefined      = 14,
 -                                       NSApplicationDefined = 15,
 -                                       NSPeriodic           = 16,
 -                                       NSCursorUpdate       = 17,*/
 -                                      
 -                              default:
 -                                      break;
 -                      }
 -                      //Resend event to NSApp to ensure Mac wide events are handled
 -                      [NSApp sendEvent:event];
 -                      [pool drain];
 -              } while (event!= nil);          
 -      //} while (waitForEvent && !anyProcessed); Needed only for timer implementation
 -      
 +                                       case NSEventTypeGesture:\r
-                                        case NSEventTypeMagnify:\r
 +                                       case NSEventTypeSwipe:\r
-                                        case NSEventTypeRotate:\r
 +                                       case NSEventTypeBeginGesture:\r
 +                                       case NSEventTypeEndGesture:\r
 +                                       break; */\r
 +                                      \r
 +                                      /*Unused events\r
 +                                       NSMouseEntered       = 8,\r
 +                                       NSMouseExited        = 9,\r
 +                                       NSAppKitDefined      = 13,\r
 +                                       NSSystemDefined      = 14,\r
 +                                       NSApplicationDefined = 15,\r
 +                                       NSPeriodic           = 16,\r
 +                                       NSCursorUpdate       = 17,*/\r
 +                                      \r
 +                              default:\r
 +                                      break;\r
 +                      }\r
 +                      //Resend event to NSApp to ensure Mac wide events are handled\r
 +                      [NSApp sendEvent:event];\r
 +                      [pool drain];\r
 +              } while (event!= nil);          \r
 +      //} while (waitForEvent && !anyProcessed); Needed only for timer implementation\r
 +      \r
        if (m_outsideLoopEventProcessed) {
                m_outsideLoopEventProcessed = false;
                return true;
@@@ -1295,58 -1330,95 +1330,95 @@@ GHOST_TSuccess GHOST_SystemCocoa::handl
                                                m_cursorDelta_y=0; //Mouse motion occured between two cursor warps, so we can reset the delta counter
                                        }
                                                break;
 -                              }
 -                              break;
 -                      
 -              case NSScrollWheel:
 -                      {
 +                              }\r
 +                              break;\r
 +                      \r
 +              case NSScrollWheel:\r
 +                      {\r
-                               GHOST_TInt32 delta;\r
-                               \r
-                               double deltaF = [event deltaY];\r
-                               if (deltaF == 0.0) break; //discard trackpad delta=0 events\r
-                               \r
-                               delta = deltaF > 0.0 ? 1 : -1;\r
-                               pushEvent(new GHOST_EventWheel([event timestamp]*1000, window, delta));
+                               /* Send Wheel event if sent from the mouse, trackpad event otherwise */
+                               if ([event subtype] == NSMouseEventSubtype) {
+                                       GHOST_TInt32 delta;
+                                       
+                                       double deltaF = [event deltaY];
+                                       if (deltaF == 0.0) break; //discard trackpad delta=0 events
+                                       
+                                       delta = deltaF > 0.0 ? 1 : -1;
+                                       pushEvent(new GHOST_EventWheel([event timestamp]*1000, window, delta));
+                               }
+                               else {
+                                       NSPoint mousePos = [event locationInWindow];
+                                       double dx = [event deltaX];
+                                       double dy = -[event deltaY];
+                                       
+                                       const double deltaMax = 50.0;
+                                       
+                                       if ((dx == 0) && (dy == 0)) break;
+                                       
+                                       /* Quadratic acceleration */
+                                       dx = dx*(fabs(dx)+0.5);
+                                       if (dx<0.0) dx-=0.5; else dx+=0.5;
+                                       if (dx< -deltaMax) dx= -deltaMax; else if (dx>deltaMax) dx=deltaMax;
+                                       
+                                       dy = dy*(fabs(dy)+0.5);
+                                       if (dy<0.0) dy-=0.5; else dy+=0.5;
+                                       if (dy< -deltaMax) dy= -deltaMax; else if (dy>deltaMax) dy=deltaMax;
+                                       pushEvent(new GHOST_EventTrackpad([event timestamp]*1000, window, GHOST_kTrackpadEventScroll, mousePos.x, mousePos.y, dx, dy));
+                               }
 -                      }
 -                      break;
 -                      
 +                      }\r
 +                      break;\r
 +                      \r
+               case NSEventTypeMagnify:
+                       {
+                               NSPoint mousePos = [event locationInWindow];
+                               pushEvent(new GHOST_EventTrackpad([event timestamp]*1000, window, GHOST_kTrackpadEventMagnify, mousePos.x, mousePos.y,
+                                                                                                 [event magnification]*250.0 + 0.1, 0));
+                       }
+                       break;
+               case NSEventTypeRotate:
+                       {
+                               NSPoint mousePos = [event locationInWindow];
+                               pushEvent(new GHOST_EventTrackpad([event timestamp]*1000, window, GHOST_kTrackpadEventRotate, mousePos.x, mousePos.y,
+                                                                                                 -[event rotation] * 5.0, 0));
+                       }
 -              default:
 -                      return GHOST_kFailure;
 -                      break;
 -              }
 -      
 -      return GHOST_kSuccess;
 -}
 -
 -
 -GHOST_TSuccess GHOST_SystemCocoa::handleKeyEvent(void *eventPtr)
 -{
 -      NSEvent *event = (NSEvent *)eventPtr;
 -      GHOST_IWindow* window = m_windowManager->getActiveWindow();
 -      unsigned int modifiers;
 -      NSString *characters;
 +              default:\r
 +                      return GHOST_kFailure;\r
 +                      break;\r
 +              }\r
 +      \r
 +      return GHOST_kSuccess;\r
 +}\r
 +\r
 +\r
 +GHOST_TSuccess GHOST_SystemCocoa::handleKeyEvent(void *eventPtr)\r
 +{\r
 +      NSEvent *event = (NSEvent *)eventPtr;\r
 +      GHOST_IWindow* window = m_windowManager->getActiveWindow();\r
 +      unsigned int modifiers;\r
 +      NSString *characters;\r
        NSData *convertedCharacters;
 -      GHOST_TKey keyCode;
 -      unsigned char ascii;
 +      GHOST_TKey keyCode;\r
 +      unsigned char ascii;\r
        NSString* charsIgnoringModifiers;
 -
 -      /* Can happen, very rarely - seems to only be when command-H makes
 -       * the window go away and we still get an HKey up. 
 -       */
 -      if (!window) {
 -              printf("\nW failure");
 -              return GHOST_kFailure;
 -      }
 -      
 -      switch ([event type]) {
 -              case NSKeyDown:
 -              case NSKeyUp:
 +\r
 +      /* Can happen, very rarely - seems to only be when command-H makes\r
 +       * the window go away and we still get an HKey up. \r
 +       */\r
 +      if (!window) {\r
 +              printf("\nW failure");\r
 +              return GHOST_kFailure;\r
 +      }\r
 +      \r
 +      switch ([event type]) {\r
 +              case NSKeyDown:\r
 +              case NSKeyUp:\r
                        charsIgnoringModifiers = [event charactersIgnoringModifiers];
                        if ([charsIgnoringModifiers length]>0)
 -                              keyCode = convertKey([event keyCode],
 +                              keyCode = convertKey([event keyCode],\r
                                                                         [charsIgnoringModifiers characterAtIndex:0]);
                        else
 -                              keyCode = convertKey([event keyCode],0);
 +                              keyCode = convertKey([event keyCode],0);\r
  
                                
                        characters = [event characters];
index 3f52ea535bdc53eb2dfe90db9e3a214dda759d03,66c6d75b6d756e4bb5603fb937938f5b4e0e2b98..873a59251026b6f853c24bcbf6cce2274bf4c8a9
@@@ -1,49 -1,51 +1,51 @@@
 -/**
 - * $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) 2001-2002 by NaN Holding BV.
 - * All rights reserved.
 - *
 - * The Original Code is: all of this file.
 - *
 - * Contributor(s):    Maarten Gribnau 05/2001
 -                                      Damien Plisson 10/2009
 - *
 - * ***** END GPL LICENSE BLOCK *****
 - */
 -
 -#include <Cocoa/Cocoa.h>
 -
 -#ifndef MAC_OS_X_VERSION_10_6
 -//Use of the SetSystemUIMode function (64bit compatible)
 -#include <Carbon/Carbon.h>
 -#endif
 -
 +/**\r
 + * $Id: GHOST_WindowCocoa.mm 23873 2009-10-15 20:09:50Z damien78 $\r
 + * ***** BEGIN GPL LICENSE BLOCK *****\r
 + *\r
 + * This program is free software; you can redistribute it and/or\r
 + * modify it under the terms of the GNU General Public License\r
 + * as published by the Free Software Foundation; either version 2\r
 + * of the License, or (at your option) any later version.\r
 + *\r
 + * This program is distributed in the hope that it will be useful,\r
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
 + * GNU General Public License for more details.\r
 + *\r
 + * You should have received a copy of the GNU General Public License\r
 + * along with this program; if not, write to the Free Software Foundation,\r
 + * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.\r
 + *\r
 + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.\r
 + * All rights reserved.\r
 + *\r
 + * The Original Code is: all of this file.\r
 + *\r
 + * Contributor(s):    Maarten Gribnau 05/2001\r
 +                                      Damien Plisson 10/2009\r
 + *\r
 + * ***** END GPL LICENSE BLOCK *****\r
 + */\r
 +\r
 +#include <Cocoa/Cocoa.h>\r
 +\r
 +#ifndef MAC_OS_X_VERSION_10_6\r
 +//Use of the SetSystemUIMode function (64bit compatible)\r
 +#include <Carbon/Carbon.h>\r
 +#endif\r
 +\r
+ #include <OpenGL/gl.h>
  /***** Multithreaded opengl code : uncomment for enabling
  #include <OpenGL/OpenGL.h>
  */
   
 -#include "GHOST_WindowCocoa.h"
 -#include "GHOST_SystemCocoa.h"
 -#include "GHOST_Debug.h"
 -
 -
 -#pragma mark Cocoa window delegate object
 +#include "GHOST_WindowCocoa.h"\r
 +#include "GHOST_SystemCocoa.h"\r
 +#include "GHOST_Debug.h"\r
 +\r
 +\r
 +#pragma mark Cocoa window delegate object\r
  /* live resize ugly patch
  extern "C" {
        struct bContext;
  }
  #endif
  
 -- (BOOL)isOpaque
 -{
 -    return YES;
 -}
 -
 -@end
 -
 -
 -#pragma mark initialization / finalization
 -
 -NSOpenGLContext* GHOST_WindowCocoa::s_firstOpenGLcontext = nil;
 -
 -GHOST_WindowCocoa::GHOST_WindowCocoa(
 -      GHOST_SystemCocoa *systemCocoa,
 -      const STR_String& title,
 -      GHOST_TInt32 left,
 -      GHOST_TInt32 top,
 -      GHOST_TUns32 width,
 -      GHOST_TUns32 height,
 -      GHOST_TWindowState state,
 -      GHOST_TDrawingContextType type,
 +- (BOOL)isOpaque\r
 +{\r
 +    return YES;\r
 +}\r
 +\r
 +@end\r
 +\r
 +\r
 +#pragma mark initialization / finalization\r
 +\r
 +NSOpenGLContext* GHOST_WindowCocoa::s_firstOpenGLcontext = nil;\r
 +\r
 +GHOST_WindowCocoa::GHOST_WindowCocoa(\r
 +      GHOST_SystemCocoa *systemCocoa,\r
 +      const STR_String& title,\r
 +      GHOST_TInt32 left,\r
 +      GHOST_TInt32 top,\r
 +      GHOST_TUns32 width,\r
 +      GHOST_TUns32 height,\r
 +      GHOST_TWindowState state,\r
 +      GHOST_TDrawingContextType type,\r
-       const bool stereoVisual\r
+       const bool stereoVisual, const GHOST_TUns16 numOfAASamples
 -) :
 +) :\r
-       GHOST_Window(title, left, top, width, height, state, GHOST_kDrawingContextTypeNone, stereoVisual),
+       GHOST_Window(title, left, top, width, height, state, GHOST_kDrawingContextTypeNone, stereoVisual, numOfAASamples),
 -      m_customCursor(0)
 -{
 +      m_customCursor(0)\r
 +{\r
        NSOpenGLPixelFormatAttribute pixelFormatAttrsWindow[40];
+       NSOpenGLPixelFormat *pixelFormat = nil;
        int i;
-       
+               
 -      m_systemCocoa = systemCocoa;
 -      m_fullScreen = false;
 -      
 -      NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 -      
 -
 -      //Creates the window
 -      NSRect rect;
 +      m_systemCocoa = systemCocoa;\r
 +      m_fullScreen = false;\r
 +      \r
 +      NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];\r
 +      \r
 +\r
 +      //Creates the window\r
 +      NSRect rect;\r
        NSSize  minSize;
 -      
 -      rect.origin.x = left;
 -      rect.origin.y = top;
 -      rect.size.width = width;
 -      rect.size.height = height;
 -      
 -      m_window = [[CocoaWindow alloc] initWithContentRect:rect
 -                                                                                 styleMask:NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask | NSMiniaturizableWindowMask
 -                                                                                       backing:NSBackingStoreBuffered defer:NO];
 -      if (m_window == nil) {
 -              [pool drain];
 -              return;
 -      }
 -      
 +      \r
 +      rect.origin.x = left;\r
 +      rect.origin.y = top;\r
 +      rect.size.width = width;\r
 +      rect.size.height = height;\r
 +      \r
 +      m_window = [[CocoaWindow alloc] initWithContentRect:rect\r
 +                                                                                 styleMask:NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask | NSMiniaturizableWindowMask\r
 +                                                                                       backing:NSBackingStoreBuffered defer:NO];\r
 +      if (m_window == nil) {\r
 +              [pool drain];\r
 +              return;\r
 +      }\r
 +      \r
        [m_window setSystemAndWindowCocoa:systemCocoa windowCocoa:this];
        
        //Forbid to resize the window below the blender defined minimum one
        
        if (stereoVisual) pixelFormatAttrsWindow[i++] = NSOpenGLPFAStereo;
        
+       if (numOfAASamples>0) {
+               // Multisample anti-aliasing
+               pixelFormatAttrsWindow[i++] = NSOpenGLPFAMultisample;
+               
+               pixelFormatAttrsWindow[i++] = NSOpenGLPFASampleBuffers;
+               pixelFormatAttrsWindow[i++] = (NSOpenGLPixelFormatAttribute) 1;
+               
+               pixelFormatAttrsWindow[i++] = NSOpenGLPFASamples;
+               pixelFormatAttrsWindow[i++] = (NSOpenGLPixelFormatAttribute) numOfAASamples;
+               
+               pixelFormatAttrsWindow[i++] = NSOpenGLPFANoRecovery;
+       }
+       
        pixelFormatAttrsWindow[i] = (NSOpenGLPixelFormatAttribute) 0;
        
+       pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:pixelFormatAttrsWindow];
+       
+       
+       //Fall back to no multisampling if Antialiasing init failed
+       if (pixelFormat == nil) {
+               i=0;
+               pixelFormatAttrsWindow[i++] = NSOpenGLPFADoubleBuffer;
+               pixelFormatAttrsWindow[i++] = NSOpenGLPFAAccelerated;
+               //pixelFormatAttrsWindow[i++] = NSOpenGLPFAAllowOfflineRenderers,;   // Removed to allow 10.4 builds, and 2 GPUs rendering is not used anyway
+               
+               pixelFormatAttrsWindow[i++] = NSOpenGLPFADepthSize;
+               pixelFormatAttrsWindow[i++] = (NSOpenGLPixelFormatAttribute) 32;
+               
+               if (stereoVisual) pixelFormatAttrsWindow[i++] = NSOpenGLPFAStereo;
+               
+               pixelFormatAttrsWindow[i] = (NSOpenGLPixelFormatAttribute) 0;
+               
+               pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:pixelFormatAttrsWindow];
+               
+       }
+       
+       if (numOfAASamples>0) { //Set m_numOfAASamples to the actual value
+               GLint gli;
+               [pixelFormat getValues:&gli forAttribute:NSOpenGLPFASamples forVirtualScreen:0];
+               if (m_numOfAASamples != (GHOST_TUns16)gli) {
+                       m_numOfAASamples = (GHOST_TUns16)gli;
+                       printf("GHOST_Window could be created with anti-aliasing of only %i samples\n",m_numOfAASamples);
+               }
+       }
+               
 -      //Creates the OpenGL View inside the window
 -      m_openGLView = [[CocoaOpenGLView alloc] initWithFrame:rect
 -                                                                                               pixelFormat:pixelFormat];
 -      
 -      [pixelFormat release];
 -      
 -      m_openGLContext = [m_openGLView openGLContext]; //This context will be replaced by the proper one just after
 -      
 -      [m_window setContentView:m_openGLView];
 -      [m_window setInitialFirstResponder:m_openGLView];
 -      
 -      [m_window setReleasedWhenClosed:NO]; //To avoid bad pointer exception in case of user closing the window
 -      
 -      [m_window makeKeyAndOrderFront:nil];
 -      
 -      setDrawingContextType(type);
 -      updateDrawingContext();
 -      activateDrawingContext();
 -      
 -      m_tablet.Active = GHOST_kTabletModeNone;
 -      
 -      CocoaWindowDelegate *windowDelegate = [[CocoaWindowDelegate alloc] init];
 -      [windowDelegate setSystemAndWindowCocoa:systemCocoa windowCocoa:this];
 -      [m_window setDelegate:windowDelegate];
 -      
 -      [m_window setAcceptsMouseMovedEvents:YES];
 -      
 +      //Creates the OpenGL View inside the window\r
-       NSOpenGLPixelFormat *pixelFormat =\r
-       [[NSOpenGLPixelFormat alloc] initWithAttributes:pixelFormatAttrsWindow];\r
-       \r
 +      m_openGLView = [[CocoaOpenGLView alloc] initWithFrame:rect\r
 +                                                                                               pixelFormat:pixelFormat];\r
 +      \r
 +      [pixelFormat release];\r
 +      \r
 +      m_openGLContext = [m_openGLView openGLContext]; //This context will be replaced by the proper one just after\r
 +      \r
 +      [m_window setContentView:m_openGLView];\r
 +      [m_window setInitialFirstResponder:m_openGLView];\r
 +      \r
 +      [m_window setReleasedWhenClosed:NO]; //To avoid bad pointer exception in case of user closing the window\r
 +      \r
 +      [m_window makeKeyAndOrderFront:nil];\r
 +      \r
 +      setDrawingContextType(type);\r
 +      updateDrawingContext();\r
 +      activateDrawingContext();\r
 +      \r
 +      m_tablet.Active = GHOST_kTabletModeNone;\r
 +      \r
 +      CocoaWindowDelegate *windowDelegate = [[CocoaWindowDelegate alloc] init];\r
 +      [windowDelegate setSystemAndWindowCocoa:systemCocoa windowCocoa:this];\r
 +      [m_window setDelegate:windowDelegate];\r
 +      \r
 +      [m_window setAcceptsMouseMovedEvents:YES];\r
 +      \r
        [m_window registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType,
                                                                                  NSStringPboardType, NSTIFFPboardType, nil]];
                                                                                  
 -      if (state == GHOST_kWindowStateFullScreen)
 -              setState(GHOST_kWindowStateFullScreen);
 -              
 -      [pool drain];
 -}
 -
 -
 -GHOST_WindowCocoa::~GHOST_WindowCocoa()
 -{
 -      if (m_customCursor) delete m_customCursor;
 -
 -    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 -      [m_openGLView release];
 -      
 -      if (m_window) {
 -              [m_window close];
 -              [[m_window delegate] release];
 -              [m_window release];
 -              m_window = nil;
 -      }
 -      
 -      //Check for other blender opened windows and make the frontmost key
 -      NSArray *windowsList = [NSApp orderedWindows];
 -      if ([windowsList count]) {
 -              [[windowsList objectAtIndex:0] makeKeyAndOrderFront:nil];
 -      }
 -      [pool drain];
 -}
 -
 -#pragma mark accessors
 -
 -bool GHOST_WindowCocoa::getValid() const
 -{
 +      if (state == GHOST_kWindowStateFullScreen)\r
 +              setState(GHOST_kWindowStateFullScreen);\r
 +              \r
 +      [pool drain];\r
 +}\r
 +\r
 +\r
 +GHOST_WindowCocoa::~GHOST_WindowCocoa()\r
 +{\r
 +      if (m_customCursor) delete m_customCursor;\r
 +\r
 +    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];\r
 +      [m_openGLView release];\r
 +      \r
 +      if (m_window) {\r
 +              [m_window close];\r
 +              [[m_window delegate] release];\r
 +              [m_window release];\r
 +              m_window = nil;\r
 +      }\r
 +      \r
 +      //Check for other blender opened windows and make the frontmost key\r
 +      NSArray *windowsList = [NSApp orderedWindows];\r
 +      if ([windowsList count]) {\r
 +              [[windowsList objectAtIndex:0] makeKeyAndOrderFront:nil];\r
 +      }\r
 +      [pool drain];\r
 +}\r
 +\r
 +#pragma mark accessors\r
 +\r
 +bool GHOST_WindowCocoa::getValid() const\r
 +{\r
-     bool valid;\r
-     if (!m_fullScreen) {\r
-         valid = (m_window != 0); //&& ::IsValidWindowPtr(m_windowRef);\r
-     }\r
-     else {\r
-         valid = true;\r
-     }\r
-     return valid;\r
+       return (m_window != 0);
 -}
 -
 -
 -void GHOST_WindowCocoa::setTitle(const STR_String& title)
 -{
 -    GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setTitle(): window invalid")
 -      NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 -
 -      NSString *windowTitle = [[NSString alloc] initWithUTF8String:title];
 -      
 -      //Set associated file if applicable
 -      if ([windowTitle hasPrefix:@"Blender"])
 -      {
 -              NSRange fileStrRange;
 -              NSString *associatedFileName;
 -              int len;
 -              
 -              fileStrRange.location = [windowTitle rangeOfString:@"["].location+1;
 -              len = [windowTitle rangeOfString:@"]"].location - fileStrRange.location;
 -      
 -              if (len >0)
 -              {
 -                      fileStrRange.length = len;
 -                      associatedFileName = [windowTitle substringWithRange:fileStrRange];
 -                      @try {
 -                              [m_window setRepresentedFilename:associatedFileName];
 -                      }
 -                      @catch (NSException * e) {
 -                              printf("\nInvalid file path given in window title");
 -                      }
 -                      [m_window setTitle:[associatedFileName lastPathComponent]];
 -              }
 -              else {
 -                      [m_window setTitle:windowTitle];
 -                      [m_window setRepresentedFilename:@""];
 -              }
 -
 -      } else {
 -              [m_window setTitle:windowTitle];
 -              [m_window setRepresentedFilename:@""];
 -      }
 -
 -      
 -      [windowTitle release];
 -      [pool drain];
 -}
 -
 -
 -void GHOST_WindowCocoa::getTitle(STR_String& title) const
 -{
 -    GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getTitle(): window invalid")
 -
 -      NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 -
 -      NSString *windowTitle = [m_window title];
 -
 -      if (windowTitle != nil) {
 -              title = [windowTitle UTF8String];               
 -      }
 -      
 -      [pool drain];
 -}
 -
 -
 -void GHOST_WindowCocoa::getWindowBounds(GHOST_Rect& bounds) const
 -{
 -      NSRect rect;
 -      GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getWindowBounds(): window invalid")
 -
 -      NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 -      
 -      NSRect screenSize = [[m_window screen] visibleFrame];
 -
 -      rect = [m_window frame];
 -
 -      bounds.m_b = screenSize.size.height - (rect.origin.y -screenSize.origin.y);
 -      bounds.m_l = rect.origin.x -screenSize.origin.x;
 -      bounds.m_r = rect.origin.x-screenSize.origin.x + rect.size.width;
 -      bounds.m_t = screenSize.size.height - (rect.origin.y + rect.size.height -screenSize.origin.y);
 -      
 -      [pool drain];
 -}
 -
 -
 -void GHOST_WindowCocoa::getClientBounds(GHOST_Rect& bounds) const
 -{
 -      NSRect rect;
 -      GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getClientBounds(): window invalid")
 -      
 -      NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 -      
 -      if (!m_fullScreen)
 -      {
 -              NSRect screenSize = [[m_window screen] visibleFrame];
 -
 -              //Max window contents as screen size (excluding title bar...)
 -              NSRect contentRect = [CocoaWindow contentRectForFrameRect:screenSize
 -                                                                                                       styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask)];
 -
 -              rect = [m_window contentRectForFrameRect:[m_window frame]];
 -              
 -              bounds.m_b = contentRect.size.height - (rect.origin.y -contentRect.origin.y);
 -              bounds.m_l = rect.origin.x -contentRect.origin.x;
 -              bounds.m_r = rect.origin.x-contentRect.origin.x + rect.size.width;
 -              bounds.m_t = contentRect.size.height - (rect.origin.y + rect.size.height -contentRect.origin.y);
 -      }
 -      else {
 -              NSRect screenSize = [[m_window screen] frame];
 -              
 -              bounds.m_b = screenSize.origin.y + screenSize.size.height;
 -              bounds.m_l = screenSize.origin.x;
 -              bounds.m_r = screenSize.origin.x + screenSize.size.width;
 -              bounds.m_t = screenSize.origin.y;
 -      }
 -      [pool drain];
 -}
 -
 -
 -GHOST_TSuccess GHOST_WindowCocoa::setClientWidth(GHOST_TUns32 width)
 -{
 -      GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientWidth(): window invalid")
 -      GHOST_Rect cBnds, wBnds;
 -      getClientBounds(cBnds);
 -      if (((GHOST_TUns32)cBnds.getWidth()) != width) {
 -              NSSize size;
 -              size.width=width;
 -              size.height=cBnds.getHeight();
 -              [m_window setContentSize:size];
 -      }
 -      return GHOST_kSuccess;
 -}
 -
 -
 -GHOST_TSuccess GHOST_WindowCocoa::setClientHeight(GHOST_TUns32 height)
 -{
 -      GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientHeight(): window invalid")
 -      GHOST_Rect cBnds, wBnds;
 -      getClientBounds(cBnds);
 -      if (((GHOST_TUns32)cBnds.getHeight()) != height) {
 -              NSSize size;
 -              size.width=cBnds.getWidth();
 -              size.height=height;
 -              [m_window setContentSize:size];
 -      }
 -      return GHOST_kSuccess;
 -}
 -
 -
 -GHOST_TSuccess GHOST_WindowCocoa::setClientSize(GHOST_TUns32 width, GHOST_TUns32 height)
 -{
 -      GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientSize(): window invalid")
 -      GHOST_Rect cBnds, wBnds;
 -      getClientBounds(cBnds);
 -      if ((((GHOST_TUns32)cBnds.getWidth()) != width) ||
 -          (((GHOST_TUns32)cBnds.getHeight()) != height)) {
 -              NSSize size;
 -              size.width=width;
 -              size.height=height;
 -              [m_window setContentSize:size];
 -      }
 -      return GHOST_kSuccess;
 -}
 -
 -
 -GHOST_TWindowState GHOST_WindowCocoa::getState() const
 -{
 -      GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getState(): window invalid")
 -      NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 -      GHOST_TWindowState state;
 -      if (m_fullScreen) {
 -              state = GHOST_kWindowStateFullScreen;
 -      } 
 -      else if ([m_window isMiniaturized]) {
 -              state = GHOST_kWindowStateMinimized;
 -      }
 -      else if ([m_window isZoomed]) {
 -              state = GHOST_kWindowStateMaximized;
 -      }
 -      else {
 -              state = GHOST_kWindowStateNormal;
 -      }
 -      [pool drain];
 -      return state;
 -}
 -
 -
 -void GHOST_WindowCocoa::screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const
 -{
 -      GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::screenToClient(): window invalid")
 -      
 -      NSPoint screenCoord;
 -      NSPoint baseCoord;
 -      
 -      screenCoord.x = inX;
 -      screenCoord.y = inY;
 -      
 -      baseCoord = [m_window convertScreenToBase:screenCoord];
 -      
 -      outX = baseCoord.x;
 -      outY = baseCoord.y;
 -}
 -
 -
 -void GHOST_WindowCocoa::clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const
 -{
 -      GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::clientToScreen(): window invalid")
 -      
 -      NSPoint screenCoord;
 -      NSPoint baseCoord;
 -      
 -      baseCoord.x = inX;
 -      baseCoord.y = inY;
 -      
 -      screenCoord = [m_window convertBaseToScreen:baseCoord];
 -      
 -      outX = screenCoord.x;
 -      outY = screenCoord.y;
 -}
 -
 +}\r
 +\r
 +\r
 +void GHOST_WindowCocoa::setTitle(const STR_String& title)\r
 +{\r
 +    GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setTitle(): window invalid")\r
 +      NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];\r
 +\r
 +      NSString *windowTitle = [[NSString alloc] initWithUTF8String:title];\r
 +      \r
 +      //Set associated file if applicable\r
 +      if ([windowTitle hasPrefix:@"Blender"])\r
 +      {\r
 +              NSRange fileStrRange;\r
 +              NSString *associatedFileName;\r
 +              int len;\r
 +              \r
 +              fileStrRange.location = [windowTitle rangeOfString:@"["].location+1;\r
 +              len = [windowTitle rangeOfString:@"]"].location - fileStrRange.location;\r
 +      \r
 +              if (len >0)\r
 +              {\r
 +                      fileStrRange.length = len;\r
 +                      associatedFileName = [windowTitle substringWithRange:fileStrRange];\r
 +                      @try {\r
 +                              [m_window setRepresentedFilename:associatedFileName];\r
 +                      }\r
 +                      @catch (NSException * e) {\r
 +                              printf("\nInvalid file path given in window title");\r
 +                      }\r
 +                      [m_window setTitle:[associatedFileName lastPathComponent]];\r
 +              }\r
 +              else {\r
 +                      [m_window setTitle:windowTitle];\r
 +                      [m_window setRepresentedFilename:@""];\r
 +              }\r
 +\r
 +      } else {\r
 +              [m_window setTitle:windowTitle];\r
 +              [m_window setRepresentedFilename:@""];\r
 +      }\r
 +\r
 +      \r
 +      [windowTitle release];\r
 +      [pool drain];\r
 +}\r
 +\r
 +\r
 +void GHOST_WindowCocoa::getTitle(STR_String& title) const\r
 +{\r
 +    GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getTitle(): window invalid")\r
 +\r
 +      NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];\r
 +\r
 +      NSString *windowTitle = [m_window title];\r
 +\r
 +      if (windowTitle != nil) {\r
 +              title = [windowTitle UTF8String];               \r
 +      }\r
 +      \r
 +      [pool drain];\r
 +}\r
 +\r
 +\r
 +void GHOST_WindowCocoa::getWindowBounds(GHOST_Rect& bounds) const\r
 +{\r
 +      NSRect rect;\r
 +      GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getWindowBounds(): window invalid")\r
 +\r
 +      NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];\r
 +      \r
 +      NSRect screenSize = [[m_window screen] visibleFrame];\r
 +\r
 +      rect = [m_window frame];\r
 +\r
 +      bounds.m_b = screenSize.size.height - (rect.origin.y -screenSize.origin.y);\r
 +      bounds.m_l = rect.origin.x -screenSize.origin.x;\r
 +      bounds.m_r = rect.origin.x-screenSize.origin.x + rect.size.width;\r
 +      bounds.m_t = screenSize.size.height - (rect.origin.y + rect.size.height -screenSize.origin.y);\r
 +      \r
 +      [pool drain];\r
 +}\r
 +\r
 +\r
 +void GHOST_WindowCocoa::getClientBounds(GHOST_Rect& bounds) const\r
 +{\r
 +      NSRect rect;\r
 +      GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getClientBounds(): window invalid")\r
 +      \r
 +      NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];\r
 +      \r
 +      if (!m_fullScreen)\r
 +      {\r
 +              NSRect screenSize = [[m_window screen] visibleFrame];\r
 +\r
 +              //Max window contents as screen size (excluding title bar...)\r
 +              NSRect contentRect = [CocoaWindow contentRectForFrameRect:screenSize\r
 +                                                                                                       styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask)];\r
 +\r
 +              rect = [m_window contentRectForFrameRect:[m_window frame]];\r
 +              \r
 +              bounds.m_b = contentRect.size.height - (rect.origin.y -contentRect.origin.y);\r
 +              bounds.m_l = rect.origin.x -contentRect.origin.x;\r
 +              bounds.m_r = rect.origin.x-contentRect.origin.x + rect.size.width;\r
 +              bounds.m_t = contentRect.size.height - (rect.origin.y + rect.size.height -contentRect.origin.y);\r
 +      }\r
 +      else {\r
 +              NSRect screenSize = [[m_window screen] frame];\r
 +              \r
 +              bounds.m_b = screenSize.origin.y + screenSize.size.height;\r
 +              bounds.m_l = screenSize.origin.x;\r
 +              bounds.m_r = screenSize.origin.x + screenSize.size.width;\r
 +              bounds.m_t = screenSize.origin.y;\r
 +      }\r
 +      [pool drain];\r
 +}\r
 +\r
 +\r
 +GHOST_TSuccess GHOST_WindowCocoa::setClientWidth(GHOST_TUns32 width)\r
 +{\r
 +      GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientWidth(): window invalid")\r
 +      GHOST_Rect cBnds, wBnds;\r
 +      getClientBounds(cBnds);\r
 +      if (((GHOST_TUns32)cBnds.getWidth()) != width) {\r
 +              NSSize size;\r
 +              size.width=width;\r
 +              size.height=cBnds.getHeight();\r
 +              [m_window setContentSize:size];\r
 +      }\r
 +      return GHOST_kSuccess;\r
 +}\r
 +\r
 +\r
 +GHOST_TSuccess GHOST_WindowCocoa::setClientHeight(GHOST_TUns32 height)\r
 +{\r
 +      GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientHeight(): window invalid")\r
 +      GHOST_Rect cBnds, wBnds;\r
 +      getClientBounds(cBnds);\r
 +      if (((GHOST_TUns32)cBnds.getHeight()) != height) {\r
 +              NSSize size;\r
 +              size.width=cBnds.getWidth();\r
 +              size.height=height;\r
 +              [m_window setContentSize:size];\r
 +      }\r
 +      return GHOST_kSuccess;\r
 +}\r
 +\r
 +\r
 +GHOST_TSuccess GHOST_WindowCocoa::setClientSize(GHOST_TUns32 width, GHOST_TUns32 height)\r
 +{\r
 +      GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientSize(): window invalid")\r
 +      GHOST_Rect cBnds, wBnds;\r
 +      getClientBounds(cBnds);\r
 +      if ((((GHOST_TUns32)cBnds.getWidth()) != width) ||\r
 +          (((GHOST_TUns32)cBnds.getHeight()) != height)) {\r
 +              NSSize size;\r
 +              size.width=width;\r
 +              size.height=height;\r
 +              [m_window setContentSize:size];\r
 +      }\r
 +      return GHOST_kSuccess;\r
 +}\r
 +\r
 +\r
 +GHOST_TWindowState GHOST_WindowCocoa::getState() const\r
 +{\r
 +      GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getState(): window invalid")\r
 +      NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];\r
 +      GHOST_TWindowState state;\r
 +      if (m_fullScreen) {\r
 +              state = GHOST_kWindowStateFullScreen;\r
 +      } \r
 +      else if ([m_window isMiniaturized]) {\r
 +              state = GHOST_kWindowStateMinimized;\r
 +      }\r
 +      else if ([m_window isZoomed]) {\r
 +              state = GHOST_kWindowStateMaximized;\r
 +      }\r
 +      else {\r
 +              state = GHOST_kWindowStateNormal;\r
 +      }\r
 +      [pool drain];\r
 +      return state;\r
 +}\r
 +\r
 +\r
 +void GHOST_WindowCocoa::screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const\r
 +{\r
 +      GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::screenToClient(): window invalid")\r
 +      \r
 +      NSPoint screenCoord;\r
 +      NSPoint baseCoord;\r
 +      \r
 +      screenCoord.x = inX;\r
 +      screenCoord.y = inY;\r
 +      \r
 +      baseCoord = [m_window convertScreenToBase:screenCoord];\r
 +      \r
 +      outX = baseCoord.x;\r
 +      outY = baseCoord.y;\r
 +}\r
 +\r
 +\r
 +void GHOST_WindowCocoa::clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const\r
 +{\r
 +      GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::clientToScreen(): window invalid")\r
 +      \r
 +      NSPoint screenCoord;\r
 +      NSPoint baseCoord;\r
 +      \r
 +      baseCoord.x = inX;\r
 +      baseCoord.y = inY;\r
 +      \r
 +      screenCoord = [m_window convertBaseToScreen:baseCoord];\r
 +      \r
 +      outX = screenCoord.x;\r
 +      outY = screenCoord.y;\r
 +}\r
 +\r
  
  NSScreen* GHOST_WindowCocoa::getScreen()
  {
@@@ -802,63 -837,66 +837,66 @@@ GHOST_TSuccess GHOST_WindowCocoa::setOr
                if ([windowsList count]) {
                        [[windowsList objectAtIndex:0] makeKeyAndOrderFront:nil];
                }
 -    }
 -    return GHOST_kSuccess;
 -}
 -
 -#pragma mark Drawing context
 -
 -/*#define  WAIT_FOR_VSYNC 1*/
 -
 -GHOST_TSuccess GHOST_WindowCocoa::swapBuffers()
 -{
 -    if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) {
 -        if (m_openGLContext != nil) {
 -                      NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 -                      [m_openGLContext flushBuffer];
 -                      [pool drain];
 -            return GHOST_kSuccess;
 -        }
 -    }
 -    return GHOST_kFailure;
 -}
 -
 -GHOST_TSuccess GHOST_WindowCocoa::updateDrawingContext()
 -{
 -      if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) {
 -              if (m_openGLContext != nil) {
 -                      NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 -                      [m_openGLContext update];
 -                      [pool drain];
 -                      return GHOST_kSuccess;
 -              }
 -      }
 -      return GHOST_kFailure;
 -}
 -
 -GHOST_TSuccess GHOST_WindowCocoa::activateDrawingContext()
 -{
 -      if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) {
 -              if (m_openGLContext != nil) {
 -                      NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 -                      [m_openGLContext makeCurrentContext];
 +    }\r
 +    return GHOST_kSuccess;\r
 +}\r
 +\r
 +#pragma mark Drawing context\r
 +\r
 +/*#define  WAIT_FOR_VSYNC 1*/\r
 +\r
 +GHOST_TSuccess GHOST_WindowCocoa::swapBuffers()\r
 +{\r
 +    if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) {\r
 +        if (m_openGLContext != nil) {\r
 +                      NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];\r
 +                      [m_openGLContext flushBuffer];\r
 +                      [pool drain];\r
 +            return GHOST_kSuccess;\r
 +        }\r
 +    }\r
 +    return GHOST_kFailure;\r
 +}\r
 +\r
 +GHOST_TSuccess GHOST_WindowCocoa::updateDrawingContext()\r
 +{\r
 +      if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) {\r
 +              if (m_openGLContext != nil) {\r
 +                      NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];\r
 +                      [m_openGLContext update];\r
 +                      [pool drain];\r
 +                      return GHOST_kSuccess;\r
 +              }\r
 +      }\r
 +      return GHOST_kFailure;\r
 +}\r
 +\r
 +GHOST_TSuccess GHOST_WindowCocoa::activateDrawingContext()\r
 +{\r
 +      if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) {\r
 +              if (m_openGLContext != nil) {\r
 +                      NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];\r
 +                      [m_openGLContext makeCurrentContext];\r
+                       
+                       // Disable AA by default
+                       if (m_numOfAASamples > 0) glDisable(GL_MULTISAMPLE_ARB);
 -                      [pool drain];
 -                      return GHOST_kSuccess;
 -              }
 -      }
 -      return GHOST_kFailure;
 -}
 -
 -
 -GHOST_TSuccess GHOST_WindowCocoa::installDrawingContext(GHOST_TDrawingContextType type)
 -{
 -      GHOST_TSuccess success = GHOST_kFailure;
 -      
 -      NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 -      
 -      NSOpenGLPixelFormat *pixelFormat;
 -      NSOpenGLContext *tmpOpenGLContext;
 -      
 +                      [pool drain];\r
 +                      return GHOST_kSuccess;\r
 +              }\r
 +      }\r
 +      return GHOST_kFailure;\r
 +}\r
 +\r
 +\r
 +GHOST_TSuccess GHOST_WindowCocoa::installDrawingContext(GHOST_TDrawingContextType type)\r
 +{\r
 +      GHOST_TSuccess success = GHOST_kFailure;\r
 +      \r
 +      NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];\r
 +      \r
 +      NSOpenGLPixelFormat *pixelFormat;\r
 +      NSOpenGLContext *tmpOpenGLContext;\r
 +      \r
        /***** Multithreaded opengl code : uncomment for enabling
        CGLContextObj cglCtx;
        */
index c97e3d2798dd57260768cf1ba8192031b329ff2e,01f863a4c2ec7da962a94a1851cf3dbbf479c6d5..f1d04358d9cfe5760bf36fe846d6a1a3fcdbe161
@@@ -172,6 -78,12 +172,12 @@@ typedef struct DMGridAdjacency 
        int rotation[4];
  } DMGridAdjacency;
  
 -      DM_TYPE_EDITMESH,
+ typedef enum DerivedMeshType {
+       DM_TYPE_CDDM,
++      DM_TYPE_EDITBMESH,
+       DM_TYPE_CCGDM
+ } DerivedMeshType;
  typedef struct DerivedMesh DerivedMesh;
  struct DerivedMesh {
        /* Private DerivedMesh data, only for internal DerivedMesh use */
        int deformedOnly; /* set by modifier stack if only deformed from original */
        BVHCache bvhCache;
        struct GPUDrawObject *drawObject;
+       DerivedMeshType type;
  
        /* Misc. Queries */
 +      
 +      /*face iterator.  initializes iter.*/
 +      DMFaceIter *(*newFaceIter)(DerivedMesh *dm);
 +
 +      /*recalculates mesh tesselation*/
 +      void (*recalcTesselation)(DerivedMesh *dm);
  
        /* Also called in Editmode */
        int (*getNumVerts)(DerivedMesh *dm);
@@@ -441,15 -336,15 +448,16 @@@ void DM_init_funcs(DerivedMesh *dm)
   * of vertices, edges and faces (doesn't allocate memory for them, just
   * sets up the custom data layers)
   */
- void DM_init(DerivedMesh *dm, int numVerts, int numEdges, int numFaces,
-            int numLoops, int numPolys);
 -void DM_init(DerivedMesh *dm, DerivedMeshType type,
 -             int numVerts, int numEdges, int numFaces);
++void DM_init(DerivedMesh *dm, DerivedMeshType type, int numVerts, int numEdges, 
++           int numFaces, int numLoops, int numPolys);
  
  /* utility function to initialise a DerivedMesh for the desired number
   * of vertices, edges and faces, with a layer setup copied from source
   */
  void DM_from_template(DerivedMesh *dm, DerivedMesh *source,
 -                      int numVerts, int numEdges, int numFaces);
+                       DerivedMeshType type,
 +                      int numVerts, int numEdges, int numFaces,
 +                    int numLoops, int numPolys);
  
  /* utility function to release a DerivedMesh's layers
   * returns 1 if DerivedMesh has to be released by the backend, 0 otherwise
Simple merge
index 1876493f5e2a83bce9bdfe25767ce4e52c31c694,3ffa32c700d9a52d136ee6e9994b55e01594b497..7973c2cd89d57e605a2a717aae15992e6a448d55
@@@ -217,9 -184,10 +217,10 @@@ void DM_init_funcs(DerivedMesh *dm
        bvhcache_init(&dm->bvhCache);
  }
  
- void DM_init(DerivedMesh *dm, int numVerts, int numEdges, int numFaces,
-            int numLoops, int numPoly)
 -void DM_init(DerivedMesh *dm, DerivedMeshType type,
 -             int numVerts, int numEdges, int numFaces)
++void DM_init(DerivedMesh *dm, DerivedMeshType type, int numVerts, int numEdges,
++           int numFaces, int numLoops, int numPoly)
  {
+       dm->type = type;
        dm->numVertData = numVerts;
        dm->numEdgeData = numEdges;
        dm->numFaceData = numFaces;
        dm->needsFree = 1;
  }
  
- void DM_from_template(DerivedMesh *dm, DerivedMesh *source,
+ void DM_from_template(DerivedMesh *dm, DerivedMesh *source, DerivedMeshType type,
 -                      int numVerts, int numEdges, int numFaces)
 +                      int numVerts, int numEdges, int numFaces,
 +                    int numLoops, int numPolys)
  {
        CustomData_copy(&source->vertData, &dm->vertData, CD_MASK_DERIVEDMESH,
                        CD_CALLOC, numVerts);
                        CD_CALLOC, numEdges);
        CustomData_copy(&source->faceData, &dm->faceData, CD_MASK_DERIVEDMESH,
                        CD_CALLOC, numFaces);
 +      CustomData_copy(&source->loopData, &dm->loopData, CD_MASK_DERIVEDMESH,
 +                      CD_CALLOC, numLoops);
 +      CustomData_copy(&source->polyData, &dm->polyData, CD_MASK_DERIVEDMESH,
 +                      CD_CALLOC, numPolys);
  
+       dm->type = type;
        dm->numVertData = numVerts;
        dm->numEdgeData = numEdges;
        dm->numFaceData = numFaces;
@@@ -513,8 -352,11 +521,11 @@@ void *DM_get_edge_data_layer(DerivedMes
        return CustomData_get_layer(&dm->edgeData, type);
  }
  
 -void *DM_get_face_data_layer(DerivedMesh *dm, int type)
 +void *DM_get_tessface_data_layer(DerivedMesh *dm, int type)
  {
 -              return dm->getFaceArray(dm);
+       if(type == CD_MFACE)
++              return dm->getTessFaceArray(dm);
        return CustomData_get_layer(&dm->faceData, type);
  }
  
@@@ -726,59 -523,17 +737,17 @@@ static void emDM_drawMappedEdges(void *
                }
                glEnd();
        } else {
-               GPUBuffer *buffer = NULL;
-               float *varray;
-               if(GPU_buffer_legacy(dm)==FALSE)
-                       buffer = GPU_buffer_alloc( sizeof(float)*3*2*emdm->em->totedge, 0 );
-               if( buffer != 0 && (varray = GPU_buffer_lock_stream( buffer )) ) {
-                       int prevdraw = 0;
-                       int numedges = 0;
-                       int draw = 0;
-                       int datatype[] = { GPU_BUFFER_INTER_V3F, GPU_BUFFER_INTER_END };
-                       GPU_buffer_unlock( buffer );
-                       GPU_interleaved_setup( buffer, datatype );
-                       varray = GPU_buffer_lock_stream( buffer );
-                       for(i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next) {
-                               if(!setDrawOptions || setDrawOptions(userData, i)) {
-                                       draw = 1;
-                               } else {
-                                       draw = 0;
-                               }
-                               if( prevdraw != draw && prevdraw != 0 && numedges > 0) {
-                                       GPU_buffer_unlock( buffer );
-                                       glDrawArrays(GL_LINES,0,numedges*2);
-                                       varray = GPU_buffer_lock_stream( buffer );
-                                       numedges = 0;
-                               }
-                               if( draw != 0 ) {
-                                       VECCOPY(&varray[numedges*6],eed->v1->co);
-                                       VECCOPY(&varray[numedges*6+3],eed->v2->co);
-                                       numedges++;
-                               }
-                               prevdraw = draw;
-                       }
-                       GPU_buffer_unlock( buffer );
-                       if( prevdraw != 0 && numedges > 0) {
-                               glDrawArrays(GL_LINES,0,numedges*2);
-                       }
-                       GPU_buffer_unbind();
-               } else {
-                       glBegin(GL_LINES);
-                       for(i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next) {
-                               if(!setDrawOptions || setDrawOptions(userData, i)) {
-                                       glVertex3fv(eed->v1->co);
-                                       glVertex3fv(eed->v2->co);
-                               }
+               glBegin(GL_LINES);
+               for(i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next) {
+                       if(!setDrawOptions || setDrawOptions(userData, i)) {
+                               glVertex3fv(eed->v1->co);
+                               glVertex3fv(eed->v2->co);
                        }
-                       glEnd();
                }
-               if( buffer != 0 )
-                       GPU_buffer_free( buffer, 0 );
+               glEnd();
        }
  }
 -static void emDM_drawEdges(DerivedMesh *dm, int drawLooseEdges)
 +static void emDM_drawEdges(void *dm, int drawLooseEdges)
  {
        emDM_drawMappedEdges(dm, NULL, NULL);
  }
@@@ -1662,11 -1323,10 +1537,12 @@@ static void emDM_release(void *dm
  static DerivedMesh *getEditMeshDerivedMesh(EditMesh *em, Object *ob,
                                             float (*vertexCos)[3])
  {
++#if 0
        EditMeshDerivedMesh *emdm = MEM_callocN(sizeof(*emdm), "emdm");
  
-       DM_init(&emdm->dm, BLI_countlist(&em->verts),
+       DM_init(&emdm->dm, DM_TYPE_EDITMESH, BLI_countlist(&em->verts),
 -                       BLI_countlist(&em->edges), BLI_countlist(&em->faces));
 +                       BLI_countlist(&em->edges), BLI_countlist(&em->faces),
 +                       0, 0);
  
        emdm->dm.getMinMax = emDM_getMinMax;
  
        }
  
        return (DerivedMesh*) emdm;
++#endif
++      return NULL;
  }
  
  /***/
index 9d50be3af53863588b655b5948496d98b41acd16,507fc520a85fb3ae43f8d577bbf4ef1883747cd5..f580bbbd5267acfd1f0dcc146f721687bb264ded
@@@ -67,8 -73,8 +73,9 @@@
  #include "BKE_mesh.h"
  #include "BKE_object.h"
  #include "BKE_particle.h"
+ #include "BKE_scene.h"
  #include "BKE_utildefines.h"
 +#include "BKE_tessmesh.h"
  
  #ifdef HAVE_CONFIG_H
  #include <config.h>
index 9d47425fcd469abe96e377301178249fbe963596,e9a1021a203516bc07ca2a9f7243c907acc99a85..ad70539535464a5b861f3e95d188efd00991b63a
@@@ -1457,7 -1406,7 +1459,7 @@@ DerivedMesh *CDDM_new(int numVerts, in
        CDDerivedMesh *cddm = cdDM_create("CDDM_new dm");
        DerivedMesh *dm = &cddm->dm;
  
-       DM_init(dm, numVerts, numEdges, numFaces, numLoops, numPolys);
 -      DM_init(dm, DM_TYPE_CDDM, numVerts, numEdges, numFaces);
++      DM_init(dm, DM_TYPE_CDDM, numVerts, numEdges, numFaces, numLoops, numPolys);
  
        CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts);
        CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
@@@ -1488,8 -1432,7 +1490,8 @@@ DerivedMesh *CDDM_from_mesh(Mesh *mesh
  
        /* this does a referenced copy, with an exception for fluidsim */
  
-       DM_init(dm, mesh->totvert, mesh->totedge, mesh->totface,
 -      DM_init(dm, DM_TYPE_CDDM, mesh->totvert, mesh->totedge, mesh->totface);
++      DM_init(dm, DM_TYPE_CDDM, mesh->totvert, mesh->totedge, mesh->totface,
 +                  mesh->totloop, mesh->totpoly);
  
        dm->deformedOnly = 1;
  
@@@ -1954,11 -1562,10 +1956,11 @@@ DerivedMesh *CDDM_copy(DerivedMesh *sou
        /* ensure these are created if they are made on demand */
        source->getVertDataArray(source, CD_ORIGINDEX);
        source->getEdgeDataArray(source, CD_ORIGINDEX);
 -      source->getFaceDataArray(source, CD_ORIGINDEX);
 +      source->getTessFaceDataArray(source, CD_ORIGINDEX);
  
        /* this initializes dm, and copies all non mvert/medge/mface layers */
-       DM_from_template(dm, source, numVerts, numEdges, numFaces,
 -      DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces);
++      DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces,
 +              numLoops, numPolys);
        dm->deformedOnly = source->deformedOnly;
  
        CustomData_copy_data(&source->vertData, &dm->vertData, 0, 0, numVerts);
@@@ -1993,7 -1591,7 +1995,7 @@@ DerivedMesh *CDDM_from_template(Derived
        DerivedMesh *dm = &cddm->dm;
  
        /* this does a copy of all non mvert/medge/mface layers */
-       DM_from_template(dm, source, numVerts, numEdges, numFaces, numLoops, numPolys);
 -      DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces);
++      DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces, numLoops, numPolys);
  
        /* now add mvert/medge/mface layers */
        CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts);
index b23322299b55e9743e0b8542c2071b434ef90f10,0000000000000000000000000000000000000000..4f10edf242ef70c21d34e2dea189ad8d19711a1a
mode 100644,000000..100644
--- /dev/null
@@@ -1,1694 -1,0 +1,1694 @@@
-       DM_init((DerivedMesh*)bmdm, em->bm->totvert, em->bm->totedge, em->tottri,
-                em->bm->totloop, em->bm->totface);
 +/**
 + * $Id: editderivedbmesh.c 18571 2009-01-19 06:04:57Z joeedh $
 + *
 + * ***** 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 Tbmple Place - Suite 330, Boston, MA  02111-1307, USA.
 + *
 + * The Original Code is Copyright (C) 2005 Blender Foundation.
 + * All rights reserved.
 + *
 + * The Original Code is: all of this file.
 + *
 + * Contributor(s): none yet.
 + *
 + * ***** END GPL LICENSE BLOCK *****
 + */
 +
 +#include <string.h>
 +
 +#ifdef HAVE_CONFIG_H
 +#include <config.h>
 +#endif
 +
 +#include "PIL_time.h"
 +
 +#include "MEM_guardedalloc.h"
 +
 +#include "DNA_effect_types.h"
 +#include "DNA_mesh_types.h"
 +#include "DNA_key_types.h"
 +#include "DNA_meshdata_types.h"
 +#include "DNA_modifier_types.h"
 +#include "DNA_object_types.h"
 +#include "DNA_object_force.h"
 +#include "DNA_object_fluidsim.h" // N_T
 +#include "DNA_scene_types.h" // N_T
 +#include "DNA_texture_types.h"
 +#include "DNA_view3d_types.h"
 +#include "DNA_screen_types.h"
 +#include "DNA_space_types.h"
 +#include "DNA_particle_types.h"
 +
 +#include "BLI_math.h"
 +#include "BLI_blenlib.h"
 +#include "BLI_editVert.h"
 +#include "BLI_edgehash.h"
 +#include "BLI_linklist.h"
 +#include "BLI_memarena.h"
 +#include "BLI_scanfill.h"
 +#include "BLI_ghash.h"
 +#include "BLI_array.h"
 +
 +#include "BKE_cdderivedmesh.h"
 +#include "BKE_customdata.h"
 +#include "BKE_DerivedMesh.h"
 +#include "BKE_deform.h"
 +#include "BKE_displist.h"
 +#include "BKE_effect.h"
 +#include "BKE_fluidsim.h"
 +#include "BKE_global.h"
 +#include "BKE_key.h"
 +#include "BKE_material.h"
 +#include "BKE_modifier.h"
 +#include "BKE_mesh.h"
 +#include "BKE_object.h"
 +#include "BKE_subsurf.h"
 +#include "BKE_texture.h"
 +#include "BKE_utildefines.h"
 +#include "BKE_particle.h"
 +#include "BKE_tessmesh.h"
 +
 +#include "BLO_sys_types.h" // for intptr_t support
 +
 +#include "BIF_gl.h"
 +#include "BIF_glutil.h"
 +
 +#include "GPU_draw.h"
 +#include "GPU_extensions.h"
 +#include "GPU_material.h"
 +
 +#include "bmesh.h"
 +
 +BMEditMesh *BMEdit_Create(BMesh *bm)
 +{
 +      BMEditMesh *tm = MEM_callocN(sizeof(BMEditMesh), "tm");
 +      
 +      tm->bm = bm;
 +
 +      BMEdit_RecalcTesselation(tm);
 +
 +      return tm;
 +}
 +
 +BMEditMesh *BMEdit_Copy(BMEditMesh *tm)
 +{
 +      BMEditMesh *tm2 = MEM_callocN(sizeof(BMEditMesh), "tm2");
 +      *tm2 = *tm;
 +      
 +      tm2->derivedCage = tm2->derivedFinal = NULL;
 +      
 +      tm2->looptris = NULL;
 +      tm2->bm = BM_Copy_Mesh(tm->bm);
 +      BMEdit_RecalcTesselation(tm2);
 +
 +      tm2->vert_index = NULL;
 +      tm2->edge_index = NULL;
 +      tm2->face_index = NULL;
 +
 +      return tm2;
 +}
 +
 +static void BMEdit_RecalcTesselation_intern(BMEditMesh *tm)
 +{
 +      BMesh *bm = tm->bm;
 +      BMLoop **looptris = NULL;
 +      BLI_array_declare(looptris);
 +      BMIter iter, liter;
 +      BMFace *f;
 +      BMLoop *l;
 +      int i = 0, j, a, b;
 +      
 +      if (tm->looptris) MEM_freeN(tm->looptris);
 +
 +#if 0 //simple quad/triangle code for performance testing purposes
 +      looptris = MEM_callocN(sizeof(void*)*bm->totface*8, "looptris");
 +
 +      f = BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL);
 +      for ( ; f; f=BMIter_Step(&iter)) {
 +              EditVert *v, *lastv=NULL, *firstv=NULL;
 +              EditEdge *e;
 +              EditFace *efa;
 +
 +              /*don't consider two-edged faces*/
 +              if (f->len < 3) continue;
 +              
 +              //BLI_array_growone(looptris);
 +              //BLI_array_growone(looptris);
 +              //BLI_array_growone(looptris);
 +
 +              looptris[i*3] = f->loopbase;
 +              looptris[i*3+1] = f->loopbase->head.next;
 +              looptris[i*3+2] = f->loopbase->head.next->next;
 +              i++;
 +
 +              if (f->len > 3) {
 +                      //BLI_array_growone(looptris);
 +                      //BLI_array_growone(looptris);
 +                      //BLI_array_growone(looptris);
 +
 +                      looptris[i*3] = f->loopbase;
 +                      looptris[i*3+1] = f->loopbase->head.next->next;
 +                      looptris[i*3+2] = f->loopbase->head.next->next->next;
 +                      i++;
 +              }
 +
 +      }
 +
 +      tm->tottri = i;
 +      tm->looptris = looptris;
 +      return;
 +#endif
 +
 +      f = BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL);
 +      for ( ; f; f=BMIter_Step(&iter)) {
 +              EditVert *v, *lastv=NULL, *firstv=NULL;
 +              EditEdge *e;
 +              EditFace *efa;
 +
 +              /*don't consider two-edged faces*/
 +              if (f->len < 3) continue;
 +              
 +              /*scanfill time*/
 +              l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, f);
 +              for (j=0; l; l=BMIter_Step(&liter), j++) {
 +                      /*mark order*/
 +                      l->head.eflag2 = j;
 +
 +                      v = BLI_addfillvert(l->v->co);
 +                      v->tmp.p = l;
 +                      
 +                      if (lastv) {
 +                              e = BLI_addfilledge(lastv, v);
 +                      }
 +
 +                      lastv = v;
 +                      if (firstv==NULL) firstv = v;
 +              }
 +
 +              /*complete the loop*/
 +              BLI_addfilledge(firstv, v);
 +
 +              BLI_edgefill(0, 0);
 +              
 +              for (efa = fillfacebase.first; efa; efa=efa->next) {
 +                      BMLoop *l1, *l2, *l3;
 +
 +                      BLI_array_growone(looptris);
 +                      BLI_array_growone(looptris);
 +                      BLI_array_growone(looptris);
 +                      
 +                      looptris[i*3] = l1 = efa->v1->tmp.p;
 +                      looptris[i*3+1] = l2 = efa->v2->tmp.p;
 +                      looptris[i*3+2] = l3 = efa->v3->tmp.p;
 +                      
 +                      if (l1->head.eflag2 > l2->head.eflag2) {
 +                              SWAP(BMLoop*, l1, l2);
 +                      }
 +                      if (l2->head.eflag2 > l3->head.eflag2) {
 +                              SWAP(BMLoop*, l2, l3);
 +                      }
 +                      if (l1->head.eflag2 > l2->head.eflag2) {
 +                              SWAP(BMLoop*, l1, l2);
 +                      }
 +                      
 +                      looptris[i*3] = l1;
 +                      looptris[i*3+1] = l2;
 +                      looptris[i*3+2] = l3;
 +
 +                      i += 1;
 +              }
 +
 +              BLI_end_edgefill();
 +      }
 +
 +      tm->tottri = i;
 +      tm->looptris = looptris;
 +}
 +
 +void BMEdit_RecalcTesselation(BMEditMesh *tm)
 +{
 +      BMEdit_RecalcTesselation_intern(tm);
 +
 +      if (tm->derivedFinal && tm->derivedFinal == tm->derivedCage) {
 +              if (tm->derivedFinal->recalcTesselation) 
 +                      tm->derivedFinal->recalcTesselation(tm->derivedFinal);
 +      } else if (tm->derivedFinal) {
 +              if (tm->derivedCage->recalcTesselation) 
 +                      tm->derivedCage->recalcTesselation(tm->derivedCage);
 +              if (tm->derivedFinal->recalcTesselation) 
 +                      tm->derivedFinal->recalcTesselation(tm->derivedFinal);
 +      }
 +}
 +
 +void BMEdit_UpdateLinkedCustomData(BMEditMesh *em)
 +{
 +      BMesh *bm = em->bm;
 +      int act;
 +
 +      if (CustomData_has_layer(&bm->pdata, CD_MTEXPOLY)) {
 +              act = CustomData_get_active_layer(&bm->pdata, CD_MTEXPOLY);
 +              CustomData_set_layer_active(&bm->ldata, CD_MLOOPUV, act);
 +
 +              act = CustomData_get_render_layer(&bm->pdata, CD_MTEXPOLY);
 +              CustomData_set_layer_render(&bm->ldata, CD_MLOOPUV, act);
 +
 +              act = CustomData_get_clone_layer(&bm->pdata, CD_MTEXPOLY);
 +              CustomData_set_layer_clone(&bm->ldata, CD_MLOOPUV, act);
 +
 +              act = CustomData_get_stencil_layer(&bm->pdata, CD_MTEXPOLY);
 +              CustomData_set_layer_stencil(&bm->ldata, CD_MLOOPUV, act);
 +      }
 +}
 +
 +/*does not free the BMEditMesh struct itself*/
 +void BMEdit_Free(BMEditMesh *em)
 +{
 +      if(em->derivedFinal) {
 +              if (em->derivedFinal!=em->derivedCage) {
 +                      em->derivedFinal->needsFree= 1;
 +                      em->derivedFinal->release(em->derivedFinal);
 +              }
 +              em->derivedFinal= NULL;
 +      }
 +      if(em->derivedCage) {
 +              em->derivedCage->needsFree= 1;
 +              em->derivedCage->release(em->derivedCage);
 +              em->derivedCage= NULL;
 +      }
 +
 +      em->retopo_paint_data= NULL;
 +
 +      if (em->looptris) MEM_freeN(em->looptris);
 +
 +      if (em->vert_index) MEM_freeN(em->vert_index);
 +      if (em->edge_index) MEM_freeN(em->edge_index);
 +      if (em->face_index) MEM_freeN(em->face_index);
 +
 +      BM_Free_Mesh(em->bm);
 +}
 +
 +
 +/*
 +ok, basic design:
 +
 +the bmesh derivedmesh exposes the mesh as triangles.  it stores pointers
 +to three loops per triangle.  the derivedmesh stores a cache of tesselations
 +for each face.  this cache will smartly update as needed (though at first
 +it'll simply be more brute force).  keeping track of face/edge counts may
 +be a small problbm.
 +
 +this won't be the most efficient thing, considering that internal edges and
 +faces of tesselations are exposed.  looking up an edge by index in particular
 +is likely to be a little slow.
 +*/
 +
 +typedef struct EditDerivedBMesh {
 +      DerivedMesh dm;
 +
 +      Object *ob;
 +      BMEditMesh *tc;
 +
 +      float (*vertexCos)[3];
 +      float (*vertexNos)[3];
 +      float (*faceNos)[3];
 +
 +      /*lookup caches; these are rebuilt on dm->RecalcTesselation()
 +        (or when the derivedmesh is created, of course)*/
 +      GHash *vhash, *ehash, *fhash;
 +      BMVert **vtable;
 +      BMEdge **etable;
 +      BMFace **ftable;
 +
 +      /*private variables, for number of verts/edges/faces
 +        within the above hash/table members*/
 +      int tv, te, tf;
 +
 +      /*customdata layout of the tesselated faces*/
 +      CustomData tessface_layout;
 +} EditDerivedBMesh;
 +
 +static void bmdm_recalc_lookups(EditDerivedBMesh *bmdm)
 +{
 +      BMIter iter;
 +      BMHeader *h;
 +      int a, i, iters[3] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, BM_FACES_OF_MESH};
 +      
 +      bmdm->tv = bmdm->tc->bm->totvert;
 +      bmdm->te = bmdm->tc->bm->totedge;
 +      bmdm->tf = bmdm->tc->bm->totface;
 +
 +      if (bmdm->vhash) BLI_ghash_free(bmdm->vhash, NULL, NULL);
 +      if (bmdm->ehash) BLI_ghash_free(bmdm->ehash, NULL, NULL);
 +      if (bmdm->fhash) BLI_ghash_free(bmdm->fhash, NULL, NULL);
 +
 +      bmdm->vhash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
 +      bmdm->ehash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
 +      bmdm->fhash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
 +      
 +      if (bmdm->vtable) MEM_freeN(bmdm->vtable);
 +      if (bmdm->etable) MEM_freeN(bmdm->etable);
 +      if (bmdm->ftable) MEM_freeN(bmdm->ftable);
 +      
 +      if (bmdm->tc->bm->totvert)
 +              bmdm->vtable = MEM_mallocN(sizeof(void**)*bmdm->tc->bm->totvert, "bmdm->vtable");
 +      else bmdm->vtable = NULL;
 +
 +      if (bmdm->tc->bm->totedge)
 +              bmdm->etable = MEM_mallocN(sizeof(void**)*bmdm->tc->bm->totedge, "bmdm->etable");
 +      else bmdm->etable = NULL;
 +      
 +      if (bmdm->tc->bm->totface)
 +              bmdm->ftable = MEM_mallocN(sizeof(void**)*bmdm->tc->bm->totface, "bmdm->ftable");
 +      else bmdm->ftable = NULL;
 +      
 +      for (a=0; a<3; a++) {
 +              h = BMIter_New(&iter, bmdm->tc->bm, iters[a], NULL);
 +              for (i=0; h; h=BMIter_Step(&iter), i++) {
 +                      switch (a) {
 +                              case 0:
 +                                      bmdm->vtable[i] = (BMVert*) h;
 +                                      BLI_ghash_insert(bmdm->vhash, h, SET_INT_IN_POINTER(i));
 +                                      break;
 +                              case 1:
 +                                      bmdm->etable[i] = (BMEdge*) h;
 +                                      BLI_ghash_insert(bmdm->ehash, h, SET_INT_IN_POINTER(i));
 +                                      break;
 +                              case 2:
 +                                      bmdm->ftable[i] = (BMFace*) h;
 +                                      BLI_ghash_insert(bmdm->fhash, h, SET_INT_IN_POINTER(i));
 +                                      break;
 +
 +                      }
 +              }
 +      }
 +}
 +
 +static void bmDM_recalcTesselation(DerivedMesh *dm)
 +{
 +      EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
 +
 +      //bmdm_recalc_lookups(bmdm);
 +}
 +
 +static void bmDM_foreachMappedVert(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no_f, short *no_s), void *userData)
 +{
 +      EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
 +      BMVert *eve;
 +      BMIter iter;
 +      int i;
 +      
 +      eve = BMIter_New(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
 +      for (i=0; eve; i++, eve=BMIter_Step(&iter)) {
 +              if (bmdm->vertexCos) {
 +                      func(userData, i, bmdm->vertexCos[i], bmdm->vertexNos[i], NULL);
 +              } else {
 +                      func(userData, i, eve->co, eve->no, NULL);
 +              }
 +      }
 +}
 +static void bmDM_foreachMappedEdge(DerivedMesh *dm, void (*func)(void *userData, int index, float *v0co, float *v1co), void *userData)
 +{
 +      EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
 +      BMEdge *eed;
 +      BMIter iter;
 +      int i;
 +      
 +      if (bmdm->vertexCos) {
 +              BMVert *eve;
 +              BMIter viter;
 +
 +              eve = BMIter_New(&viter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
 +              for (i=0; eve; eve=BMIter_Step(&viter), i++) {
 +                      BMINDEX_SET(eve, i);
 +              }
 +
 +              eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
 +              for(i=0; eed; i++,eed=BMIter_Step(&iter))
 +                      func(userData, i, 
 +                           bmdm->vertexCos[BMINDEX_GET(eve)], 
 +                           bmdm->vertexCos[BMINDEX_GET(eve)]);
 +      } else {
 +              eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
 +              for(i=0; eed; i++,eed=BMIter_Step(&iter))
 +                      func(userData, i, eed->v1->co, eed->v2->co);
 +      }
 +
 +}
 +
 +static void bmDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData) 
 +{
 +      EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
 +      BMEdge *eed;
 +      BMIter iter;
 +      int i;
 +      
 +      if (bmdm->vertexCos) {
 +              BMVert *eve;
 +              BMIter viter;
 +
 +              eve = BMIter_New(&viter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
 +              for (i=0; eve; eve=BMIter_Step(&viter), i++) {
 +                      BMINDEX_SET(eve, i);
 +              }
 +
 +              glBegin(GL_LINES);
 +              eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
 +              for(i=0; eed; i++,eed=BMIter_Step(&iter)) {
 +                      if(!setDrawOptions || setDrawOptions(userData, i)) {
 +                              glVertex3fv(bmdm->vertexCos[BMINDEX_GET(eed->v1)]);
 +                              glVertex3fv(bmdm->vertexCos[BMINDEX_GET(eed->v2)]);
 +                      }
 +              }
 +              glEnd();
 +
 +      } else {
 +              glBegin(GL_LINES);
 +              eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
 +              for(i=0; eed; i++,eed=BMIter_Step(&iter)) {
 +                      if(!setDrawOptions || setDrawOptions(userData, i)) {
 +                              glVertex3fv(eed->v1->co);
 +                              glVertex3fv(eed->v2->co);
 +                      }
 +              }
 +              glEnd();
 +      }
 +}
 +
 +static void bmDM_drawEdges(DerivedMesh *dm, int drawLooseEdges)
 +{
 +      bmDM_drawMappedEdges(dm, NULL, NULL);
 +}
 +
 +static void bmDM_drawMappedEdgesInterp(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void (*setDrawInterpOptions)(void *userData, int index, float t), void *userData) 
 +{
 +      EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
 +      BMEdge *eed;
 +      BMIter iter;
 +      int i;
 +
 +      if (bmdm->vertexCos) {
 +              BMVert *eve;
 +
 +              eve = BMIter_New(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
 +              for (i=0; eve; eve=BMIter_Step(&iter), i++)
 +                      BMINDEX_SET(eve, i);
 +
 +              glBegin(GL_LINES);
 +              eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
 +              for(i=0; eed; i++,eed=BMIter_Step(&iter)) {
 +                      if(!setDrawOptions || setDrawOptions(userData, i)) {
 +                              setDrawInterpOptions(userData, i, 0.0);
 +                              glVertex3fv(bmdm->vertexCos[(int) BMINDEX_GET(eed->v1)]);
 +                              setDrawInterpOptions(userData, i, 1.0);
 +                              glVertex3fv(bmdm->vertexCos[(int) BMINDEX_GET(eed->v2)]);
 +                      }
 +              }
 +              glEnd();
 +      } else {
 +              glBegin(GL_LINES);
 +              eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
 +              for(i=0; eed; i++,eed=BMIter_Step(&iter)) {
 +                      if(!setDrawOptions || setDrawOptions(userData, i)) {
 +                              setDrawInterpOptions(userData, i, 0.0);
 +                              glVertex3fv(eed->v1->co);
 +                              setDrawInterpOptions(userData, i, 1.0);
 +                              glVertex3fv(eed->v2->co);
 +                      }
 +              }
 +              glEnd();
 +      }
 +}
 +
 +static void bmDM_drawUVEdges(DerivedMesh *dm)
 +{
 +#if 0
 +      EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
 +      BMFace *efa;
 +      MTFace *tf;
 +
 +      glBegin(GL_LINES);
 +      for(efa= bmdm->tc->bm->faces.first; efa; efa= efa->next) {
 +              tf = CustomData_bm_get(&bmdm->tc->bm->pdata, efa->data, CD_MTFACE);
 +
 +              if(tf && !(efa->h)) {
 +                      glVertex2fv(tf->uv[0]);
 +                      glVertex2fv(tf->uv[1]);
 +
 +                      glVertex2fv(tf->uv[1]);
 +                      glVertex2fv(tf->uv[2]);
 +
 +                      if (!efa->v4) {
 +                              glVertex2fv(tf->uv[2]);
 +                              glVertex2fv(tf->uv[0]);
 +                      } else {
 +                              glVertex2fv(tf->uv[2]);
 +                              glVertex2fv(tf->uv[3]);
 +                              glVertex2fv(tf->uv[3]);
 +                              glVertex2fv(tf->uv[0]);
 +                      }
 +              }
 +      }
 +      glEnd();
 +#endif
 +}
 +
 +static void bmDM__calcFaceCent(BMesh *bm, BMFace *efa, float cent[3],
 +                               float (*vertexCos)[3])
 +{
 +      BMIter iter;
 +      BMLoop *l;
 +      int tot = 0;
 +      
 +      cent[0] = cent[1] = cent[2] = 0.0f;
 +      
 +      /*simple (and stupid) median (average) based method :/ */
 +      
 +      if (vertexCos) {
 +              l = BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, efa);
 +              for (; l; l=BMIter_Step(&iter)) {
 +                      VECADD(cent, cent, vertexCos[BMINDEX_GET(l->v)]);
 +                      tot++;
 +              }
 +      } else {
 +              l = BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, efa);
 +              for (; l; l=BMIter_Step(&iter)) {
 +                      VECADD(cent, cent, l->v->co);
 +                      tot++;
 +              }
 +      }
 +
 +      if (tot==0) return;
 +      VECMUL(cent, 1.0f/(float)tot);
 +}
 +
 +static void bmDM_foreachMappedFaceCenter(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no), void *userData)
 +{
 +      EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
 +      BMVert *eve;
 +      BMFace *efa;
 +      BMIter iter;
 +      float cent[3];
 +      int i;
 +
 +      if (bmdm->vertexCos) {
 +              eve = BMIter_New(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
 +              for (i=0; eve; eve=BMIter_Step(&iter), i++)
 +                      BMINDEX_SET(eve, i);
 +      }
 +
 +      efa = BMIter_New(&iter, bmdm->tc->bm, BM_FACES_OF_MESH, NULL);
 +      for (i=0; efa; efa=BMIter_Step(&iter), i++) {
 +              bmDM__calcFaceCent(bmdm->tc->bm, efa, cent, bmdm->vertexCos);
 +              func(userData, i, cent, bmdm->vertexCos?bmdm->faceNos[i]:efa->no);
 +      }
 +}
 +
 +static void bmDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int useColors)
 +{
 +      EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
 +      BMFace *efa;
 +      BMIter iter;
 +      int i, draw;
 +
 +      if (bmdm->vertexCos) {
 +              BMVert *eve;
 +              
 +              eve = BMIter_New(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
 +              for (i=0; eve; eve=BMIter_Step(&iter), i++)
 +                      BMINDEX_SET(eve, i);
 +
 +              efa = BMIter_New(&iter, bmdm->tc->bm, BM_FACES_OF_MESH, NULL);
 +              for (i=0; efa; efa=BMIter_Step(&iter), i++)
 +                      BMINDEX_SET(efa, i);
 +
 +              for (i=0; i<bmdm->tc->tottri; i++) {
 +                      BMLoop **l = bmdm->tc->looptris[i];
 +                      int drawSmooth;
 +                      
 +                      efa = l[0]->f;
 +                      drawSmooth = (efa->head.flag & BM_SMOOTH);
 +
 +                      draw = setDrawOptions==NULL ? 1 : setDrawOptions(userData, BMINDEX_GET(efa), &drawSmooth);
 +                      if(draw) {
 +                              if (draw==2) { /* enabled with stipple */
 +                                      glEnable(GL_POLYGON_STIPPLE);
 +                                      glPolygonStipple(stipple_quarttone);
 +                              }
 +                              
 +                              glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
 +
 +                              glBegin(GL_TRIANGLES);
 +
 +                              if (!drawSmooth) {
 +                                      glNormal3fv(bmdm->faceNos[i]);
 +                                      glVertex3fv(bmdm->vertexCos[(int) BMINDEX_GET(l[0]->v)]);
 +                                      glVertex3fv(bmdm->vertexCos[(int) BMINDEX_GET(l[1]->v)]);
 +                                      glVertex3fv(bmdm->vertexCos[(int) BMINDEX_GET(l[2]->v)]);
 +                              } else {
 +                                      glNormal3fv(bmdm->vertexNos[(int) BMINDEX_GET(l[0]->v)]);
 +                                      glVertex3fv(bmdm->vertexCos[(int) BMINDEX_GET(l[0]->v)]);
 +                                      glNormal3fv(bmdm->vertexNos[(int) BMINDEX_GET(l[1]->v)]);
 +                                      glVertex3fv(bmdm->vertexCos[(int) BMINDEX_GET(l[1]->v)]);
 +                                      glNormal3fv(bmdm->vertexNos[(int) BMINDEX_GET(l[2]->v)]);
 +                                      glVertex3fv(bmdm->vertexCos[(int) BMINDEX_GET(l[2]->v)]);
 +                              }
 +                              glEnd();
 +
 +                              if (draw==2)
 +                                      glDisable(GL_POLYGON_STIPPLE);
 +                      }
 +              }
 +      } else {
 +              efa = BMIter_New(&iter, bmdm->tc->bm, BM_FACES_OF_MESH, NULL);
 +              for (i=0; efa; efa=BMIter_Step(&iter), i++)
 +                      BMINDEX_SET(efa, i);
 +
 +              for (i=0; i<bmdm->tc->tottri; i++) {
 +                      BMLoop **l = bmdm->tc->looptris[i];
 +                      int drawSmooth;
 +
 +                      efa = l[0]->f;
 +                      drawSmooth = (efa->head.flag & BM_SMOOTH);
 +                      
 +                      draw = setDrawOptions==NULL ? 1 : setDrawOptions(userData, BMINDEX_GET(efa), &drawSmooth);
 +                      if(draw) {
 +                              if (draw==2) { /* enabled with stipple */
 +                                      glEnable(GL_POLYGON_STIPPLE);
 +                                      glPolygonStipple(stipple_quarttone);
 +                              }
 +                              glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
 +                              
 +                              glBegin(GL_TRIANGLES);
 +                              if (!drawSmooth) {
 +                                      glNormal3fv(efa->no);
 +                                      glVertex3fv(l[0]->v->co);
 +                                      glVertex3fv(l[1]->v->co);
 +                                      glVertex3fv(l[2]->v->co);
 +                              } else {
 +                                      glNormal3fv(l[0]->v->no);
 +                                      glVertex3fv(l[0]->v->co);
 +                                      glNormal3fv(l[1]->v->no);
 +                                      glVertex3fv(l[1]->v->co);
 +                                      glNormal3fv(l[2]->v->no);
 +                                      glVertex3fv(l[2]->v->co);
 +                              }
 +                              glEnd();
 +                              
 +                              if (draw==2)
 +                                      glDisable(GL_POLYGON_STIPPLE);
 +                      }
 +              }
 +      }
 +}
 +
 +static void bmdm_get_tri_tex(BMesh *bm, BMLoop **ls, MLoopUV *luv[3], MLoopCol *lcol[3], 
 +                           int has_uv, int has_col)
 +{
 +      if (has_uv) { 
 +              luv[0] = CustomData_bmesh_get(&bm->ldata, ls[0]->head.data, CD_MLOOPUV);
 +              luv[1] = CustomData_bmesh_get(&bm->ldata, ls[1]->head.data, CD_MLOOPUV);
 +              luv[2] = CustomData_bmesh_get(&bm->ldata, ls[2]->head.data, CD_MLOOPUV);
 +      }
 +
 +      if (has_col) {
 +              lcol[0] = CustomData_bmesh_get(&bm->ldata, ls[0]->head.data, CD_MLOOPCOL);
 +              lcol[1] = CustomData_bmesh_get(&bm->ldata, ls[1]->head.data, CD_MLOOPCOL);
 +              lcol[2] = CustomData_bmesh_get(&bm->ldata, ls[2]->head.data, CD_MLOOPCOL);
 +      }
 +
 +
 +}
 +
 +static void bmDM_drawFacesTex_common(DerivedMesh *dm,
 +               int (*drawParams)(MTFace *tface, int has_vcol, int matnr),
 +               int (*drawParamsMapped)(void *userData, int index),
 +               void *userData) 
 +{
 +      EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
 +      BMEditMesh *em = bmdm->tc;
 +      BMesh *bm= bmdm->tc->bm;
 +      float (*vertexCos)[3]= bmdm->vertexCos;
 +      float (*vertexNos)[3]= bmdm->vertexNos;
 +      BMFace *efa;
 +      BMVert *eve;
 +      BMIter iter;
 +      MLoopUV *luv[3], dummyluv = {0};
 +      MLoopCol *lcol[3], dummylcol = {0};
 +      int i, has_vcol = CustomData_has_layer(&bm->ldata, CD_MLOOPCOL);
 +      int has_uv = CustomData_has_layer(&bm->pdata, CD_MTEXPOLY);
 +      
 +      luv[0] = luv[1] = luv[2] = &dummyluv;
 +      lcol[0] = lcol[1] = lcol[2] = &dummylcol;
 +
 +      dummylcol.a = dummylcol.r = dummylcol.g = dummylcol.b = 255;
 +
 +      /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
 +      glShadeModel(GL_SMOOTH);
 +      
 +      i = 0;
 +      BM_ITER(efa, &iter, bm, BM_FACES_OF_MESH, NULL)
 +              BMINDEX_SET(efa, i++);
 +
 +      if (vertexCos) {
 +              i = 0;
 +              BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL)
 +                      BMINDEX_SET(eve, i++);
 +                              
 +              glBegin(GL_TRIANGLES);
 +              for (i=0; i<em->tottri; i++) {
 +                      BMLoop **ls = em->looptris[i];
 +                      MTexPoly *tp= CustomData_bmesh_get(&bm->pdata, ls[0]->f->head.data, CD_MTEXPOLY);
 +                      MTFace mtf = {0};
 +                      unsigned char *cp= NULL;
 +                      int drawSmooth= BM_TestHFlag(ls[0]->f, BM_SMOOTH);
 +                      int flag;
 +
 +                      efa = ls[0]->f;
 +                      
 +                      if (has_uv) {
 +                              mtf.flag = tp->flag;
 +                              mtf.tpage = tp->tpage;
 +                              mtf.transp = tp->transp;
 +                              mtf.mode = tp->mode;
 +                              mtf.tile = tp->tile;
 +                              mtf.unwrap = tp->unwrap;
 +                      }
 +
 +                      if(drawParams)
 +                              flag= drawParams(&mtf, has_vcol, efa->mat_nr);
 +                      else if(drawParamsMapped)
 +                              flag= drawParamsMapped(userData, BMINDEX_GET(efa));
 +                      else
 +                              flag= 1;
 +
 +                      if(flag != 0) { /* flag 0 == the face is hidden or invisible */
 +                              
 +                              /* we always want smooth here since otherwise vertex colors dont interpolate */
 +                              if (!has_vcol) {
 +                                      glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
 +                              } 
 +                              
 +                              if (!drawSmooth) {
 +                                      glNormal3fv(bmdm->faceNos[i]);
 +                                      
 +                                      bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
 +                                      
 +                                      glTexCoord2fv(luv[0]->uv);
 +                                      glColor3ub(lcol[0]->b, lcol[0]->g, lcol[0]->r);
 +                                      glVertex3fv(vertexCos[BMINDEX_GET(ls[0]->v)]);
 +
 +                                      glTexCoord2fv(luv[1]->uv);
 +                                      glColor3ub(lcol[1]->b, lcol[1]->g, lcol[1]->r);
 +                                      glVertex3fv(vertexCos[BMINDEX_GET(ls[1]->v)]);
 +
 +                                      glTexCoord2fv(luv[2]->uv);
 +                                      glColor3ub(lcol[2]->b, lcol[2]->g, lcol[2]->r);
 +                                      glVertex3fv(vertexCos[BMINDEX_GET(ls[2]->v)]);
 +                              } else {
 +                                      bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
 +                                      
 +                                      glTexCoord2fv(luv[0]->uv);
 +                                      glColor3ub(lcol[0]->b, lcol[0]->g, lcol[0]->r);
 +                                      glNormal3fv(vertexNos[BMINDEX_GET(ls[0]->v)]);
 +                                      glVertex3fv(vertexCos[BMINDEX_GET(ls[0]->v)]);
 +
 +                                      glTexCoord2fv(luv[1]->uv);
 +                                      glColor3ub(lcol[1]->b, lcol[1]->g, lcol[1]->r);
 +                                      glNormal3fv(vertexNos[BMINDEX_GET(ls[1]->v)]);
 +                                      glVertex3fv(vertexCos[BMINDEX_GET(ls[1]->v)]);
 +
 +                                      glTexCoord2fv(luv[2]->uv);
 +                                      glColor3ub(lcol[2]->b, lcol[2]->g, lcol[2]->r);
 +                                      glNormal3fv(vertexNos[BMINDEX_GET(ls[2]->v)]);
 +                                      glVertex3fv(vertexCos[BMINDEX_GET(ls[2]->v)]);
 +                              }
 +                      }
 +              }
 +              glEnd();
 +      } else {
 +              i = 0;
 +              BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL)
 +                      BMINDEX_SET(eve, i++);
 +                              
 +              for (i=0; i<em->tottri; i++) {
 +                      BMLoop **ls = em->looptris[i];
 +                      MTexPoly *tp= CustomData_bmesh_get(&bm->pdata, ls[0]->f->head.data, CD_MTEXPOLY);
 +                      MTFace mtf = {0};
 +                      unsigned char *cp= NULL;
 +                      int drawSmooth= BM_TestHFlag(ls[0]->f, BM_SMOOTH);
 +                      int flag;
 +
 +                      efa = ls[0]->f;
 +                      
 +                      if (has_uv) {
 +                              mtf.flag = tp->flag;
 +                              mtf.tpage = tp->tpage;
 +                              mtf.transp = tp->transp;
 +                              mtf.mode = tp->mode;
 +                              mtf.tile = tp->tile;
 +                              mtf.unwrap = tp->unwrap;
 +                      }
 +
 +                      if(drawParams)
 +                              flag= drawParams(&mtf, has_vcol, efa->mat_nr);
 +                      else if(drawParamsMapped)
 +                              flag= drawParamsMapped(userData, BMINDEX_GET(efa));
 +                      else
 +                              flag= 1;
 +
 +                      if(flag != 0) { /* flag 0 == the face is hidden or invisible */
 +                              
 +                              /* we always want smooth here since otherwise vertex colors dont interpolate */
 +                              if (!has_vcol) {
 +                                      glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
 +                              } 
 +                              
 +                              glBegin(GL_TRIANGLES);
 +                              if (!drawSmooth) {
 +                                      glNormal3fv(efa->no);
 +                                      
 +                                      bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
 +                                      
 +                                      if (luv[0])
 +                                              glTexCoord2fv(luv[0]->uv);
 +                                      if (lcol[0])
 +                                              glColor3ub(lcol[0]->b, lcol[0]->g, lcol[0]->r);
 +                                      else glColor3ub(0, 0, 0);
 +                                      glVertex3fv(ls[0]->v->co);
 +
 +                                      if (luv[1])
 +                                              glTexCoord2fv(luv[1]->uv);
 +                                      if (lcol[1])
 +                                              glColor3ub(lcol[1]->b, lcol[1]->g, lcol[1]->r);
 +                                      else glColor3ub(0, 0, 0);
 +                                      glVertex3fv(ls[1]->v->co);
 +
 +                                      if (luv[2])
 +                                              glTexCoord2fv(luv[2]->uv);
 +                                      if (lcol[2])
 +                                              glColor3ub(lcol[2]->b, lcol[2]->g, lcol[2]->r);
 +                                      else glColor3ub(0, 0, 0);
 +                                      glVertex3fv(ls[2]->v->co);
 +                              } else {
 +                                      bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
 +                                      
 +                                      if (luv[0])
 +                                              glTexCoord2fv(luv[0]->uv);
 +                                      if (lcol[0])
 +                                              glColor3ub(lcol[0]->b, lcol[0]->g, lcol[0]->r);
 +                                      else glColor3ub(0, 0, 0);
 +                                      glNormal3fv(ls[0]->v->no);
 +                                      glVertex3fv(ls[0]->v->co);
 +
 +                                      if (luv[1])
 +                                              glTexCoord2fv(luv[1]->uv);
 +                                      if (lcol[1])
 +                                              glColor3ub(lcol[1]->b, lcol[1]->g, lcol[1]->r);
 +                                      else glColor3ub(0, 0, 0);
 +                                      glNormal3fv(ls[1]->v->no);
 +                                      glVertex3fv(ls[1]->v->co);
 +
 +                                      if (luv[2])
 +                                              glTexCoord2fv(luv[2]->uv);
 +                                      if (lcol[2])
 +                                              glColor3ub(lcol[2]->b, lcol[2]->g, lcol[2]->r);
 +                                      else glColor3ub(0, 0, 0);
 +                                      glNormal3fv(ls[2]->v->no);
 +                                      glVertex3fv(ls[2]->v->co);
 +                              }
 +                              glEnd();
 +                      }
 +              }
 +      }
 +}
 +
 +static void bmDM_drawFacesTex(DerivedMesh *dm, int (*setDrawOptions)(MTFace *tface, int has_vcol, int matnr))
 +{
 +      bmDM_drawFacesTex_common(dm, setDrawOptions, NULL, NULL);
 +}
 +
 +static void bmDM_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
 +{
 +      bmDM_drawFacesTex_common(dm, NULL, setDrawOptions, userData);
 +}
 +
 +static void bmDM_drawMappedFacesGLSL(DerivedMesh *dm,
 +               int (*setMaterial)(int, void *attribs),
 +               int (*setDrawOptions)(void *userData, int index), void *userData) 
 +{
 +#if 0
 +      EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
 +      BMesh *bm= bmdm->tc->bm;
 +      float (*vertexCos)[3]= bmdm->vertexCos;
 +      float (*vertexNos)[3]= bmdm->vertexNos;
 +      BMVert *eve;
 +      BMFace *efa;
 +      DMVertexAttribs attribs;
 +      GPUVertexAttribs gattribs;
 +      MTFace *tf;
 +      int transp, new_transp, orig_transp, tfoffset;
 +      int i, b, matnr, new_matnr, dodraw, layer;
 +
 +      dodraw = 0;
 +      matnr = -1;
 +
 +      transp = GPU_get_material_blend_mode();
 +      orig_transp = transp;
 +      layer = CustomData_get_layer_index(&bm->pdata, CD_MTFACE);
 +      tfoffset = (layer == -1)? -1: bm->pdata.layers[layer].offset;
 +
 +      memset(&attribs, 0, sizeof(attribs));
 +
 +      /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
 +      glShadeModel(GL_SMOOTH);
 +
 +      for (i=0,eve=bm->verts.first; eve; eve= eve->next)
 +              BMINDEX_SET(eve, i++);
 +
 +#define PASSATTRIB(efa, eve, vert) {                                                                                  \
 +      if(attribs.totorco) {                                                                                                           \
 +              float *orco = attribs.orco.array[BMINDEX_GET(eve)];                                                     \
 +              glVertexAttrib3fvARB(attribs.orco.glIndex, orco);                                               \
 +      }                                                                                                                                                       \
 +      for(b = 0; b < attribs.tottface; b++) {                                                                         \
 +              MTFace *_tf = (MTFace*)((char*)efa->data + attribs.tface[b].bmOffset);  \
 +              glVertexAttrib2fvARB(attribs.tface[b].glIndex, _tf->uv[vert]);                  \
 +      }                                                                                                                                                       \
 +      for(b = 0; b < attribs.totmcol; b++) {                                                                          \
 +              MCol *cp = (MCol*)((char*)efa->data + attribs.mcol[b].bmOffset);                \
 +              GLubyte col[4];                                                                                                                 \
 +              col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;                             \
 +              glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, col);                                    \
 +      }                                                                                                                                                       \
 +      if(attribs.tottang) {                                                                                                           \
 +              float *tang = attribs.tang.array[i*4 + vert];                                                   \
 +              glVertexAttrib3fvARB(attribs.tang.glIndex, tang);                                               \
 +      }                                                                                                                                                       \
 +}
 +
 +      for (i=0,efa= bm->faces.first; efa; i++,efa= efa->next) {
 +              int drawSmooth= (efa->flag & ME_SMOOTH);
 +
 +              if(setDrawOptions && !setDrawOptions(userData, i))
 +                      continue;
 +
 +              new_matnr = efa->mat_nr + 1;
 +              if(new_matnr != matnr) {
 +                      dodraw = setMaterial(matnr = new_matnr, &gattribs);
 +                      if(dodraw)
 +                              DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
 +              }
 +
 +              if(tfoffset != -1) {
 +                      tf = (MTFace*)((char*)efa->data)+tfoffset;
 +                      new_transp = tf->transp;
 +
 +                      if(new_transp != transp) {
 +                              if(new_transp == GPU_BLEND_SOLID && orig_transp != GPU_BLEND_SOLID)
 +                                      GPU_set_material_blend_mode(orig_transp);
 +                              else
 +                                      GPU_set_material_blend_mode(new_transp);
 +                              transp = new_transp;
 +                      }
 +              }
 +
 +              if(dodraw) {
 +                      glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
 +                      if (!drawSmooth) {
 +                              if(vertexCos) glNormal3fv(bmdm->faceNos[i]);
 +                              else glNormal3fv(efa->n);
 +
 +                              PASSATTRIB(efa, efa->v1, 0);
 +                              if(vertexCos) glVertex3fv(vertexCos[(int) efa->v1->tmp.l]);
 +                              else glVertex3fv(efa->v1->co);
 +
 +                              PASSATTRIB(efa, efa->v2, 1);
 +                              if(vertexCos) glVertex3fv(vertexCos[(int) efa->v2->tmp.l]);
 +                              else glVertex3fv(efa->v2->co);
 +
 +                              PASSATTRIB(efa, efa->v3, 2);
 +                              if(vertexCos) glVertex3fv(vertexCos[(int) efa->v3->tmp.l]);
 +                              else glVertex3fv(efa->v3->co);
 +
 +                              if(efa->v4) {
 +                                      PASSATTRIB(efa, efa->v4, 3);
 +                                      if(vertexCos) glVertex3fv(vertexCos[(int) efa->v4->tmp.l]);
 +                                      else glVertex3fv(efa->v4->co);
 +                              }
 +                      } else {
 +                              PASSATTRIB(efa, efa->v1, 0);
 +                              if(vertexCos) {
 +                                      glNormal3fv(vertexNos[(int) efa->v1->tmp.l]);
 +                                      glVertex3fv(vertexCos[(int) efa->v1->tmp.l]);
 +                              }
 +                              else {
 +                                      glNormal3fv(efa->v1->no);
 +                                      glVertex3fv(efa->v1->co);
 +                              }
 +
 +                              PASSATTRIB(efa, efa->v2, 1);
 +                              if(vertexCos) {
 +                                      glNormal3fv(vertexNos[(int) efa->v2->tmp.l]);
 +                                      glVertex3fv(vertexCos[(int) efa->v2->tmp.l]);
 +                              }
 +                              else {
 +                                      glNormal3fv(efa->v2->no);
 +                                      glVertex3fv(efa->v2->co);
 +                              }
 +
 +                              PASSATTRIB(efa, efa->v3, 2);
 +                              if(vertexCos) {
 +                                      glNormal3fv(vertexNos[(int) efa->v3->tmp.l]);
 +                                      glVertex3fv(vertexCos[(int) efa->v3->tmp.l]);
 +                              }
 +                              else {
 +                                      glNormal3fv(efa->v3->no);
 +                                      glVertex3fv(efa->v3->co);
 +                              }
 +
 +                              if(efa->v4) {
 +                                      PASSATTRIB(efa, efa->v4, 3);
 +                                      if(vertexCos) {
 +                                              glNormal3fv(vertexNos[(int) efa->v4->tmp.l]);
 +                                              glVertex3fv(vertexCos[(int) efa->v4->tmp.l]);
 +                                      }
 +                                      else {
 +                                              glNormal3fv(efa->v4->no);
 +                                              glVertex3fv(efa->v4->co);
 +                                      }
 +                              }
 +                      }
 +                      glEnd();
 +              }
 +      }
 +#endif
 +}
 +
 +static void bmDM_drawFacesGLSL(DerivedMesh *dm,
 +               int (*setMaterial)(int, void *attribs))
 +{
 +      dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
 +}
 +
 +static void bmDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3])
 +{
 +      EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
 +      BMVert *eve;
 +      BMIter iter;
 +      int i;
 +
 +      if (bmdm->tc->bm->verts.first) {
 +              eve = BMIter_New(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
 +              for (i=0; eve; eve=BMIter_Step(&iter), i++) {
 +                      if (bmdm->vertexCos) {
 +                              DO_MINMAX(bmdm->vertexCos[i], min_r, max_r);
 +                      } else {
 +                              DO_MINMAX(eve->co, min_r, max_r);
 +                      }
 +              }
 +      } else {
 +              min_r[0] = min_r[1] = min_r[2] = max_r[0] = max_r[1] = max_r[2] = 0.0;
 +      }
 +}
 +static int bmDM_getNumVerts(DerivedMesh *dm)
 +{
 +      EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
 +
 +      return bmdm->tc->bm->totvert;
 +}
 +
 +static int bmDM_getNumEdges(DerivedMesh *dm)
 +{
 +      EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
 +
 +      return bmdm->tc->bm->totedge;
 +}
 +
 +static int bmDM_getNumTessFaces(DerivedMesh *dm)
 +{
 +      EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
 +      
 +      return bmdm->tc->tottri;
 +}
 +
 +static int bmDM_getNumFaces(DerivedMesh *dm)
 +{
 +      EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
 +      
 +      return bmdm->tc->bm->totface;
 +}
 +
 +static int bmvert_to_mvert(BMVert *ev, MVert *vert_r)
 +{
 +      VECCOPY(vert_r->co, ev->co);
 +
 +      vert_r->no[0] = (short)(ev->no[0] * 32767.0f);
 +      vert_r->no[1] = (short)(ev->no[1] * 32767.0f);
 +      vert_r->no[2] = (short)(ev->no[2] * 32767.0f);
 +
 +      /* TODO what to do with vert_r->flag and vert_r->mat_nr? */
 +      vert_r->flag = BMFlags_To_MEFlags(ev);
 +      vert_r->mat_nr = 0;
 +      vert_r->bweight = (unsigned char) (ev->bweight*255.0f);
 +}
 +
 +static void bmDM_getVert(DerivedMesh *dm, int index, MVert *vert_r)
 +{
 +      BMVert *ev;
 +      BMIter iter;
 +      int i;
 +
 +      if (index < 0 || index >= ((EditDerivedBMesh *)dm)->tv) {
 +              printf("error in bmDM_getVert.\n");
 +              return;
 +      }
 +
 +      ev = ((EditDerivedBMesh *)dm)->vtable[index];
 +      bmvert_to_mvert(ev, vert_r);
 +}
 +
 +static void bmDM_getEdge(DerivedMesh *dm, int index, MEdge *edge_r)
 +{
 +      EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
 +      BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
 +      BMEdge *e;
 +      BMVert *ev, *v1, *v2;
 +      BMIter iter;
 +      int i;
 +
 +      if (index < 0 || index >= ((EditDerivedBMesh *)dm)->te) {
 +              printf("error in bmDM_getEdge.\n");
 +              return;
 +      }
 +
 +      e = bmdm->etable[index];
 +
 +      edge_r->crease = (unsigned char) (e->crease*255.0f);
 +      edge_r->bweight = (unsigned char) (e->bweight*255.0f);
 +      /* TODO what to do with edge_r->flag? */
 +      edge_r->flag = ME_EDGEDRAW|ME_EDGERENDER;
 +      edge_r->flag |= BMFlags_To_MEFlags(e);
 +#if 0
 +      /* this needs setup of f2 field */
 +      if (!ee->f2) edge_r->flag |= ME_LOOSEEDGE;
 +#endif
 +      
 +      edge_r->v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(bmdm->vhash, e->v1));
 +      edge_r->v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(bmdm->vhash, e->v2));
 +}
 +
 +static void bmDM_getTessFace(DerivedMesh *dm, int index, MFace *face_r)
 +{
 +      EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
 +      BMesh *bm = bmdm->tc->bm;
 +      BMFace *ef;
 +      BMIter iter;
 +      BMLoop **l;
 +      int i;
 +      
 +      if (index < 0 || index >= ((EditDerivedBMesh *)dm)->tf) {
 +              printf("error in bmDM_getTessFace.\n");
 +              return;
 +      }
 +
 +      l = ((EditDerivedBMesh *)dm)->tc->looptris[index];
 +
 +      ef = l[0]->f;
 +
 +      face_r->mat_nr = (unsigned char) ef->mat_nr;
 +      face_r->flag = BMFlags_To_MEFlags(ef);
 +
 +      face_r->v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(bmdm->vhash, l[0]->v));
 +      face_r->v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(bmdm->vhash, l[1]->v));
 +      face_r->v3 = GET_INT_FROM_POINTER(BLI_ghash_lookup(bmdm->vhash, l[2]->v));
 +      face_r->v4 = 0;
 +
 +      test_index_face(face_r, NULL, 0, 3);
 +}
 +
 +static void bmDM_copyVertArray(DerivedMesh *dm, MVert *vert_r)
 +{
 +      BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
 +      BMVert *ev;
 +      BMIter iter;
 +
 +      ev = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
 +      for( ; ev; ev = BMIter_Step(&iter), ++vert_r) {
 +              VECCOPY(vert_r->co, ev->co);
 +
 +              vert_r->no[0] = (short) (ev->no[0] * 32767.0);
 +              vert_r->no[1] = (short) (ev->no[1] * 32767.0);
 +              vert_r->no[2] = (short) (ev->no[2] * 32767.0);
 +
 +              /* TODO what to do with vert_r->flag and vert_r->mat_nr? */
 +              vert_r->mat_nr = 0;
 +              vert_r->flag = BMFlags_To_MEFlags(ev);
 +              vert_r->bweight = (unsigned char) (ev->bweight*255.0f);
 +      }
 +}
 +
 +static void bmDM_copyEdgeArray(DerivedMesh *dm, MEdge *edge_r)
 +{
 +      BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
 +      BMEdge *ee;
 +      BMIter iter;
 +      BMVert *ev;
 +      int i;
 +
 +      /* store vertex indices in tmp union */
 +      ev = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
 +      for (i=0; ev; ev=BMIter_Step(&iter), i++)
 +              BMINDEX_SET(ev, i);
 +
 +      ee = BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL);
 +      for( ; ee; ee=BMIter_Step(&iter)) {
 +              edge_r->crease = (unsigned char) (ee->crease*255.0f);
 +              edge_r->bweight = (unsigned char) (ee->bweight*255.0f);
 +              /* TODO what to do with edge_r->flag? */
 +              edge_r->flag = ME_EDGEDRAW|ME_EDGERENDER;
 +              if (ee->head.flag & BM_SEAM) edge_r->flag |= ME_SEAM;
 +              if (ee->head.flag & BM_SHARP) edge_r->flag |= ME_SHARP;
 +#if 0
 +              /* this needs setup of f2 field */
 +              if (!ee->f2) edge_r->flag |= ME_LOOSEEDGE;
 +#endif
 +
 +              edge_r->v1 = (int)BMINDEX_GET(ee->v1);
 +              edge_r->v2 = (int)BMINDEX_GET(ee->v2);
 +      }
 +}
 +
 +static void bmDM_copyFaceArray(DerivedMesh *dm, MFace *face_r)
 +{
 +      EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
 +      BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
 +      BMFace *ef;
 +      BMVert *ev;
 +      BMIter iter;
 +      BMLoop **l;
 +      int i;
 +
 +      /* store vertexes indices in tmp union */
 +      ev = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
 +      for (i=0; ev; ev=BMIter_Step(&iter), i++)
 +              BMINDEX_SET(ev, i);
 +
 +      for (i=0; i<bmdm->tc->tottri; i++) {
 +              l = bmdm->tc->looptris[i];
 +              ef = l[0]->f;
 +
 +              face_r->mat_nr = (unsigned char) ef->mat_nr;
 +
 +              /*HACK/TODO: need to convert this*/
 +              face_r->flag = ef->head.flag;
 +
 +              face_r->v1 = BMINDEX_GET(l[0]->v);
 +              face_r->v2 = BMINDEX_GET(l[1]->v);
 +              face_r->v3 = BMINDEX_GET(l[2]->v);
 +              face_r->v4 = 0;
 +
 +              test_index_face(face_r, NULL, 0, 3);
 +      }
 +}
 +
 +static void *bmDM_getFaceDataArray(DerivedMesh *dm, int type)
 +{
 +      EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
 +      BMesh *bm= bmdm->tc->bm;
 +      BMFace *efa;
 +      char *data, *bmdata;
 +      void *datalayer;
 +      int index, offset, size, i;
 +
 +      datalayer = DM_get_tessface_data_layer(dm, type);
 +      if(datalayer)
 +              return datalayer;
 +
 +      /* layers are store per face for editmesh, we convert to a tbmporary
 +       * data layer array in the derivedmesh when these are requested */
 +      if(type == CD_MTFACE || type == CD_MCOL) {
 +              index = CustomData_get_layer_index(&bm->pdata, type);
 +
 +              if(index != -1) {
 +                      offset = bm->pdata.layers[index].offset;
 +                      size = CustomData_sizeof(type);
 +
 +                      DM_add_tessface_layer(dm, type, CD_CALLOC, NULL);
 +                      index = CustomData_get_layer_index(&dm->faceData, type);
 +                      dm->faceData.layers[index].flag |= CD_FLAG_TEMPORARY;
 +
 +                      data = datalayer = DM_get_tessface_data_layer(dm, type);
 +                      for (i=0; i<bmdm->tc->tottri; i++, data+=size) {
 +                              efa = bmdm->tc->looptris[i][0]->f;
 +                              /*BMESH_TODO: need to still add tface data,
 +                                derived from the loops.*/
 +                              bmdata = CustomData_bmesh_get(&bm->pdata, efa->head.data, type);
 +                              memcpy(data, bmdata, size);
 +                      }
 +              }
 +      }
 +
 +      return datalayer;
 +}
 +
 +typedef struct bmDM_loopIter {
 +      DMLoopIter head;
 +
 +      BMFace *f;
 +      BMLoop *l, *nextl;
 +      BMIter iter;
 +      BMesh *bm;
 +} bmDM_loopIter;
 +
 +typedef struct bmDM_faceIter {
 +      DMFaceIter head;
 +
 +      BMFace *f, *nextf;
 +      BMIter iter;
 +      BMesh *bm;
 +
 +      bmDM_loopIter loopiter;
 +} bmDM_faceIter;
 +
 +void bmDM_faceIterStep(void *self)
 +{
 +      bmDM_faceIter *iter = self;
 +      
 +      iter->f = iter->nextf;
 +
 +      iter->head.mat_nr = iter->f->mat_nr;
 +      iter->head.flags = BMFlags_To_MEFlags(iter->f);
 +      iter->head.index++;
 +
 +      iter->head.len = iter->f->len;
 +
 +      iter->nextf = BMIter_Step(&iter->iter);
 +
 +      if (!iter->nextf) iter->head.done = 1;
 +}
 +
 +void *bmDM_getFaceCDData(void *self, int type, int layer)
 +{
 +      bmDM_faceIter *iter = self;
 +
 +      if (layer == -1) 
 +              return CustomData_bmesh_get(&iter->bm->pdata, iter->f->head.data, type);
 +      else return CustomData_bmesh_get_n(&iter->bm->pdata, iter->f->head.data, type, layer);
 +}
 +
 +void bmDM_loopIterStep(void *self)
 +{
 +      bmDM_loopIter *iter = self;
 +
 +      iter->l = BMIter_Step(&iter->iter);
 +      if (!iter->l) {
 +              iter->head.done = 1;
 +              return;
 +      }
 +
 +      bmvert_to_mvert(iter->l->v, &iter->head.v);
 +      iter->head.index++;
 +      iter->head.vindex = BMINDEX_GET(iter->l->v);
 +      iter->head.eindex = BMINDEX_GET(iter->l->e);
 +}
 +
 +void *bmDM_getLoopCDData(void *self, int type, int layer)
 +{
 +      bmDM_loopIter *iter = self;
 +
 +      if (layer == -1) 
 +              return CustomData_bmesh_get(&iter->bm->ldata, iter->l->head.data, type);
 +      else return CustomData_bmesh_get_n(&iter->bm->ldata, iter->l->head.data, type, layer);
 +}
 +
 +void *bmDM_getVertCDData(void *self, int type, int layer)
 +{
 +      bmDM_loopIter *iter = self;
 +
 +      if (layer == -1) 
 +              return CustomData_bmesh_get(&iter->bm->vdata, iter->l->v->head.data, type);
 +      else return CustomData_bmesh_get_n(&iter->bm->vdata, iter->l->v->head.data, type, layer);
 +}
 +
 +void bmDM_iterFree(void *self)
 +{
 +      MEM_freeN(self);
 +}
 +
 +void bmDM_nulliterFree(void *self)
 +{
 +}
 +
 +DMLoopIter *bmDM_newLoopsIter(void *faceiter)
 +{
 +      bmDM_faceIter *fiter = faceiter;
 +      bmDM_loopIter *iter = &fiter->loopiter;
 +
 +      memset(&fiter->loopiter, 0, sizeof(bmDM_loopIter));
 +
 +      iter->bm = fiter->bm;
 +      iter->f = fiter->f;
 +      iter->l = BMIter_New(&iter->iter, iter->bm, BM_LOOPS_OF_FACE, iter->f);
 +
 +      iter->head.step = bmDM_loopIterStep;
 +      iter->head.getLoopCDData = bmDM_getLoopCDData;
 +      iter->head.getVertCDData = bmDM_getVertCDData;
 +
 +      bmvert_to_mvert(iter->l->v, &iter->head.v);
 +      iter->head.vindex = BMINDEX_GET(iter->l->v);
 +      iter->head.eindex = BMINDEX_GET(iter->l->e);
 +
 +      return (DMLoopIter*) iter;
 +}
 +
 +static DMFaceIter *bmDM_getFaceIter(void *dm)
 +{
 +      EditDerivedBMesh *bmdm= dm;
 +      bmDM_faceIter *iter = MEM_callocN(sizeof(bmDM_faceIter), "bmDM_faceIter");
 +      BMIter biter;
 +      BMVert *v;
 +      BMEdge *e;
 +      int i;
 +
 +      iter->bm = bmdm->tc->bm;
 +      iter->f = iter->nextf = BMIter_New(&iter->iter, iter->bm, BM_FACES_OF_MESH, NULL);
 +      
 +      iter->head.step = bmDM_faceIterStep;
 +      iter->head.free = bmDM_iterFree;
 +      iter->head.getCDData = bmDM_getFaceCDData;
 +      iter->head.getLoopsIter = bmDM_newLoopsIter;
 +      
 +      iter->head.mat_nr = iter->f->mat_nr;
 +      iter->head.flags = BMFlags_To_MEFlags(iter->f);
 +
 +      /*set up vert/edge indices*/
 +      i = 0;
 +      BM_ITER(v, &biter, iter->bm, BM_VERTS_OF_MESH, NULL) {
 +              BMINDEX_SET(v, i);
 +              i++;
 +      }
 +
 +      i = 0;
 +      BM_ITER(e, &biter, iter->bm, BM_EDGES_OF_MESH, NULL) {
 +              BMINDEX_SET(e, i);
 +              i++;
 +      }
 +
 +      return (DMFaceIter*) iter;
 +}
 +
 +static void bmDM_release(void *dm)
 +{
 +      EditDerivedBMesh *bmdm= dm;
 +
 +      if (DM_release(dm)) {
 +              if (bmdm->vertexCos) {
 +                      MEM_freeN(bmdm->vertexCos);
 +                      MEM_freeN(bmdm->vertexNos);
 +                      MEM_freeN(bmdm->faceNos);
 +              }
 +              
 +              if (bmdm->fhash) BLI_ghash_free(bmdm->fhash, NULL, NULL);
 +              if (bmdm->ehash) BLI_ghash_free(bmdm->ehash, NULL, NULL);
 +              if (bmdm->vhash) BLI_ghash_free(bmdm->vhash, NULL, NULL);
 +
 +              if (bmdm->vtable) MEM_freeN(bmdm->vtable);
 +              if (bmdm->etable) MEM_freeN(bmdm->etable);
 +              if (bmdm->ftable) MEM_freeN(bmdm->ftable);
 +              
 +              MEM_freeN(bmdm);
 +      }
 +}
 +
 +CustomData *bmDm_getVertDataLayout(DerivedMesh *dm)
 +{
 +      EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
 +
 +      return &bmdm->tc->bm->vdata;
 +}
 +
 +CustomData *bmDm_getEdgeDataLayout(DerivedMesh *dm)
 +{
 +      EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
 +
 +      return &bmdm->tc->bm->edata;
 +}
 +
 +CustomData *bmDm_getTessFaceDataLayout(DerivedMesh *dm)
 +{
 +      EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
 +
 +      return &bmdm->tessface_layout;
 +}
 +
 +CustomData *bmDm_getLoopDataLayout(DerivedMesh *dm)
 +{
 +      EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
 +
 +      return &bmdm->tc->bm->ldata;
 +}
 +
 +CustomData *bmDm_getFaceDataLayout(DerivedMesh *dm)
 +{
 +      EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
 +
 +      return &bmdm->tc->bm->pdata;
 +}
 +
 +
 +DerivedMesh *getEditDerivedBMesh(BMEditMesh *em, Object *ob,
 +                                           float (*vertexCos)[3])
 +{
 +      EditDerivedBMesh *bmdm = MEM_callocN(sizeof(*bmdm), "bmdm");
 +      BMesh *bm = em->bm;
 +      int i;
 +      
 +      bmdm->tc = em;
 +
++      DM_init((DerivedMesh*)bmdm, DM_TYPE_EDITBMESH, em->bm->totvert, 
++               em->bm->totedge, em->tottri, em->bm->totloop, em->bm->totface);
 +      
 +      for (i=0; i<bm->ldata.totlayer; i++) {
 +              if (bm->ldata.layers[i].type == CD_MLOOPCOL) {
 +                      CustomData_add_layer(&bmdm->tessface_layout, CD_MCOL, CD_ASSIGN, NULL, 0);
 +              } else if (bm->ldata.layers[i].type == CD_MLOOPUV) {
 +                      CustomData_add_layer(&bmdm->tessface_layout, CD_MTFACE, CD_ASSIGN, NULL, 0);
 +              }
 +      }
 +
 +      bmdm->dm.numVertData = bm->totvert;
 +      bmdm->dm.numEdgeData = bm->totedge;
 +      bmdm->dm.numFaceData = em->tottri;
 +      bmdm->dm.numLoopData = bm->totloop;
 +      bmdm->dm.numPolyData = bm->totface;
 +
 +      bmdm->dm.getMinMax = bmDM_getMinMax;
 +
 +      bmdm->dm.getVertDataLayout = bmDm_getVertDataLayout;
 +      bmdm->dm.getEdgeDataLayout = bmDm_getEdgeDataLayout;
 +      bmdm->dm.getTessFaceDataLayout = bmDm_getTessFaceDataLayout;
 +      bmdm->dm.getLoopDataLayout = bmDm_getLoopDataLayout;
 +      bmdm->dm.getFaceDataLayout = bmDm_getFaceDataLayout;
 +
 +      bmdm->dm.getNumVerts = bmDM_getNumVerts;
 +      bmdm->dm.getNumEdges = bmDM_getNumEdges;
 +      bmdm->dm.getNumTessFaces = bmDM_getNumTessFaces;
 +      bmdm->dm.getNumFaces = bmDM_getNumFaces;
 +
 +      bmdm->dm.getVert = bmDM_getVert;
 +      bmdm->dm.getEdge = bmDM_getEdge;
 +      bmdm->dm.getTessFace = bmDM_getTessFace;
 +      bmdm->dm.copyVertArray = bmDM_copyVertArray;
 +      bmdm->dm.copyEdgeArray = bmDM_copyEdgeArray;
 +      bmdm->dm.copyTessFaceArray = bmDM_copyFaceArray;
 +      bmdm->dm.getTessFaceDataArray = bmDM_getFaceDataArray;
 +
 +      bmdm->dm.newFaceIter = bmDM_getFaceIter;
 +      bmdm->dm.recalcTesselation = bmDM_recalcTesselation;
 +
 +      bmdm->dm.foreachMappedVert = bmDM_foreachMappedVert;
 +      bmdm->dm.foreachMappedEdge = bmDM_foreachMappedEdge;
 +      bmdm->dm.foreachMappedFaceCenter = bmDM_foreachMappedFaceCenter;
 +
 +      bmdm->dm.drawEdges = bmDM_drawEdges;
 +      bmdm->dm.drawMappedEdges = bmDM_drawMappedEdges;
 +      bmdm->dm.drawMappedEdgesInterp = bmDM_drawMappedEdgesInterp;
 +      bmdm->dm.drawMappedFaces = bmDM_drawMappedFaces;
 +      bmdm->dm.drawMappedFacesTex = bmDM_drawMappedFacesTex;
 +      bmdm->dm.drawMappedFacesGLSL = bmDM_drawMappedFacesGLSL;
 +      bmdm->dm.drawFacesTex = bmDM_drawFacesTex;
 +      bmdm->dm.drawFacesGLSL = bmDM_drawFacesGLSL;
 +      bmdm->dm.drawUVEdges = bmDM_drawUVEdges;
 +
 +      bmdm->dm.release = bmDM_release;
 +      
 +      bmdm->vertexCos = vertexCos;
 +
 +      if(CustomData_has_layer(&bm->vdata, CD_MDEFORMVERT)) {
 +              BMIter iter;
 +              BMVert *eve;
 +              int i;
 +
 +              DM_add_vert_layer(&bmdm->dm, CD_MDEFORMVERT, CD_CALLOC, NULL);
 +              
 +              eve = BMIter_New(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
 +              for (i=0; eve; eve=BMIter_Step(&iter), i++)
 +                      DM_set_vert_data(&bmdm->dm, i, CD_MDEFORMVERT,
 +                                       CustomData_bmesh_get(&bm->vdata, eve->head.data, CD_MDEFORMVERT));
 +      }
 +
 +      if(vertexCos) {
 +              BMVert *eve;
 +              BMIter iter;
 +              int totface = bmdm->tc->tottri;
 +              int i;
 +              
 +              eve=BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
 +              for (i=0; eve; eve=BMIter_Step(&iter), i++)
 +                      BMINDEX_SET(eve, i);
 +
 +              bmdm->vertexNos = MEM_callocN(sizeof(*bmdm->vertexNos)*i, "bmdm_vno");
 +              bmdm->faceNos = MEM_mallocN(sizeof(*bmdm->faceNos)*totface, "bmdm_vno");
 +
 +              for (i=0; i<bmdm->tc->tottri; i++) {
 +                      BMLoop **l = bmdm->tc->looptris[i];
 +                      float *v1 = vertexCos[(int) BMINDEX_GET(l[0]->v)];
 +                      float *v2 = vertexCos[(int) BMINDEX_GET(l[1]->v)];
 +                      float *v3 = vertexCos[(int) BMINDEX_GET(l[2]->v)];
 +                      float *no = bmdm->faceNos[i];
 +                      
 +                      normal_tri_v3( no,v1, v2, v3);
 +                      add_v3_v3v3(bmdm->vertexNos[BMINDEX_GET(l[0]->v)], bmdm->vertexNos[BMINDEX_GET(l[0]->v)], no);
 +                      add_v3_v3v3(bmdm->vertexNos[BMINDEX_GET(l[1]->v)], bmdm->vertexNos[BMINDEX_GET(l[1]->v)], no);
 +                      add_v3_v3v3(bmdm->vertexNos[BMINDEX_GET(l[2]->v)], bmdm->vertexNos[BMINDEX_GET(l[2]->v)], no);
 +              }
 +
 +              eve=BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
 +              for (i=0; eve; eve=BMIter_Step(&iter), i++) {
 +                      float *no = bmdm->vertexNos[i];
 +                      /* following Mesh convention; we use vertex coordinate itself
 +                       * for normal in this case */
 +                      if (normalize_v3(no)==0.0) {
 +                              VECCOPY(no, vertexCos[i]);
 +                              normalize_v3(no);
 +                      }
 +              }
 +      }
 +
 +      //bmdm_recalc_lookups(bmdm);
 +
 +      return (DerivedMesh*) bmdm;
 +}
index e83c494ba79728fa73a0715fe8b111eea9c0c1ed,1f5e0ca1624a4febddff69827f21907d1bd3d579..77dfb7bafb473e66f38b5012267baa3462772ef0
@@@ -1456,13 -1410,18 +1457,19 @@@ KeyBlock *add_keyblock(Key *key, char *
        kb->type= KEY_CARDINAL;
        
        tot= BLI_countlist(&key->block);
-       if(tot==1) strcpy(kb->name, "Basis");
-       else sprintf(kb->name, "Key %d", tot-1);
-       
+       if(name) {
+               strncpy(kb->name, name, sizeof(kb->name));
+       } else {
+               if(tot==1) strcpy(kb->name, "Basis");
+               else sprintf(kb->name, "Key %d", tot-1);
+       }
+       BLI_uniquename(&key->block, kb, "Key", '.', offsetof(KeyBlock, name), sizeof(kb->name));
        // XXX this is old anim system stuff? (i.e. the 'index' of the shapekey)
        kb->adrcode= tot-1;
 -      
 +      kb->uid = key->uidgen++;
 +
        key->totkey++;
        if(key->totkey==1) key->refkey= kb;
        
index eee2df207436701139f632cc047db08b785e02d0,1ab4c06bc4c4725fcb699968d42216df47b06d0e..63533ef1adbf47e4fd89fc6715efe946edbeaf37
@@@ -230,9 -145,12 +232,14 @@@ void free_mesh(Mesh *me, int unlink
        CustomData_free(&me->vdata, me->totvert);
        CustomData_free(&me->edata, me->totedge);
        CustomData_free(&me->fdata, me->totface);
 -      
 +      CustomData_free(&me->ldata, me->totloop);
 +      CustomData_free(&me->pdata, me->totpoly);
 +
+       if(me->adt) {
+               BKE_free_animdata(&me->id);
+               me->adt= NULL;
+       }
+       
        if(me->mat) MEM_freeN(me->mat);
        
        if(me->bb) MEM_freeN(me->bb);
index 6f428213e53cd6f31917760522300bcf2331515c,2985eb7774b50265ae96a04afa678279a4e54bbc..9ef10eda6c4230b8fa133a29d017a886481c53c8
@@@ -190,6 -188,26 +193,26 @@@ static DerivedMesh *get_dm(Scene *scene
        return dm;
  }
  
 -              dm= CDDM_copy(dm);
+ /* returns a cdderivedmesh if dm == NULL or is another type of derivedmesh */
+ static DerivedMesh *get_cddm(Scene *scene, Object *ob, EditMesh *em, DerivedMesh *dm, float (*vertexCos)[3])
+ {
+       if(dm && dm->type == DM_TYPE_CDDM)
+               return dm;
+       if(!dm) {
+               dm= get_dm(scene, ob, em, dm, vertexCos, 0);
+       }
+       else {
++              dm= CDDM_copy(dm, 0);
+               CDDM_apply_vert_coords(dm, vertexCos);
+       }
+       if(dm)
+               CDDM_calc_normals(dm);
+       
+       return dm;
+ }
  /***/
  
  static int noneModifier_isDisabled(ModifierData *md, int userRenderParams)
@@@ -2979,16 -3803,10 +2996,10 @@@ static void displaceModifier_deformVert
  }
  
  static void displaceModifier_deformVertsEM(
 -                                         ModifierData *md, Object *ob, EditMesh *editData,
 +                                         ModifierData *md, Object *ob, BMEditMesh *editData,
        DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
  {
-       DerivedMesh *dm;
-       if(derivedData) dm = CDDM_copy(derivedData, 0);
-       else dm = CDDM_from_BMEditMesh(editData, ob->data);
-       CDDM_apply_vert_coords(dm, vertexCos);
-       CDDM_calc_normals(dm);
+       DerivedMesh *dm= get_cddm(md->scene, ob, editData, derivedData, vertexCos);
  
        displaceModifier_do((DisplaceModifierData *)md, ob, dm,
                             vertexCos, numVerts);
@@@ -3656,16 -4469,10 +3663,10 @@@ static void smoothModifier_deformVerts
  }
  
  static void smoothModifier_deformVertsEM(
 -                                       ModifierData *md, Object *ob, EditMesh *editData,
 +                                       ModifierData *md, Object *ob, BMEditMesh *editData,
        DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
  {
-       DerivedMesh *dm;
-       if(derivedData) dm = CDDM_copy(derivedData, 0);
-       else dm = CDDM_from_BMEditMesh(editData, ob->data);
-       CDDM_apply_vert_coords(dm, vertexCos);
-       CDDM_calc_normals(dm);
+       DerivedMesh *dm= get_dm(md->scene, ob, editData, derivedData, NULL, 0);
  
        smoothModifier_do((SmoothModifierData *)md, ob, dm,
                           vertexCos, numVerts);
@@@ -4237,15 -5043,12 +4237,12 @@@ static void castModifier_deformVerts
  }
  
  static void castModifier_deformVertsEM(
 -                                     ModifierData *md, Object *ob, EditMesh *editData,
 +                                     ModifierData *md, Object *ob, BMEditMesh *editData,
           DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
  {
-       DerivedMesh *dm = derivedData;
+       DerivedMesh *dm = get_dm(md->scene, ob, editData, derivedData, NULL, 0);
        CastModifierData *cmd = (CastModifierData *)md;
  
-       if (!dm && ob->type == OB_MESH)
-               dm = CDDM_from_BMEditMesh(editData, ob->data);
        if (cmd->type == MOD_CAST_TYPE_CUBOID) {
                castModifier_cuboid_do(cmd, ob, dm, vertexCos, numVerts);
        } else { /* MOD_CAST_TYPE_SPHERE or MOD_CAST_TYPE_CYLINDER */
@@@ -4643,21 -5442,16 +4636,16 @@@ static void waveModifier_deformVerts
  }
  
  static void waveModifier_deformVertsEM(
 -                                     ModifierData *md, Object *ob, EditMesh *editData,
 +                                     ModifierData *md, Object *ob, BMEditMesh *editData,
           DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
  {
-       DerivedMesh *dm;
+       DerivedMesh *dm= derivedData;
        WaveModifierData *wmd = (WaveModifierData *)md;
  
-       if(!wmd->texture && !wmd->defgrp_name[0] && !(wmd->flag & MOD_WAVE_NORM))
-               dm = derivedData;
-       else if(derivedData) dm = CDDM_copy(derivedData, 0);
-       else dm = CDDM_from_BMEditMesh(editData, ob->data);
-       if(wmd->flag & MOD_WAVE_NORM) {
-               CDDM_apply_vert_coords(dm, vertexCos);
-               CDDM_calc_normals(dm);
-       }
+       if(wmd->flag & MOD_WAVE_NORM)
+               dm= get_cddm(md->scene, ob, editData, dm, vertexCos);
+       else if(wmd->texture || wmd->defgrp_name[0])
+               dm= get_dm(md->scene, ob, editData, dm, NULL, 0);
  
        waveModifier_do(wmd, md->scene, ob, dm, vertexCos, numVerts);
  
@@@ -5896,8 -6683,8 +5879,8 @@@ static void surfaceModifier_deformVerts
                surmd->dm->release(surmd->dm);
  
        /* if possible use/create DerivedMesh */
 -      if(derivedData) surmd->dm = CDDM_copy(derivedData);
 +      if(derivedData) surmd->dm = CDDM_copy(derivedData, 0);
-       else surmd->dm = get_original_dm(md->scene, ob, NULL, 0);
+       else surmd->dm = get_dm(md->scene, ob, NULL, NULL, NULL, 0);
        
        if(!ob->pd)
        {
@@@ -7095,8 -7883,9 +7081,9 @@@ static DerivedMesh * explodeModifier_ex
        int totdup=0,totvert=0,totface=0,totpart=0;
        int i, j, v, mindex=0;
  
 -      totface= dm->getNumFaces(dm);
 +      totface= dm->getNumTessFaces(dm);
        totvert= dm->getNumVerts(dm);
 -      mface= dm->getFaceArray(dm);
++      mface= dm->getTessFaceArray(dm);
        totpart= psmd->psys->totpart;
  
        timestep= psys_get_timestep(&sim);
@@@ -7845,24 -8616,14 +7815,14 @@@ static void shrinkwrapModifier_deformVe
                dm->release(dm);
  }
  
 -static void shrinkwrapModifier_deformVertsEM(ModifierData *md, Object *ob, EditMesh *editData, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
 +static void shrinkwrapModifier_deformVertsEM(ModifierData *md, Object *ob, BMEditMesh *editData, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
  {
-       DerivedMesh *dm = NULL;
+       DerivedMesh *dm = derivedData;
        CustomDataMask dataMask = shrinkwrapModifier_requiredDataMask(ob, md);
  
+       /* ensure we get a CDDM with applied vertex coords */
        if(dataMask)
-       {
-               if(derivedData) dm = CDDM_copy(derivedData, 0);
-               else if(ob->type==OB_MESH) dm = CDDM_from_BMEditMesh(editData, ob->data);
-               else if(ob->type==OB_LATTICE) dm = NULL;
-               else return;
-               if(dm != NULL && (dataMask & (1<<CD_MVERT)))
-               {
-                       CDDM_apply_vert_coords(dm, vertexCos);
-                       CDDM_calc_normals(dm);
-               }
-       }
+               dm= get_cddm(md->scene, ob, editData, dm, vertexCos);
  
        shrinkwrapModifier_deform((ShrinkwrapModifierData*)md, md->scene, ob, dm, vertexCos, numVerts);
  
@@@ -7955,30 -8706,19 +7905,19 @@@ static void simpledeformModifier_deform
  
        SimpleDeformModifier_do((SimpleDeformModifierData*)md, ob, dm, vertexCos, numVerts);
  
-       if(dm)
+       if(dm != derivedData)
                dm->release(dm);
  }
  
 -static void simpledeformModifier_deformVertsEM(ModifierData *md, Object *ob, EditMesh *editData, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
 +static void simpledeformModifier_deformVertsEM(ModifierData *md, Object *ob, BMEditMesh *editData, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
  {
-       DerivedMesh *dm = NULL;
+       DerivedMesh *dm = derivedData;
        CustomDataMask dataMask = simpledeformModifier_requiredDataMask(ob, md);
  
-       /* We implement requiredDataMask but thats not really usefull since mesh_calc_modifiers pass a NULL derivedData or without the modified vertexs applied */
+       /* we implement requiredDataMask but thats not really usefull since
+          mesh_calc_modifiers pass a NULL derivedData */
        if(dataMask)
-       {
-               if(derivedData) dm = CDDM_copy(derivedData, 0);
-               else if(ob->type==OB_MESH) dm = CDDM_from_BMEditMesh(editData, ob->data);
-               else if(ob->type==OB_LATTICE) dm = NULL;
-               else return;
-               if(dm != NULL && (dataMask & CD_MVERT))
-               {
-                       CDDM_apply_vert_coords(dm, vertexCos);
-                       CDDM_calc_normals(dm);
-               }
-       }
+               dm= get_dm(md->scene, ob, editData, dm, NULL, 0);
  
        SimpleDeformModifier_do((SimpleDeformModifierData*)md, ob, dm, vertexCos, numVerts);
  
index b61ada3cf9bdbf0bba2b664f2b4f5ad02d36b282,762ad2432b09704a7f687f80adbbb1c2c5d0d8fe..d7738fc3f5455aa1d6ae862ca9b8a6ee3871982d
@@@ -2396,11 -2428,16 +2429,15 @@@ void object_handle_update(Scene *scene
                        
                        /* includes all keys and modifiers */
                        if(ob->type==OB_MESH) {
 -                              EditMesh *em = BKE_mesh_get_editmesh(ob->data);
 +                              BMEditMesh *em = ((Mesh*)ob->data)->edit_btmesh;
+                               
+                               /* evaluate drivers */
+                               // XXX: should we push this to derivedmesh instead?
+                               BKE_animsys_evaluate_animdata(data_id, adt, ctime, ADT_RECALC_DRIVERS);
+                               
 -                                      // here was vieweditdatamask? XXX
 +                              // here was vieweditdatamask? XXX
                                if(ob->mode & OB_MODE_EDIT) {
                                        makeDerivedMesh(scene, ob, em, CD_MASK_BAREMESH);
 -                                      BKE_mesh_end_editmesh(ob->data, em);
                                } else
                                        makeDerivedMesh(scene, ob, NULL, CD_MASK_BAREMESH);
                        }
index 092c0ff1042d75e160c9d9fe42be1d839803bb12,3997f83ed498344324c328a2b5e67944fc317dbf..8a5e1b24c019b9031229e9d2eaf55c547a0b74f8
@@@ -2926,96 -2215,75 +2926,97 @@@ static CCGDerivedMesh *getCCGDerivedMes
        int index, totvert, totedge, totface;
        int i;
        int vertNum, edgeNum, faceNum;
 +      int *vertOrigIndex, *faceOrigIndex, *polyOrigIndex; /* *edgeOrigIndex - as yet, unused  */
        short *edgeFlags;
        char *faceFlags;
 -      int edgeSize;
 +      int *loopidx = NULL, *vertidx = NULL;
 +      BLI_array_declare(loopidx);
 +      BLI_array_declare(vertidx);
 +      int loopindex, loopindex2;
 +      int edgeSize, has_edge_origindex;
        int gridSize;
 -      int gridFaces;
 +      int gridFaces, gridCuts;
        int gridSideVerts;
        int gridSideEdges;
 +      int numTex, numCol;
        int gridInternalEdges;
 -      MEdge *medge = NULL;
 +      float *w = NULL, one = 1.0f;
 +      WeightTable wtable = {0};
 +      MCol *mcol;
 +      MEdge *medge = NULL, medge2;
        MFace *mface = NULL;
 -      FaceVertWeight *qweight, *tweight;
 +      MPoly *mpoly = NULL;
  
-       DM_from_template(&cgdm->dm, dm, ccgSubSurf_getNumFinalVerts(ss),
 -      DM_from_template(&ccgdm->dm, dm, DM_TYPE_CCGDM,
++      DM_from_template(&cgdm->dm, dm, DM_TYPE_CCGDM,
+                                        ccgSubSurf_getNumFinalVerts(ss),
                                         ccgSubSurf_getNumFinalEdges(ss),
 +                                       ccgSubSurf_getNumFinalFaces(ss),
 +                                       ccgSubSurf_getNumFinalFaces(ss)*4, 
                                         ccgSubSurf_getNumFinalFaces(ss));
 -
 -      ccgdm->dm.getMinMax = ccgDM_getMinMax;
 -      ccgdm->dm.getNumVerts = ccgDM_getNumVerts;
 -      ccgdm->dm.getNumFaces = ccgDM_getNumFaces;
 -
 -      ccgdm->dm.getNumEdges = ccgDM_getNumEdges;
 -      ccgdm->dm.getVert = ccgDM_getFinalVert;
 -      ccgdm->dm.getEdge = ccgDM_getFinalEdge;
 -      ccgdm->dm.getFace = ccgDM_getFinalFace;
 -      ccgdm->dm.copyVertArray = ccgDM_copyFinalVertArray;
 -      ccgdm->dm.copyEdgeArray = ccgDM_copyFinalEdgeArray;
 -      ccgdm->dm.copyFaceArray = ccgDM_copyFinalFaceArray;
 -      ccgdm->dm.getVertData = DM_get_vert_data;
 -      ccgdm->dm.getEdgeData = DM_get_edge_data;
 -      ccgdm->dm.getFaceData = DM_get_face_data;
 -      ccgdm->dm.getVertDataArray = ccgDM_get_vert_data_layer;
 -      ccgdm->dm.getEdgeDataArray = ccgDM_get_edge_data_layer;
 -      ccgdm->dm.getFaceDataArray = ccgDM_get_face_data_layer;
 -      ccgdm->dm.getNumGrids = ccgDM_getNumGrids;
 -      ccgdm->dm.getGridSize = ccgDM_getGridSize;
 -      ccgdm->dm.getGridData = ccgDM_getGridData;
 -      ccgdm->dm.getGridAdjacency = ccgDM_getGridAdjacency;
 -      ccgdm->dm.getGridOffset = ccgDM_getGridOffset;
 -      ccgdm->dm.getPBVH = ccgDM_getPBVH;
 -
 -      ccgdm->dm.getVertCos = ccgdm_getVertCos;
 -      ccgdm->dm.foreachMappedVert = ccgDM_foreachMappedVert;
 -      ccgdm->dm.foreachMappedEdge = ccgDM_foreachMappedEdge;
 -      ccgdm->dm.foreachMappedFaceCenter = ccgDM_foreachMappedFaceCenter;
        
 -      ccgdm->dm.drawVerts = ccgDM_drawVerts;
 -      ccgdm->dm.drawEdges = ccgDM_drawEdges;
 -      ccgdm->dm.drawLooseEdges = ccgDM_drawLooseEdges;
 -      ccgdm->dm.drawFacesSolid = ccgDM_drawFacesSolid;
 -      ccgdm->dm.drawFacesColored = ccgDM_drawFacesColored;
 -      ccgdm->dm.drawFacesTex = ccgDM_drawFacesTex;
 -      ccgdm->dm.drawFacesGLSL = ccgDM_drawFacesGLSL;
 -      ccgdm->dm.drawMappedFaces = ccgDM_drawMappedFaces;
 -      ccgdm->dm.drawMappedFacesTex = ccgDM_drawMappedFacesTex;
 -      ccgdm->dm.drawMappedFacesGLSL = ccgDM_drawMappedFacesGLSL;
 -      ccgdm->dm.drawUVEdges = ccgDM_drawUVEdges;
 -
 -      ccgdm->dm.drawMappedEdgesInterp = ccgDM_drawMappedEdgesInterp;
 -      ccgdm->dm.drawMappedEdges = ccgDM_drawMappedEdges;
 +      numTex = CustomData_number_of_layers(&cgdm->dm.loopData, CD_MLOOPUV);
 +      numCol = CustomData_number_of_layers(&cgdm->dm.loopData, CD_MLOOPCOL);
 +      
 +      if (numTex && CustomData_number_of_layers(&cgdm->dm.faceData, CD_MTFACE) != numTex)
 +              CustomData_from_bmeshpoly(&cgdm->dm.faceData, &cgdm->dm.polyData, &cgdm->dm.loopData, ccgSubSurf_getNumFinalFaces(ss));
 +      else if (numCol && CustomData_number_of_layers(&cgdm->dm.faceData, CD_MCOL) != numCol)
 +              CustomData_from_bmeshpoly(&cgdm->dm.faceData, &cgdm->dm.polyData, &cgdm->dm.loopData, ccgSubSurf_getNumFinalFaces(ss));
 +
 +      cgdm->dm.getMinMax = cgdm_getMinMax;
 +      cgdm->dm.getNumVerts = cgdm_getNumVerts;
 +      cgdm->dm.getNumTessFaces = cgdm_getNumTessFaces;
 +      cgdm->dm.getNumFaces = cgdm_getNumTessFaces;
 +
 +      cgdm->dm.getNumGrids = ccgDM_getNumGrids;
 +      cgdm->dm.getGridSize = ccgDM_getGridSize;
 +      cgdm->dm.getGridData = ccgDM_getGridData;
 +      cgdm->dm.getGridAdjacency = ccgDM_getGridAdjacency;
 +      cgdm->dm.getGridOffset = ccgDM_getGridOffset;
 +      cgdm->dm.getPBVH = ccgDM_getPBVH;
 +
 +      cgdm->dm.newFaceIter = cgdm_newFaceIter;
 +      cgdm->dm.getNumEdges = cgdm_getNumEdges;
 +      cgdm->dm.getVert = cgdm_getFinalVert;
 +      cgdm->dm.getEdge = cgdm_getFinalEdge;
 +      cgdm->dm.getTessFace = cgdm_getFinalFace;
 +      cgdm->dm.copyVertArray = cgdm_copyFinalVertArray;
 +      cgdm->dm.copyEdgeArray = cgdm_copyFinalEdgeArray;
 +      cgdm->dm.copyTessFaceArray = cgdm_copyFinalFaceArray;
 +      cgdm->dm.getVertData = DM_get_vert_data;
 +      cgdm->dm.getEdgeData = DM_get_edge_data;
 +      cgdm->dm.getTessFaceData = DM_get_face_data;
 +      cgdm->dm.getVertDataArray = DM_get_vert_data_layer;
 +      cgdm->dm.getEdgeDataArray = DM_get_edge_data_layer;
 +      cgdm->dm.getTessFaceDataArray = DM_get_tessface_data_layer;
 +
 +      cgdm->dm.getVertCos = cgdm_getVertCos;
 +      cgdm->dm.foreachMappedVert = cgdm_foreachMappedVert;
 +      cgdm->dm.foreachMappedEdge = cgdm_foreachMappedEdge;
 +      cgdm->dm.foreachMappedFaceCenter = cgdm_foreachMappedFaceCenter;
        
 -      ccgdm->dm.release = ccgDM_release;
 +      cgdm->dm.drawVerts = cgdm_drawVerts;
 +      cgdm->dm.drawEdges = cgdm_drawEdges;
 +      cgdm->dm.drawLooseEdges = cgdm_drawLooseEdges;
 +      cgdm->dm.drawFacesSolid = ccgDM_drawFacesSolid;
 +      cgdm->dm.drawFacesColored = cgdm_drawFacesColored;
 +      cgdm->dm.drawFacesTex = cgdm_drawFacesTex;
 +      cgdm->dm.drawFacesGLSL = cgdm_drawFacesGLSL;
 +      cgdm->dm.drawMappedFaces = ccgDM_drawMappedFaces;
 +      cgdm->dm.drawMappedFacesTex = cgdm_drawMappedFacesTex;
 +      cgdm->dm.drawMappedFacesGLSL = cgdm_drawMappedFacesGLSL;
 +      cgdm->dm.drawUVEdges = cgdm_drawUVEdges;
 +
 +      cgdm->dm.drawMappedEdgesInterp = cgdm_drawMappedEdgesInterp;
 +      cgdm->dm.drawMappedEdges = cgdm_drawMappedEdges;
        
 -      ccgdm->ss = ss;
 -      ccgdm->drawInteriorEdges = drawInteriorEdges;
 -      ccgdm->useSubsurfUv = useSubsurfUv;
 +      cgdm->dm.release = cgdm_release;
 +      
 +      cgdm->ss = ss;
 +      cgdm->drawInteriorEdges = drawInteriorEdges;
 +      cgdm->useSubsurfUv = useSubsurfUv;
  
        totvert = ccgSubSurf_getNumVerts(ss);
 -      ccgdm->vertMap = MEM_mallocN(totvert * sizeof(*ccgdm->vertMap), "vertMap");
 +      cgdm->vertMap = MEM_mallocN(totvert * sizeof(*cgdm->vertMap), "vertMap");
        vi = ccgSubSurf_getVertIterator(ss);
        for(; !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
                CCGVert *v = ccgVertIterator_getCurrent(vi);
Simple merge
index e3ecc8ac2a28e71c2104344fafcef7e95216a1ad,6bf347e9bd5c18fd96fc32174ce5dbcd3eb8d3be..a6aaf86f45902691286ef837d549399e520d47ce
  #include "BLI_blenlib.h"
  #include "BLI_math.h"
  #include "BLI_storage_types.h" // for relname flags
 +#include "BLI_cellalloc.h"
  
  #include "BKE_animsys.h"
+ #include "BKE_anim.h"
  #include "BKE_action.h"
  #include "BKE_armature.h"
  #include "BKE_brush.h"
index 596b190307deb1fc1328689e5a4609a508840792,8ed840f0be4832b1e12c5a30b8563c3e400c7abf..72b5aae74b409392bf7885f2179242cc7b0f0f08
@@@ -86,13 -86,12 +86,12 @@@ ELSE(WITH_PYTHON
  ENDIF(WITH_PYTHON)
  
  IF(WIN32)
 -      SET(INC ${INC} ${PTHREADS_INC})
 +  SET(INC ${INC} ${PTHREADS_INC})
  ENDIF(WIN32)
  
- # TODO buildinfo
- IF(BF_BUILDINFO)
+ IF(WITH_BUILDINFO)
 -      ADD_DEFINITIONS(-DNAN_BUILDINFO)
 +  ADD_DEFINITIONS(-DNAN_BUILDINFO)
- ENDIF(BF_BUILDINFO)
+ ENDIF(WITH_BUILDINFO)
  
  BLENDERLIB_NOLIST(bf_editors "${SRC}" "${INC}")
  
index 46af8e5ec3198434a727d2bb529daf701dd7de26,101f0e2074cf29e52d1e389bedaa7e60ce4f0bd9..472eac6b81d7a195b90e9bbfbf911f3c6ddd307b
@@@ -1536,9 -1541,172 +1541,172 @@@ void FONT_OT_case_toggle(wmOperatorTyp
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
  }
  
+ /* **************** Open Font ************** */
+ static void open_init(bContext *C, wmOperator *op)
+ {
+       PropertyPointerRNA *pprop;
+       
+       op->customdata= pprop= MEM_callocN(sizeof(PropertyPointerRNA), "OpenPropertyPointerRNA");
+       uiIDContextProperty(C, &pprop->ptr, &pprop->prop);
+ }
+ static int open_cancel(bContext *C, wmOperator *op)
+ {
+       MEM_freeN(op->customdata);
+       op->customdata= NULL;
+       return OPERATOR_CANCELLED;
+ }
+ static int open_exec(bContext *C, wmOperator *op)
+ {
+       Object *ob = CTX_data_active_object(C);
+       Curve *cu;
+       VFont *font;
+       PropertyPointerRNA *pprop;
+       PointerRNA idptr;
+       char str[FILE_MAX];
+       
+       RNA_string_get(op->ptr, "path", str);
+       font = load_vfont(str);
+       
+       if(!font) {
+               if(op->customdata) MEM_freeN(op->customdata);
+               return OPERATOR_CANCELLED;
+       }
+       
+       if(!op->customdata)
+               open_init(C, op);
+       
+       /* hook into UI */
+       pprop= op->customdata;
+       
+       if(pprop->prop) {
+               /* when creating new ID blocks, use is already 1, but RNA
+                * pointer se also increases user, so this compensates it */
+               font->id.us--;
+               
+               RNA_id_pointer_create(&font->id, &idptr);
+               RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr);
+               RNA_property_update(C, &pprop->ptr, pprop->prop);
+       } else if(ob && ob->type == OB_FONT) {
+               cu = ob->data;
+               id_us_min(&cu->vfont->id);
+               cu->vfont = font;
+       }
+       
+       DAG_id_flush_update(ob->data, OB_RECALC_DATA);
+       WM_event_add_notifier(C, NC_GEOM|ND_DATA|NA_EDITED, ob->data);
+       
+       MEM_freeN(op->customdata);
+       
+       return OPERATOR_FINISHED;
+ }
+ static int open_invoke(bContext *C, wmOperator *op, wmEvent *event)
+ {
+       Object *ob = CTX_data_active_object(C);
+       Curve *cu;
+       VFont *font=NULL;
+       char *path;
+       if (ob && ob->type == OB_FONT) {
+               cu = ob->data;
+               font = cu->vfont;
+       }
+       path = (font && font->name)? font->name: U.fontdir;
+        
+       if(RNA_property_is_set(op->ptr, "path"))
+               return open_exec(C, op);
+       
+       open_init(C, op);
+       
+       RNA_string_set(op->ptr, "path", path);
+       WM_event_add_fileselect(C, op); 
+       return OPERATOR_RUNNING_MODAL;
+ }
+ void FONT_OT_open(wmOperatorType *ot)
+ {
+       /* identifiers */
+       ot->name= "Open";
+       ot->idname= "FONT_OT_open";
+       
+       /* api callbacks */
+       ot->exec= open_exec;
+       ot->invoke= open_invoke;
+       ot->cancel= open_cancel;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       
+       /* properties */
+       WM_operator_properties_filesel(ot, FOLDERFILE|FTFONTFILE, FILE_SPECIAL);
+ }
+ /******************* delete operator *********************/
+ static int font_unlink_poll(bContext *C)
+ {
+       Object *ob = CTX_data_active_object(C);
+       Curve *cu;
+       
+       if (!ED_operator_object_active_editable(C) ) return 0;
+       if (ob->type != OB_FONT) return 0;
+       
+       cu = ob->data;
+       if (cu && strcmp(cu->vfont->name, "<builtin>")==0) return 0;
+       return 1;
+ }
+ static int font_unlink_exec(bContext *C, wmOperator *op)
+ {
+       Object *ob = CTX_data_active_object(C);
+       Curve *cu;
+       VFont *font, *builtin_font;
+               
+       cu = ob->data;
+       font = cu->vfont;
+       
+       if (!font) {
+               BKE_report(op->reports, RPT_ERROR, "No font datablock available to unlink.");
+               return OPERATOR_CANCELLED;
+       }
+       
+       if (strcmp(font->name, "<builtin>")==0) {
+               BKE_report(op->reports, RPT_WARNING, "Can't unlink the default builtin font.");
+               return OPERATOR_FINISHED;
+       }
+       /* revert back to builtin font */
+       builtin_font = get_builtin_font();
+       cu->vfont = builtin_font;
+       id_us_plus(&cu->vfont->id);
+       id_us_min(&font->id);
+       
+       DAG_id_flush_update(ob->data, OB_RECALC_DATA);
+       WM_event_add_notifier(C, NC_GEOM|ND_DATA|NA_EDITED, ob->data);
+       
+       return OPERATOR_FINISHED;
+ }
+ void FONT_OT_unlink(wmOperatorType *ot)
+ {
+       /* identifiers */
+       ot->name= "Unlink";
+       ot->idname= "FONT_OT_unlink";
+       ot->description= "Unlink active font data block.";
+       
+       /* api callbacks */
+       ot->exec= font_unlink_exec;
+       ot->poll= font_unlink_poll;
+ }
  /* **************** undo for font object ************** */
  
 -static void undoFont_to_editFont(void *strv, void *ecu)
 +static void undoFont_to_editFont(void *strv, void *ecu, void *obdata)
  {
        Curve *cu= (Curve *)ecu;
        EditFont *ef= cu->editfont;
index 626062b27a1d04c21f4ade2eaba33382f5a02499,dee831b7fd038b7eb79bafb4ebb636396a5c33f1..dd70181884abeb28dcde1c3844d185d8c661c014
@@@ -1908,8 -3799,8 +1908,7 @@@ void EM_deselect_by_material(EditMesh *
  }
  
  /* **************** NORMALS ************** */
- /* XXX value of select is messed up, it means two things */
- void righthandfaces(EditMesh *em, int select) /* makes faces righthand turning */
 -
+ void EM_recalc_normal_direction(EditMesh *em, int inside, int select) /* makes faces righthand turning */
  {
        EditEdge *eed, *ed1, *ed2, *ed3, *ed4;
        EditFace *efa, *startvl;
index 059e8fb505946a81aa1f727ad25b86634c9d8712,9510e40c6ac92008fd1ad303337edd573a92180c..0e5710386e40dc57fdcf2e058494d8476731fec2
@@@ -106,75 -103,34 +106,77 @@@ static void ringsel_draw(const bContex
        int i;
        tringselOpData *lcd = arg;
        
-       glDisable(GL_DEPTH_TEST);
+       if (lcd->totedge > 0) {
+               glDisable(GL_DEPTH_TEST);
  
-       glPushMatrix();
-       glMultMatrixf(lcd->ob->obmat);
+               glPushMatrix();
+               glMultMatrixf(lcd->ob->obmat);
  
-       glColor3ub(255, 0, 255);
-       glBegin(GL_LINES);
-       for (i=0; i<lcd->totedge; i++) {
-               glVertex3fv(lcd->edges[i][0]);
-               glVertex3fv(lcd->edges[i][1]);
-       }
-       glEnd();
+               glColor3ub(255, 0, 255);
+               glBegin(GL_LINES);
+               for (i=0; i<lcd->totedge; i++) {
+                       glVertex3fv(lcd->edges[i][0]);
+                       glVertex3fv(lcd->edges[i][1]);
+               }
+               glEnd();
  
-       glPopMatrix();
-       glEnable(GL_DEPTH_TEST);
+               glPopMatrix();
+               glEnable(GL_DEPTH_TEST);
+       }
  }
  
 +/*given two opposite edges in a face, finds the ordering of their vertices so
 +  that cut preview lines won't cross each other*/
 +static void edgering_find_order(BMEditMesh *em, BMEdge *lasteed, BMEdge *eed, 
 +                                BMVert *lastv1, BMVert *v[2][2])
 +{
 +      BMIter iter, liter;
 +      BMLoop *l, *l2;
 +      int rev;
 +
 +      l = eed->loop;
 +
 +      /*find correct order for v[1]*/
 +      if (!(BM_Edge_In_Face(l->f, eed) && BM_Edge_In_Face(l->f, lasteed))) {
 +              BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_LOOP, l) {
 +                      if (BM_Edge_In_Face(l->f, eed) && BM_Edge_In_Face(l->f, lasteed))
 +                              break;
 +              }
 +      }
 +      
 +      /*this should never happen*/
 +      if (!l) {
 +              v[0][0] = eed->v1;
 +              v[0][1] = eed->v2;
 +              v[1][0] = lasteed->v1;
 +              v[1][1] = lasteed->v2;
 +              return;
 +      }
 +      
 +      l2 = BM_OtherFaceLoop(l->e, l->f, eed->v1);
 +      rev = (l2 == (BMLoop*)l->head.prev);
 +      while (l2->v != lasteed->v1 && l2->v != lasteed->v2) {
 +              l2 = rev ? (BMLoop*)l2->head.prev : (BMLoop*)l2->head.next;
 +      }
 +
 +      if (l2->v == lastv1) {
 +              v[0][0] = eed->v1;
 +              v[0][1] = eed->v2;
 +      } else {
 +              v[0][0] = eed->v2;
 +              v[0][1] = eed->v1;
 +      }
 +}
 +
  static void edgering_sel(tringselOpData *lcd, int previewlines, int select)
  {
 -      EditMesh *em = lcd->em;
 -      EditEdge *startedge = lcd->eed;
 -      EditEdge *eed;
 -      EditFace *efa;
 -      EditVert *v[2][2];
 +      BMEditMesh *em = lcd->em;
 +      BMEdge *startedge = lcd->eed;
 +      BMEdge *eed, *lasteed;
 +      BMVert *v[2][2], *lastv1;
 +      BMWalker walker;
        float (*edges)[2][3] = NULL;
 -      V_DYNDECLARE(edges);
 +      BLI_array_declare(edges);
        float co[2][3];
        int looking=1, i, tot=0;
        
index 5283e98d9aefb7c86a1db8c2fd4a8eb0c78dcf59,94bdbdc73aa1fa552b0d5d5429c81d631ddd4692..85996b462ede5da910fd6b8ea7c7d5e99b90899a
@@@ -220,12 -168,14 +220,12 @@@ void MESH_OT_flip_normals(struct wmOper
  void MESH_OT_solidify(struct wmOperatorType *ot);
  void MESH_OT_select_nth(struct wmOperatorType *ot);
  
 -
 -extern EditEdge *findnearestedge(ViewContext *vc, int *dist);
  extern void EM_automerge(Scene *scene, Object *obedit, int update);
  void editmesh_select_by_material(EditMesh *em, int index);
- void righthandfaces(EditMesh *em, int select);        /* makes faces righthand turning */
+ void EM_recalc_normal_direction(EditMesh *em, int inside, int select);        /* makes faces righthand turning */
  void EM_select_more(EditMesh *em);
  void selectconnected_mesh_all(EditMesh *em);
 -void faceloop_select(EditMesh *em, EditEdge *startedge, int select);
 +void faceloop_select(struct BMEditMesh *em, struct BMEdge *startedge, int select);
  
  /**
   * findnearestvert
index 85148b128c3fb9bd4e1ccae80e7b1d3cb59ba832,32141005c7cd5474cb8cd990b37e5c95a165bc71..5c5eac0b5d22c3609444295b889fdd3f940b71ec
@@@ -191,12 -192,13 +191,11 @@@ void ED_operatormacros_mesh(void
        WM_operatortype_macro_define(ot, "MESH_OT_extrude");
        otmacro= WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
        RNA_enum_set(otmacro->ptr, "proportional", 0);
 -      RNA_enum_set(otmacro->ptr, "constraint_orientation", V3D_MANIP_NORMAL);
 -      RNA_boolean_set_array(otmacro->ptr, "constraint_axis", constraint_axis);
 +      RNA_enum_set(otm->ptr, "proportional", 0);
 +      RNA_boolean_set(otm->ptr, "mirror", 0);
  
 -      ot= WM_operatortype_append_macro("MESH_OT_extrude_move", "Extrude and Move", OPTYPE_UNDO|OPTYPE_REGISTER);
 -      WM_operatortype_macro_define(ot, "MESH_OT_extrude");
 -      otmacro= WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
 -      RNA_enum_set(otmacro->ptr, "proportional", 0);
 +      RNA_enum_set(otm->ptr, "constraint_orientation", V3D_MANIP_NORMAL);
 +      RNA_boolean_set_array(otm->ptr, "constraint_axis", constraint_axis);*/
  }
  
  /* note mesh keymap also for other space? */
@@@ -297,23 -287,18 +296,25 @@@ void ED_keymap_mesh(wmKeyConfig *keycon
        WM_keymap_add_item(keymap, "MESH_OT_fgon_clear", FKEY, KM_PRESS, KM_SHIFT|KM_ALT, 0);
        
        WM_keymap_add_item(keymap, "MESH_OT_knife_cut", LEFTMOUSE, KM_PRESS, 0, KKEY);
+       
+       WM_keymap_add_item(keymap, "OBJECT_OT_vertex_parent_set", PKEY, KM_PRESS, KM_CTRL, 0);
  
        /* menus */
 -      WM_keymap_add_menu(keymap, "VIEW3D_MT_edit_mesh_specials", WKEY, KM_PRESS, 0, 0);
 -      WM_keymap_add_menu(keymap, "VIEW3D_MT_edit_mesh_faces", FKEY, KM_PRESS, KM_CTRL, 0);
 -      WM_keymap_add_menu(keymap, "VIEW3D_MT_edit_mesh_edges", EKEY, KM_PRESS, KM_CTRL, 0);
 -      WM_keymap_add_menu(keymap, "VIEW3D_MT_edit_mesh_vertices", VKEY, KM_PRESS, KM_CTRL, 0);
 -      WM_keymap_add_menu(keymap, "VIEW3D_MT_hook", HKEY, KM_PRESS, KM_CTRL, 0);
 -      WM_keymap_add_menu(keymap, "VIEW3D_MT_uv_map", UKEY, KM_PRESS, 0, 0);
 -      WM_keymap_add_menu(keymap, "VIEW3D_MT_vertex_group", GKEY, KM_PRESS, KM_CTRL, 0);
 +      kmi= WM_keymap_add_item(keymap, "WM_OT_call_menu", WKEY, KM_PRESS, 0, 0);
 +      RNA_string_set(kmi->ptr, "name", "VIEW3D_MT_edit_mesh_specials");
 +
 +      kmi= WM_keymap_add_item(keymap, "WM_OT_call_menu", FKEY, KM_PRESS, KM_CTRL, 0);
 +      RNA_string_set(kmi->ptr, "name", "VIEW3D_MT_edit_mesh_faces");
        
 +      kmi= WM_keymap_add_item(keymap, "WM_OT_call_menu", EKEY, KM_PRESS, KM_CTRL, 0);
 +      RNA_string_set(kmi->ptr, "name", "VIEW3D_MT_edit_mesh_edges");
 +
 +      kmi= WM_keymap_add_item(keymap, "WM_OT_call_menu", VKEY, KM_PRESS, KM_CTRL, 0);
 +      RNA_string_set(kmi->ptr, "name", "VIEW3D_MT_edit_mesh_vertices");
 +
 +      kmi= WM_keymap_add_item(keymap, "WM_OT_call_menu", UKEY, KM_PRESS, 0, 0);
 +      RNA_string_set(kmi->ptr, "name", "VIEW3D_MT_uv_map");
 +
        ED_object_generic_keymap(keyconf, keymap, TRUE);
  }
  
index 99c2bc65ee4c4cdde55f15104128ab8c018e0aea,269fc2785819df9324c8904ad205ebcccec6c522..9421a8befc1136b414555e6e43f9a2a0fd954178
  #include "BKE_object.h"
  #include "BKE_utildefines.h"
  #include "BKE_report.h"
 +#include "BKE_tessmesh.h"
  
- #include "RE_pipeline.h"
- #include "RE_shader_ext.h"
- #include "PIL_time.h"
- #include "IMB_imbuf_types.h"
- #include "IMB_imbuf.h"
- #include "GPU_draw.h"
  #include "BLO_sys_types.h" // for intptr_t support
  
  #include "ED_mesh.h"
index 9ac2b1393300333c4f1d9837d032336847af9157,0a94de255cb416c2733149b31cb199d7cc76a466..d6da69f4a3a4178ff26994471489814431253755
@@@ -5,7 -5,8 +5,8 @@@ sources = env.Glob('*.c'
  
  incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
  incs += ' ../../windowmanager #/intern/guardedalloc'
 -incs += ' ../../makesrna ../../python ../../ikplugin'
 +incs += ' ../../makesrna ../../python ../../ikplugin ../../bmesh'
+ incs += ' ../../render/extern/include ../../gpu' # for object_bake.c
  
  defs = []
  
index 2c02954b7cb232fafd7edfdd3087c61a947a487d,28ddf07fe8e3a354bdff2e4c662b59d34a6d7e49..a78b3377c1f7ec041cb561fd7c79ce87e6cdd849
@@@ -270,10 -310,10 +310,10 @@@ static Object *effector_add_type(bConte
                BLI_addtail(curve_get_editcurve(ob), add_nurbs_primitive(C, CU_NURBS|CU_PRIM_PATH, 1));
  
                if(!enter_editmode)
 -                      ED_object_exit_editmode(C, EM_FREEDATA|EM_DO_UNDO);
 +              ED_object_exit_editmode(C, EM_FREEDATA|EM_DO_UNDO);
        }
        else {
-               ob= ED_object_add_type(C, OB_EMPTY, view_align, FALSE);
+               ob= ED_object_add_type(C, OB_EMPTY, loc, rot, FALSE);
                rename_id(&ob->id, "Field");
  
                switch(type) {
index 084b092e320cfecb1eeef3853e9719c9db2af29e,54fa3f51eb6f288cbb517bca8d34a492ae4a1c55..364fc41045124d6a41b82c257bd7890b73c9c6cd
@@@ -1879,16 -1890,13 +1881,18 @@@ static int object_mode_set_compat(bCont
  {
        ObjectMode mode = RNA_enum_get(op->ptr, "mode");
  
 -      if(ob) {
 -              if(mode == OB_MODE_OBJECT)
 -                      return 1;
++      if(mode & OB_MODE_OBJECT)
++              return 1;
 +      if(ob) {
                switch(ob->type) {
-                       if(mode & OB_MODE_OBJECT)
-                               return 1;
 +              case OB_EMPTY:
 +              case OB_LAMP:
 +              case OB_CAMERA:
 +                      return 0;
++
                case OB_MESH:
-                       if(mode & (     OB_MODE_OBJECT|OB_MODE_EDIT|OB_MODE_SCULPT|OB_MODE_VERTEX_PAINT|OB_MODE_WEIGHT_PAINT|OB_MODE_TEXTURE_PAINT|OB_MODE_PARTICLE_EDIT))
+                       if(mode & (OB_MODE_EDIT|OB_MODE_SCULPT|OB_MODE_VERTEX_PAINT|OB_MODE_WEIGHT_PAINT|OB_MODE_TEXTURE_PAINT|OB_MODE_PARTICLE_EDIT))
                                return 1;
                        return 0;
                case OB_CURVE:
index 15ab98a14bdd4d3e347fdc852e917bb60332e655,95fbcdd4223cabc4e72b9ba97e8c1b4fb381517b..9d95c9dfe28a77e96373ef4bf891cae5963736ed
@@@ -1215,29 -1217,27 +1217,27 @@@ static int make_links_data_exec(bContex
                                for(a=0; a<ob->totcol; a++) {
                                        Material *ma= give_current_material(ob, a+1);
                                        assign_material(obt, ma, a+1);  /* also works with ma==NULL */
 -                              }
 +                                              }
                                break;
                        case MAKE_LINKS_ANIMDATA:
- #if 0 // XXX old animation system
-                                       if(obt->ipo) obt->ipo->id.us--;
-                                       obt->ipo= ob->ipo;
-                                       if(obt->ipo) {
-                                               id_us_plus((ID *)obt->ipo);
-                                               do_ob_ipo(scene, obt);
-                                       }
- #endif // XXX old animation system
+                               BKE_copy_animdata_id((ID *)obt, (ID *)ob);
+                               BKE_copy_animdata_id((ID *)obt->data, (ID *)ob->data);
                                break;
                        case MAKE_LINKS_DUPLIGROUP:
 -                              if(ob->dup_group) ob->dup_group->id.us--;
 -                              obt->dup_group= ob->dup_group;
 -                              if(obt->dup_group) {
 -                                      id_us_plus((ID *)obt->dup_group);
 -                                      obt->transflag |= OB_DUPLIGROUP;
 -                              }
 +                                      if(ob->dup_group) ob->dup_group->id.us--;
 +                                      obt->dup_group= ob->dup_group;
 +                                      if(obt->dup_group) {
 +                                              id_us_plus((ID *)obt->dup_group);
 +                                              obt->transflag |= OB_DUPLIGROUP;
 +                                      }
                                break;
-                               }
-                                       }
-                               }
+                       case MAKE_LINKS_MODIFIERS:
+                               object_link_modifiers(obt, ob);
+                               obt->recalc |= OB_RECALC;
+                               break;
+                       }
+               }
+       }
        CTX_DATA_END;
  
        DAG_ids_flush_update(0);
index bf13370fbfd4443f07f3d276b1a915d7e5955218,c510a28b7ad5f10863a6c3af730568b5b5e9dbb0..5ac843f796c738a1f688ecda1103bda622c8a889
@@@ -3403,13 -3343,13 +3343,13 @@@ static void brush_edit_apply(bContext *
                        recalc_lengths(edit);
  
                if(ELEM(pset->brushtype, PE_BRUSH_ADD, PE_BRUSH_CUT) && (added || removed)) {
-                               if(pset->brushtype == PE_BRUSH_ADD && (pset->flag & PE_X_MIRROR))
-                                       PE_mirror_x(scene, ob, 1);
+                       if(pset->brushtype == PE_BRUSH_ADD && pe_x_mirror(ob))
+                               PE_mirror_x(scene, ob, 1);
  
 -                      update_world_cos(ob,edit);
 -                      psys_free_path_cache(NULL, edit);
 -                      DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
 -              }
 +                              update_world_cos(ob,edit);
 +                              psys_free_path_cache(NULL, edit);
 +                              DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
 +                      }
                else
                        PE_update_object(scene, ob, 1);
  
index 31785f682733b74935e02831bd4570573646dc9d,3fca79cd2f05c9525b0822e7501b904ae6710123..759d4cfd0fd6b8c17dd2b02921133c6c3427e4db
@@@ -1371,11 -1361,11 +1375,11 @@@ static void mesh_foreachScreenEdge__map
                        view3d_project_short_clip(data->vc.ar, v0co, s[0], 1);
                        view3d_project_short_clip(data->vc.ar, v1co, s[1], 1);
                } else {
 -                      view3d_project_short_noclip(data->vc.ar, v0co, s[0]);
 -                      view3d_project_short_noclip(data->vc.ar, v1co, s[1]);
 +                      project_short_noclip(data->vc.ar, v1_co, s[0]);
 +                      project_short_noclip(data->vc.ar, v2_co, s[1]);
  
                        if (data->clipVerts==2) {
-                 if (!(s[0][0]>=0 && s[0][1]>= 0 && s[0][0]<data->vc.ar->winx && s[0][1]<data->vc.ar->winy)) 
+                               if (!(s[0][0]>=0 && s[0][1]>= 0 && s[0][0]<data->vc.ar->winx && s[0][1]<data->vc.ar->winy))
                                        if (!(s[1][0]>=0 && s[1][1]>= 0 && s[1][0]<data->vc.ar->winx && s[1][1]<data->vc.ar->winy)) 
                                                return;
                        }
@@@ -1655,87 -1576,15 +1659,20 @@@ static void draw_dm_verts__mapFunc(voi
        }
  }
  
- /* disabled because it crashes combined with e.g. subsurf modifier,
-  * the derivedmesh can't be assumed to be an EditMeshDerivedMesh,
-  * nor should this struct be copied around, it should be defined in
-  * a single place only to avoid them getting out of sync */
- #if 0
- /* originally defined in DerivedMesh.c */
- typedef struct {
-       DerivedMesh dm;
-       EditMesh *em;
-       float (*vertexCos)[3];
-       float (*vertexNos)[3];
-       float (*faceNos)[3];
- } EditMeshDerivedMesh;
- #endif
 -static void draw_dm_verts(DerivedMesh *dm, int sel, EditVert *eve_act)
 +static void draw_dm_verts(BMEditMesh *em, DerivedMesh *dm, int sel, BMVert *eve_act)
  {
 -      struct { int sel; EditVert *eve_act; } data;
 +      struct { BMEditMesh *em; int sel; BMVert *eve_act; } data;
-       //GPUBuffer *buffer;
-       //float *varray;
        data.sel = sel;
        data.eve_act = eve_act;
 +      data.em = em;
 +      
 +      bglBegin(GL_POINTS);
 +      dm->foreachMappedVert(dm, draw_dm_verts__mapFunc,&nb