2.50: svn merge https://svn.blender.org/svnroot/bf-blender/trunk/blender -r17853...
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Mon, 26 Jan 2009 08:34:40 +0000 (08:34 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Mon, 26 Jan 2009 08:34:40 +0000 (08:34 +0000)
149 files changed:
1  2 
CMakeLists.txt
SConstruct
config/darwin-config.py
config/irix6-config.py
config/linux2-config.py
config/sunos5-config.py
config/win32-mingw-config.py
config/win32-vc-config.py
extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.cpp
extern/libopenjpeg/SConscript
extern/libopenjpeg/openjpeg.h
projectfiles_vc9/blender/blender.vcproj
release/scripts/ac3d_import.py
release/scripts/animation_bake_constraints.py
release/scripts/bpymodules/BPyMesh.py
release/scripts/bpymodules/dxfLibrary.py
release/scripts/export_fbx.py
release/scripts/help_bpy_api.py
release/scripts/help_browser.py
release/scripts/help_getting_started.py
release/scripts/help_manual.py
release/scripts/help_release_notes.py
release/scripts/help_tutorials.py
release/scripts/help_web_blender.py
release/scripts/help_web_devcomm.py
release/scripts/help_web_eshop.py
release/scripts/help_web_usercomm.py
release/scripts/import_web3d.py
release/scripts/mesh_edges2curves.py
release/scripts/scripttemplate_background_job.py
release/scripts/uvcalc_follow_active_coords.py
release/scripts/uvcalc_quad_clickproj.py
release/scripts/vertexpaint_from_material.py
source/blender/blenkernel/BKE_global.h
source/blender/blenkernel/SConscript
source/blender/blenkernel/intern/collision.c
source/blender/blenkernel/intern/constraint.c
source/blender/blenkernel/intern/effect.c
source/blender/blenkernel/intern/image.c
source/blender/blenkernel/intern/particle_system.c
source/blender/blenlib/BLI_arithb.h
source/blender/blenlib/intern/arithb.c
source/blender/blenlib/intern/graph.c
source/blender/blenloader/intern/readfile.c
source/blender/blenpluginapi/iff.h
source/blender/editors/animation/anim_markers.c
source/blender/editors/space_file/SConscript
source/blender/editors/space_file/filelist.c
source/blender/editors/space_view3d/view3d_draw.c
source/blender/editors/transform/transform_snap.c
source/blender/gpu/intern/gpu_material.c
source/blender/imbuf/IMB_imbuf_types.h
source/blender/imbuf/intern/IMB_jp2.h
source/blender/imbuf/intern/jp2.c
source/blender/imbuf/intern/openexr/CMakeLists.txt
source/blender/imbuf/intern/readimage.c
source/blender/imbuf/intern/util.c
source/blender/imbuf/intern/writeimage.c
source/blender/makesdna/DNA_action_types.h
source/blender/makesdna/DNA_actuator_types.h
source/blender/makesdna/DNA_scene_types.h
source/blender/nodes/CMakeLists.txt
source/blender/nodes/SConscript
source/blender/nodes/intern/CMP_nodes/CMP_filter.c
source/blender/radiosity/intern/source/radfactors.c
source/blender/radiosity/intern/source/radrender.c
source/blender/readblenfile/intern/BLO_readblenfile.c
source/blender/render/intern/source/occlusion.c
source/blender/render/intern/source/pipeline.c
source/blender/render/intern/source/rendercore.c
source/blender/render/intern/source/shadeinput.c
source/creator/creator.c
source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
source/gameengine/BlenderRoutines/KX_BlenderInputDevice.h
source/gameengine/Converter/BL_ActionActuator.cpp
source/gameengine/Converter/BL_ActionActuator.h
source/gameengine/Converter/BL_ShapeActionActuator.cpp
source/gameengine/Converter/BL_ShapeActionActuator.h
source/gameengine/Converter/KX_ConvertActuators.cpp
source/gameengine/Converter/KX_ConvertSensors.cpp
source/gameengine/Expressions/PyObjectPlus.cpp
source/gameengine/Expressions/PyObjectPlus.h
source/gameengine/Expressions/Value.cpp
source/gameengine/Expressions/Value.h
source/gameengine/GameLogic/SCA_2DFilterActuator.cpp
source/gameengine/GameLogic/SCA_ActuatorSensor.cpp
source/gameengine/GameLogic/SCA_ActuatorSensor.h
source/gameengine/GameLogic/SCA_DelaySensor.cpp
source/gameengine/GameLogic/SCA_DelaySensor.h
source/gameengine/GameLogic/SCA_IInputDevice.h
source/gameengine/GameLogic/SCA_ILogicBrick.cpp
source/gameengine/GameLogic/SCA_ILogicBrick.h
source/gameengine/GameLogic/SCA_ISensor.cpp
source/gameengine/GameLogic/SCA_ISensor.h
source/gameengine/GameLogic/SCA_JoystickSensor.cpp
source/gameengine/GameLogic/SCA_JoystickSensor.h
source/gameengine/GameLogic/SCA_KeyboardSensor.cpp
source/gameengine/GameLogic/SCA_KeyboardSensor.h
source/gameengine/GameLogic/SCA_MouseSensor.cpp
source/gameengine/GameLogic/SCA_MouseSensor.h
source/gameengine/GameLogic/SCA_PropertyActuator.cpp
source/gameengine/GameLogic/SCA_PropertyActuator.h
source/gameengine/GameLogic/SCA_PropertySensor.cpp
source/gameengine/GameLogic/SCA_PropertySensor.h
source/gameengine/GameLogic/SCA_PythonController.cpp
source/gameengine/GameLogic/SCA_PythonController.h
source/gameengine/GameLogic/SCA_RandomActuator.cpp
source/gameengine/GameLogic/SCA_RandomActuator.h
source/gameengine/GameLogic/SCA_RandomSensor.cpp
source/gameengine/GameLogic/SCA_RandomSensor.h
source/gameengine/GamePlayer/ghost/CMakeLists.txt
source/gameengine/GamePlayer/ghost/GPG_Application.cpp
source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
source/gameengine/GamePlayer/ghost/Makefile
source/gameengine/GamePlayer/ghost/SConscript
source/gameengine/Ketsji/KX_BulletPhysicsController.cpp
source/gameengine/Ketsji/KX_BulletPhysicsController.h
source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp
source/gameengine/Ketsji/KX_GameObject.cpp
source/gameengine/Ketsji/KX_IPhysicsController.cpp
source/gameengine/Ketsji/KX_IPhysicsController.h
source/gameengine/Ketsji/KX_KetsjiEngine.cpp
source/gameengine/Ketsji/KX_OdePhysicsController.cpp
source/gameengine/Ketsji/KX_OdePhysicsController.h
source/gameengine/Ketsji/KX_PolyProxy.cpp
source/gameengine/Ketsji/KX_PythonInit.cpp
source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp
source/gameengine/Ketsji/KX_SCA_DynamicActuator.h
source/gameengine/Ketsji/KX_SumoPhysicsController.cpp
source/gameengine/Ketsji/KX_SumoPhysicsController.h
source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
source/gameengine/Physics/Bullet/CcdPhysicsController.h
source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h
source/gameengine/Physics/common/PHY_DynamicTypes.h
source/gameengine/PyDoc/BL_ActionActuator.py
source/gameengine/PyDoc/BL_ShapeActionActuator.py
source/gameengine/PyDoc/KX_ActuatorSensor.py
source/gameengine/PyDoc/SCA_DelaySensor.py
source/gameengine/PyDoc/SCA_ILogicBrick.py
source/gameengine/PyDoc/SCA_ISensor.py
source/gameengine/PyDoc/SCA_JoystickSensor.py
source/gameengine/PyDoc/SCA_KeyboardSensor.py
source/gameengine/PyDoc/SCA_MouseSensor.py
source/gameengine/PyDoc/SCA_PropertyActuator.py
source/gameengine/PyDoc/SCA_PropertySensor.py
source/gameengine/PyDoc/SCA_PythonController.py
source/gameengine/PyDoc/SCA_RandomActuator.py
source/nan_definitions.mk

diff --cc CMakeLists.txt
@@@ -175,7 -175,7 +175,7 @@@ IF(UNIX
  
    SET(FFMPEG /usr)
    SET(FFMPEG_INC ${FFMPEG}/include)
--  SET(FFMPEG_LIB avformat avcodec avutil)
++  SET(FFMPEG_LIB avformat avcodec avutil avdevice swscale)
    SET(FFMPEG_LIBPATH ${FFMPEG}/lib)
  
    SET(JPEG_LIB jpeg)
diff --cc SConstruct
@@@ -113,8 -115,8 +113,9 @@@ if toolset
                env.Tool('mstoolkit', ['tools'])
        else:
                env = BlenderEnvironment(tools=[toolset], ENV = os.environ)
 -              if env:
 -                      btools.SetupSpawn(env)
++              # xxx commented out, as was supressing warnings under mingw..
 +              #if env:
 +              #       btools.SetupSpawn(env)
  else:
        env = BlenderEnvironment(ENV = os.environ)
  
@@@ -323,10 -321,10 +324,15 @@@ if not quickie and do_clean
                                print "remove file %s"%(B.root_build_dir+entry)
                                os.remove(B.root_build_dir+entry)
                for confile in ['extern/ffmpeg/config.mak', 'extern/x264/config.mak',
--                              'extern/xvidcore/build/generic/platform.inc']:
++                              'extern/xvidcore/build/generic/platform.inc', 'extern/ffmpeg/include']:
                        if os.path.exists(confile):
                                print "clean file %s"%confile
--                              os.remove(confile)
++                              if os.path.isdir(confile):
++                                      for root, dirs, files in os.walk(confile):
++                                              for name in files:
++                                                      os.remove(os.path.join(root, name))
++                              else:
++                                      os.remove(confile)
                print B.bc.OKGREEN+'...done'+B.bc.ENDC
        else:
                print B.bc.HEADER+'Already Clean, nothing to do.'+B.bc.ENDC
@@@ -40,7 -40,7 +40,11 @@@ else
  # enable ffmpeg  support
  WITH_BF_FFMPEG = True  # -DWITH_FFMPEG
  BF_FFMPEG = "#extern/ffmpeg"
--BF_FFMPEG_INC = '${BF_FFMPEG}/include'
++# trick : The version of ffmpeg in extern/ffmpeg uses explicit libav.. directory in #include statements
++#         To keep Blender compatible with older versions, I add ${BF_FFMPEG} to the inc dir so that ffmpeg
++#         finds the files directly in extern/ffmpeg/libav... while blender finds them in
++#         extern/ffmpeg/include. 
++BF_FFMPEG_INC = '${BF_FFMPEG}/include ${BF_FFMPEG}'
  if USE_SDK==True:
        BF_FFMPEG_EXTRA = '-isysroot '+MACOSX_SDK+' -mmacosx-version-min='+MAC_MIN_VERS
  #BF_FFMPEG_LIBPATH='${BF_FFMPEG}/lib'
@@@ -142,7 -146,7 +142,7 @@@ WITH_BF_BINRELOC = 'false
  WITH_BF_FFMPEG = 'true'  # -DWITH_FFMPEG
  # Uncomment the following two lines to use system's ffmpeg
  BF_FFMPEG = LCGDIR+'/ffmpeg'
--BF_FFMPEG_LIB = 'avformat avcodec swscale avutil faad faac vorbis x264 ogg mp3lame z'
++BF_FFMPEG_LIB = 'avformat avcodec swscale avutil avdevice faad faac vorbis x264 ogg mp3lame z'
  BF_FFMPEG_INC = '${BF_FFMPEG}/include'
  BF_FFMPEG_LIBPATH='${BF_FFMPEG}/lib'
  
@@@ -155,7 -159,7 +155,7 @@@ BF_OGG_LIB = 'ogg vorbis theoraenc theo
  WITH_BF_OPENJPEG = 'false' 
  BF_OPENJPEG = '#extern/libopenjpeg'
  BF_OPENJPEG_LIB = ''
--BF_OPENJPEG_INC = '${BF_OPENJPEG}/include'
++BF_OPENJPEG_INC = '${BF_OPENJPEG}'
  BF_OPENJPEG_LIBPATH='${BF_OPENJPEG}/lib'
  
  WITH_BF_REDCODE = 'false'  
@@@ -136,8 -139,8 +136,13 @@@ BF_FFMPEG = '#extern/ffmpeg
  BF_FFMPEG_LIB = ''
  # Uncomment the following two lines to use system's ffmpeg
  # BF_FFMPEG = '/usr'
--# BF_FFMPEG_LIB = 'avformat avcodec swscale avutil'
--BF_FFMPEG_INC = '${BF_FFMPEG}/include'
++# BF_FFMPEG_LIB = 'avformat avcodec swscale avutil avdevice'
++# trick : The version of ffmpeg in extern/ffmpeg uses explicit libav.. directory in #include statements
++#         To keep Blender compatible with older version, I add ${BF_FFMPEG} to the inc dir so that ffmpeg
++#         finds the files directly in extern/ffmpeg/libav... while blender finds them in
++#         extern/ffmpeg/include. When using system ffmpeg, you don't need that, assuming the system library
++#         still use the flat directory model, otherwise will not compile anyway
++BF_FFMPEG_INC = '${BF_FFMPEG}/include ${BF_FFMPEG}'
  BF_FFMPEG_LIBPATH='${BF_FFMPEG}/lib'
  
  # enable ogg, vorbis and theora in ffmpeg
@@@ -149,13 -152,13 +154,14 @@@ BF_OGG_LIB = 'ogg vorbis theoraenc theo
  WITH_BF_OPENJPEG = True 
  BF_OPENJPEG = '#extern/libopenjpeg'
  BF_OPENJPEG_LIB = ''
--BF_OPENJPEG_INC = '${BF_OPENJPEG}/include'
++BF_OPENJPEG_INC = '${BF_OPENJPEG}'
  BF_OPENJPEG_LIBPATH='${BF_OPENJPEG}/lib'
  
  WITH_BF_REDCODE = False  
  BF_REDCODE = '#extern/libredcode'
  BF_REDCODE_LIB = ''
--BF_REDCODE_INC = '${BF_REDCODE}/include'
++# BF_REDCODE_INC = '${BF_REDCODE}/include'
++BF_REDCODE_INC = '${BF_REDCODE}/../' #C files request "libredcode/format.h" which is in "#extern/libredcode/format.h", stupid but compiles for now.
  BF_REDCODE_LIBPATH='${BF_REDCODE}/lib'
  
  # Mesa Libs should go here if your using them as well....
@@@ -131,7 -131,7 +131,7 @@@ WITH_BF_FFMPEG = False  # -DWITH_FFMPE
  BF_FFMPEG = '/usr/local'
  BF_FFMPEG_INC = '${BF_FFMPEG}/include'
  BF_FFMPEG_LIBPATH='${BF_FFMPEG}/lib'
--BF_FFMPEG_LIB = 'avformat avcodec avutil'
++BF_FFMPEG_LIB = 'avformat avcodec avutil avdevice'
  
  # Mesa Libs should go here if your using them as well....
  WITH_BF_STATICOPENGL = False
@@@ -1,12 -1,15 +1,14 @@@
  LCGDIR = '#../lib/windows'
  LIBDIR = "${LCGDIR}"
  
 -WITH_BF_VERSE = False
 -BF_VERSE_INCLUDE = "#extern/verse/dist"
 -
  BF_PYTHON = LIBDIR + '/python'
  BF_PYTHON_VERSION = '2.5'
++WITH_BF_STATICPYTHON = False
  BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}'
  BF_PYTHON_BINARY = 'python'
  BF_PYTHON_LIB = 'python25'
  BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib/lib25_vs2005'
++BF_PYTHON_LIB_STATIC = '${BF_PYTHON}/lib/lib25_vs2005/libpython25.a'
  
  WITH_BF_OPENAL = True
  WITH_BF_STATICOPENAL = False
@@@ -18,7 -21,7 +20,7 @@@ BF_OPENAL_LIBPATH = '${BF_OPENAL}/lib
  BF_OPENAL_LIB_STATIC = '${BF_OPENAL}/lib/libopenal.a'
  
  WITH_BF_FFMPEG = False
--BF_FFMPEG_LIB = 'avformat swscale avcodec avutil xvidcore x264'
++BF_FFMPEG_LIB = 'avformat swscale avcodec avutil avdevice xvidcore x264'
  BF_FFMPEG_LIBPATH = LIBDIR + '/gcc/ffmpeg/lib'
  BF_FFMPEG_INC =  LIBDIR + '/gcc/ffmpeg/include'
  
@@@ -150,6 -153,6 +150,10 @@@ BF_QUICKTIME_LIB = 'qtmlClient
  BF_QUICKTIME_LIBPATH = '${BF_QUICKTIME}/Libraries'
  
  WITH_BF_OPENJPEG = True 
++BF_OPENJPEG = '#extern/libopenjpeg'
++BF_OPENJPEG_LIB = ''
++BF_OPENJPEG_INC = '${BF_OPENJPEG}'
++BF_OPENJPEG_LIBPATH='${BF_OPENJPEG}/lib'
  
  WITH_BF_REDCODE = False  
  BF_REDCODE_INC = '#extern'
@@@ -49,8 -49,8 +49,6 @@@ void  btCompoundShape::addChildShape(con
        child.m_childShapeType = shape->getShapeType();
        child.m_childMargin = shape->getMargin();
  
--      m_children.push_back(child);
--
        //extend the local aabbMin/aabbMax
        btVector3 localAabbMin,localAabbMax;
        shape->getAabb(localTransform,localAabbMin,localAabbMax);
        if (m_dynamicAabbTree)
        {
                const btDbvtVolume      bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax);
--              int index = m_children.size()-1;
++              int index = m_children.size();
                child.m_node = m_dynamicAabbTree->insert(bounds,(void*)index);
        }
  
++      m_children.push_back(child);
  }
  
  void btCompoundShape::removeChildShapeByIndex(int childShapeIndex)
@@@ -6,9 -6,9 +6,12 @@@ Import('env'
  
  sources = env.Glob('*.c')
  incs = '.'
++flags = []
++defs = []
  
  if env['OURPLATFORM'] == 'win32-vc':
        flags = []
++      defs.append('OPJ_STATIC')
  else:
        flags = ['-Wall', '-O3', '-ffast-math', '-std=c99']
  
@@@ -19,6 -19,6 +22,6 @@@ if not env['OURPLATFORM'] == 'win32-vc'
  
  oj_env.BlenderLib ( libname='extern_openjpeg', 
                      sources=sources, includes=Split(incs),
--                    defines=[],
 -                    libtype=['core','intern','player'],
 -                    priority=[10, 10, 300], compileflags = flags)
++                    defines=defs,
 +                    libtype=['extern'],
 +                    priority=[10], compileflags = flags)
  ==========================================================
  */
  
--#if defined(OPJ_STATIC) || !(defined(WIN32) || defined(__WIN32__))
  #define OPJ_API
  #define OPJ_CALLCONV
--#else
--#define OPJ_CALLCONV __stdcall
--/*
--The following ifdef block is the standard way of creating macros which make exporting 
--from a DLL simpler. All files within this DLL are compiled with the OPJ_EXPORTS
--symbol defined on the command line. this symbol should not be defined on any project
--that uses this DLL. This way any other project whose source files include this file see 
--OPJ_API functions as being imported from a DLL, wheras this DLL sees symbols
--defined with this macro as being exported.
--*/
--#ifdef OPJ_EXPORTS
--#define OPJ_API __declspec(dllexport)
--#else
--#define OPJ_API __declspec(dllimport)
--#endif /* OPJ_EXPORTS */
--#endif /* !OPJ_STATIC || !WIN32 */
  
  #ifndef __cplusplus
  #if defined(HAVE_STDBOOL_H)
@@@ -73,7 -73,7 +73,7 @@@
                        <Tool\r
                                Name="VCLinkerTool"\r
                                AdditionalOptions="/MACHINE:I386"\r
--                              AdditionalDependencies="SDL.lib freetype2ST.lib gnu_gettext.lib qtmlClient.lib openal_static.lib ws2_32.lib dxguid.lib opengl32.lib libjpeg.lib glu32.lib vfw32.lib winmm.lib libpng_st.lib zlib.lib python25.lib pthreadVSE2.lib pthreadVC2.lib libtiff.lib Half.lib Iex.lib IlmImf.lib Imath.lib IlmThread.lib avcodec-51.lib avformat-52.lib avutil-49.lib swscale-0.lib"\r
++                              AdditionalDependencies="SDL.lib freetype2ST.lib gnu_gettext.lib qtmlClient.lib openal_static.lib ws2_32.lib dxguid.lib opengl32.lib libjpeg.lib glu32.lib vfw32.lib winmm.lib libpng_st.lib zlib.lib python25.lib pthreadVSE2.lib pthreadVC2.lib libtiff.lib Half.lib Iex.lib IlmImf.lib Imath.lib IlmThread.lib avcodec-51.lib avformat-52.lib avutil-49.lib swscale-0.lib avdevice-52.lib"\r
                                ShowProgress="0"\r
                                OutputFile="..\..\bin\blender.exe"\r
                                LinkIncremental="1"\r
@@@ -10,7 -10,7 +10,7 @@@ Tip: 'Import an AC3D (.ac) file.
  __author__ = "Willian P. Germano"
  __url__ = ("blender", "blenderartists.org", "AC3D's homepage, http://www.ac3d.org",
        "PLib 3d gaming lib, http://plib.sf.net")
--__version__ = "2.43.1 2007-02-21"
++__version__ = "2.48.1 2009-01-11"
  
  __bpydoc__ = """\
  This script imports AC3D models into Blender.
@@@ -31,6 -31,6 +31,7 @@@ Known issues:<br
  Config Options:<br>
      - display transp (toggle): if "on", objects that have materials with alpha < 1.0 are shown with translucency (transparency) in the 3D View.<br>
      - subdiv (toggle): if "on", ac3d objects meant to be subdivided receive a SUBSURF modifier in Blender.<br>
++    - emis as mircol: store the emissive rgb color from AC3D as mirror color in Blender -- this is a hack to preserve the values and be able to export them using the equivalent option in the exporter.<br>
      - textures dir (string): if non blank, when imported texture paths are
  wrong in the .ac file, Blender will also look for them at this dir.
  
@@@ -50,11 -50,11 +51,12 @@@ users can configure (see config option
  # --------------------------------------------------------------------------
  # Thanks: Melchior Franz for extensive bug testing and reporting, making this
  # version cope much better with old or bad .ac files, among other improvements;
--# Stewart Andreason for reporting a serious crash.
++# Stewart Andreason for reporting a serious crash; Francesco Brisa for the
++# emis as mircol functionality (w/ patch).
  # --------------------------------------------------------------------------
  # ***** BEGIN GPL LICENSE BLOCK *****
  #
--# Copyright (C) 2004-2007: Willian P. Germano, wgermano _at_ ig.com.br
++# Copyright (C) 2004-2009: Willian P. Germano, wgermano _at_ ig.com.br
  #
  # This program is free software; you can redistribute it and/or
  # modify it under the terms of the GNU General Public License
@@@ -89,15 -89,15 +91,19 @@@ DISPLAY_TRANSP = Tru
  
  SUBDIV = True
  
++EMIS_AS_MIRCOL = False
++
++
  tooltips = {
        'DISPLAY_TRANSP': 'Turn transparency on in the 3d View for objects using materials with alpha < 1.0.',
        'SUBDIV': 'Apply a SUBSURF modifier to objects meant to appear subdivided.',
--      'TEXTURES_DIR': 'Additional folder to look for missing textures.'
++      'TEXTURES_DIR': 'Additional folder to look for missing textures.',
++      'EMIS_AS_MIRCOL': 'Store emis color as mirror color in Blender.'        
  }
  
  def update_registry():
--      global TEXTURES_DIR, DISPLAY_TRANSP
--      rd = dict([('tooltips', tooltips), ('TEXTURES_DIR', TEXTURES_DIR), ('DISPLAY_TRANSP', DISPLAY_TRANSP), ('SUBDIV', SUBDIV)])
++      global TEXTURES_DIR, DISPLAY_TRANSP, EMIS_AS_MIRCOL
++      rd = dict([('tooltips', tooltips), ('TEXTURES_DIR', TEXTURES_DIR), ('DISPLAY_TRANSP', DISPLAY_TRANSP), ('SUBDIV', SUBDIV), ('EMIS_AS_MIRCOL', EMIS_AS_MIRCOL)])
        Registry.SetKey('ac3d_import', rd, True)
  
  rd = Registry.GetKey('ac3d_import', True)
@@@ -109,6 -109,6 +115,7 @@@ if rd
                TEXTURES_DIR = rd['TEXTURES_DIR']
                DISPLAY_TRANSP = rd['DISPLAY_TRANSP']
                SUBDIV = rd['SUBDIV']
++              EMIS_AS_MIRCOL = rd['EMIS_AS_MIRCOL']
        except:
                update_registry()
  else: update_registry()
@@@ -299,7 -299,7 +306,7 @@@ class AC3DImport
                lines = self.lines
                line = lines[i].split()
                mat_name = ''
--              mat_col = mat_amb = mat_emit = mat_spec_col = [0,0,0]
++              mat_col = mat_amb = mat_emit = mat_spec_col = mat_mir_col = [0,0,0]
                mat_alpha = 1
                mat_spec = 1.0
  
                        mat_amb = (v[0]+v[1]+v[2]) / 3.0
                        v = map(float,[line[11],line[12],line[13]])
                        mat_emit = (v[0]+v[1]+v[2]) / 3.0
++                      if EMIS_AS_MIRCOL:
++                              mat_emit = 0
++                              mat_mir_col = map(float,[line[11],line[12],line[13]])
++
                        mat_spec_col = map(float,[line[15],line[16],line[17]])
                        mat_spec = float(line[19]) / 64.0
                        mat_alpha = float(line[-1])
                        mat_alpha = 1 - mat_alpha
--                      self.mlist.append([mat_name, mat_col, mat_amb, mat_emit, mat_spec_col, mat_spec, mat_alpha])
++                      self.mlist.append([mat_name, mat_col, mat_amb, mat_emit, mat_spec_col, mat_spec, mat_mir_col, mat_alpha])
                        i += 1
                        line = lines[i].split()
  
                        m.emit = mat[3]
                        m.specCol = (mat[4][0], mat[4][1], mat[4][2])
                        m.spec = mat[5]
--                      m.alpha = mat[6]
++                      m.mirCol = (mat[6][0], mat[6][1], mat[6][2])
++                      m.alpha = mat[7]
                        if m.alpha < 1.0:
                                m.mode |= MAT_MODE_ZTRANSP
                                has_transp_mats = True
@@@ -155,7 -155,7 +155,7 @@@ usrObjectNamePrefix= "
  # if that armature had bones (spine, neck, arm) and the bone prefix was "a."
  #  the bones and IPO curves will be (a.spine, a.neck, a.arm)
  
--R2D = 18/3.1415  # radian to grad
++R2D = 18/3.141592653589793  # radian to grad
  BLENDER_VERSION = Blender.Get('version')
  
  # Gets the current scene, there can be many scenes in 1 blend file. 
@@@ -479,7 -479,7 +479,7 @@@ def pickMeshRayFaceWeight(me, orig, rdi
        
        w0 = (l1+l2)
        w1 = (l0+l2)
--      w2 = (l1+l2)
++      w2 = (l1+l0)
        
        totw= w0 + w1 + w2
        w0=w0/totw
@@@ -1,10 -1,10 +1,10 @@@
  #dxfLibrary.py : provides functions for generating DXF files
  # --------------------------------------------------------------------------
--__version__ = "v1.27beta - 2008.10.05"
--__author__  = "Stani Michiels(Stani), Remigiusz Fiedler(migius)"
++__version__ = "v1.28beta - 2008.12.13"
++__author__ = "Stani Michiels(Stani), Remigiusz Fiedler(migius)"
  __license__ = "GPL"
--__url__        = "http://wiki.blender.org/index.php/Scripts/Manual/Export/autodesk_dxf"
--__bpydoc__ ="""The script exports geometry data to DXF format r12 version.
++__url__ = "http://wiki.blender.org/index.php/Scripts/Manual/Export/autodesk_dxf"
++__bpydoc__ ="""The library to export geometry data to DXF format r12 version.
  
  Copyright %s
  Version %s
@@@ -12,15 -12,15 +12,17 @@@ License %
  Homepage %s
  
  See the homepage for documentation.
--url:
++Dedicated thread on BlenderArtists: http://blenderartists.org/forum/showthread.php?t=136439
  
  IDEAs:
  -
--              
++
  TODO:
---
++- add support for SPLINEs
  
  History
++v1.28 - 2008.12.13 by Steeve/BlenderArtists
++- bugfix for EXTMIN/EXTMAX to suit Cycas-CAD
  v1.27 - 2008.10.07 by migius
  - beautifying output code: keys whitespace prefix
  - refactoring DXF-strings format: NewLine moved to the end of
@@@ -154,56 -154,56 +156,56 @@@ BYBLOCK=
  BYLAYER=256
  
  #---block-type flags (bit coded values, may be combined):
--ANONYMOUS                        =1  # This is an anonymous block generated by hatching, associative dimensioning, other internal operations, or an application
++ANONYMOUS =1  # This is an anonymous block generated by hatching, associative dimensioning, other internal operations, or an application
  NON_CONSTANT_ATTRIBUTES =2  # This block has non-constant attribute definitions (this bit is not set if the block has any attribute definitions that are constant, or has no attribute definitions at all)
--XREF                                  =4  # This block is an external reference (xref)
--XREF_OVERLAY                  =8  # This block is an xref overlay
--EXTERNAL                              =16 # This block is externally dependent
--RESOLVED                              =32 # This is a resolved external reference, or dependent of an external reference (ignored on input)
--REFERENCED                      =64 # This definition is a referenced external reference (ignored on input)
++XREF =4  # This block is an external reference (xref)
++XREF_OVERLAY =8  # This block is an xref overlay
++EXTERNAL =16 # This block is externally dependent
++RESOLVED =32 # This is a resolved external reference, or dependent of an external reference (ignored on input)
++REFERENCED =64 # This definition is a referenced external reference (ignored on input)
  
  #---mtext flags
  #attachment point
--TOP_LEFT              = 1
--TOP_CENTER      = 2
--TOP_RIGHT        = 3
--MIDDLE_LEFT    = 4
--MIDDLE_CENTER   = 5
++TOP_LEFT = 1
++TOP_CENTER = 2
++TOP_RIGHT = 3
++MIDDLE_LEFT = 4
++MIDDLE_CENTER = 5
  MIDDLE_RIGHT  = 6
--BOTTOM_LEFT    = 7
--BOTTOM_CENTER   = 8
--BOTTOM_RIGHT  = 9
++BOTTOM_LEFT = 7
++BOTTOM_CENTER = 8
++BOTTOM_RIGHT = 9
  #drawing direction
--LEFT_RIGHT      = 1
--TOP_BOTTOM      = 3
--BY_STYLE              = 5 #the flow direction is inherited from the associated text style
++LEFT_RIGHT = 1
++TOP_BOTTOM = 3
++BY_STYLE = 5 #the flow direction is inherited from the associated text style
  #line spacing style (optional):
--AT_LEAST              = 1 #taller characters will override
--EXACT            = 2 #taller characters will not override
++AT_LEAST = 1 #taller characters will override
++EXACT = 2 #taller characters will not override
  
  #---polyline flags
--CLOSED                                          =1      # This is a closed polyline (or a polygon mesh closed in the M direction)
--CURVE_FIT                                =2     # Curve-fit vertices have been added
--SPLINE_FIT                              =4      # Spline-fit vertices have been added
--POLYLINE_3D                            =8       # This is a 3D polyline
--POLYGON_MESH                          =16      # This is a 3D polygon mesh
--CLOSED_N                                      =32      # The polygon mesh is closed in the N direction
--POLYFACE_MESH                    =64   # The polyline is a polyface mesh
--CONTINOUS_LINETYPE_PATTERN  =128      # The linetype pattern is generated continuously around the vertices of this polyline
++CLOSED =1       # This is a closed polyline (or a polygon mesh closed in the M direction)
++CURVE_FIT =2    # Curve-fit vertices have been added
++SPLINE_FIT =4   # Spline-fit vertices have been added
++POLYLINE_3D =8          # This is a 3D polyline
++POLYGON_MESH =16       # This is a 3D polygon mesh
++CLOSED_N =32   # The polygon mesh is closed in the N direction
++POLYFACE_MESH =64      # The polyline is a polyface mesh
++CONTINOUS_LINETYPE_PATTERN =128       # The linetype pattern is generated continuously around the vertices of this polyline
  
  #---text flags
  #horizontal
--LEFT          = 0
--CENTER          = 1
--RIGHT    = 2
--ALIGNED        = 3 #if vertical alignment = 0
--MIDDLE          = 4 #if vertical alignment = 0
--FIT            = 5 #if vertical alignment = 0
++LEFT = 0
++CENTER = 1
++RIGHT = 2
++ALIGNED = 3 #if vertical alignment = 0
++MIDDLE = 4 #if vertical alignment = 0
++FIT = 5 #if vertical alignment = 0
  #vertical
--BASELINE      = 0
--BOTTOM          = 1
--MIDDLE          = 2
--TOP            = 3
++BASELINE = 0
++BOTTOM        = 1
++MIDDLE = 2
++TOP = 3
  
  ####3) Classes
  #---entitities -----------------------------------------------
@@@ -239,7 -239,7 +241,7 @@@ class Face(_Entity)
        """3dface"""
        def __init__(self,points,**common):
                _Entity.__init__(self,**common)
--              if len(points)<4: #fix for r12 format
++              while len(points)<4: #fix for r12 format
                        points.append(points[-1])
                self.points=points
                
@@@ -336,10 -336,10 +338,14 @@@ class PolyLine(_Entity)
  
  #-----------------------------------------------
  class Point(_Entity):
--      """Colored solid fill."""
++      """Point."""
        def __init__(self,points=None,**common):
                _Entity.__init__(self,**common)
                self.points=points
++      def __str__(self): #TODO:
++              return '  0\nPOINT\n%s%s\n' %(self._common(),
++                       _points(self.points)
++                      )
  
  #-----------------------------------------------
  class Solid(_Entity):
@@@ -468,7 -468,7 +474,7 @@@ class Block(_Collection)
                self.name=name
                self.flag=0
                self.base=base
--      def __str__(self):
++      def __str__(self): #TODO:
                e=''.join([str(x)for x in self.entities])
                return '  0\nBLOCK\n  8\n%s\n  2\n%s\n 70\n%s\n%s\n  3\n%s\n%s  0\nENDBLK\n'%\
                           (self.layer,self.name.upper(),self.flag,_point(self.base),self.name.upper(),e)
@@@ -552,11 -552,11 +558,12 @@@ def ViewByWindow(name,leftBottom=(0,0),
  #-----------------------------------------------
  class Drawing(_Collection):
        """Dxf drawing. Use append or any other list methods to add objects."""
--      def __init__(self,insbase=(0.0,0.0,0.0),extmin=(0.0,0.0),extmax=(0.0,0.0),
++      def __init__(self,insbase=(0.0,0.0,0.0),extmin=(0.0,0.0,0.0),extmax=(0.0,0.0,0.0),
                                 layers=[Layer()],linetypes=[LineType()],styles=[Style()],blocks=[],
                                 views=[],entities=None,fileName='test.dxf'):
                # TODO: replace list with None,arial
--              if not entities:entities=[]
++              if not entities:
++                      entities=[]
                _Collection.__init__(self,entities)
                self.insbase=insbase
                self.extmin=extmin
@@@ -680,9 -680,9 +687,9 @@@ def test()
        #Drawing
        d=Drawing()
        #tables
--      d.blocks.append(b)                                        #table blocks
--      d.styles.append(Style())                                #table styles
--      d.views.append(View('Normal'))            #table view
++      d.blocks.append(b)  #table blocks
++      d.styles.append(Style())  #table styles
++      d.views.append(View('Normal'))  #table view
        d.views.append(ViewByWindow('Window',leftBottom=(1,0),rightTop=(2,1)))  #idem
  
        #entities
@@@ -1446,13 -1446,13 +1446,13 @@@ def write(filename, batch_objects = Non
                                for f in me.faces:
                                        for col in f.col:
                                                if i==-1:
--                                                      file.write('%i,%i,%i' % (col[0], col[1], col[2]))
++                                                      file.write('%i,%i,%i,255' % (col[0], col[1], col[2]))
                                                        i=0
                                                else:
                                                        if i==7:
                                                                file.write('\n\t\t\t\t')
                                                                i=0
--                                                      file.write(',%i,%i,%i' % (col[0], col[1], col[2]))
++                                                      file.write(',%i,%i,%i,255' % (col[0], col[1], col[2]))
                                                i+=1
                                                ii+=1 # One more Color
                                
@@@ -1,17 -1,17 +1,17 @@@
  #!BPY
  """
  Name: 'Blender/Python Scripting API'
--Blender: 244
++Blender: 248
  Group: 'Help'
  Tooltip: 'The Blender Python API reference manual'
  """
  
  __author__ = "Matt Ebb"
  __url__ = ("blender", "blenderartist")
--__version__ = "1.0"
++__version__ = "1.0.1"
  __bpydoc__ = """\
  This script opens the user's default web browser at http://www.blender.org's
--"Blenders Python API" page.
++"Blender Python API Reference" page.
  """
  
  # --------------------------------------------------------------------------
@@@ -38,4 -38,4 +38,4 @@@
  
  import Blender, webbrowser
  version = str(int(Blender.Get('version')))
--webbrowser.open('http://www.blender.org/documentation/'+ version +'PythonDoc/index.html')
++webbrowser.open('http://www.blender.org/documentation/'+ version +'PythonDoc/')
@@@ -8,7 -8,7 +8,7 @@@ Tooltip: 'Show help information about 
  """
  
  __author__ = "Willian P. Germano"
--__version__ = "0.1 11/02/04"
++__version__ = "0.3 01/21/09"
  __email__ = ('scripts', 'Author, wgermano:ig*com*br')
  __url__ = ('blender', 'blenderartists.org')
  
@@@ -47,8 -47,8 +47,6 @@@ Hotkeys:<br
  # $Id$
  #
  # --------------------------------------------------------------------------
--# sysinfo.py version 0.1 Jun 09, 2004
--# --------------------------------------------------------------------------
  # ***** BEGIN GPL LICENSE BLOCK *****
  #
  # Copyright (C) 2004: Willian P. Germano, wgermano _at_ ig.com.br
@@@ -69,6 -69,6 +67,9 @@@
  #
  # ***** END GPL LICENCE BLOCK *****
  # --------------------------------------------------------------------------
++# Thanks: Brendon Murphy (suggestion) and Kevin Morgan (implementation)
++# for the "run" button; Jean-Michel Soler for pointing a parsing error
++# with multilines using triple single quotes.
  
  import Blender
  from Blender import sys as bsys, Draw, Window, Registry
@@@ -355,7 -355,7 +356,12 @@@ def parse_pyobj(var, lines, i)
                        l = "ERROR"
  
        elif l[0] == "'":
--              if l[-1] == '\\':
++              if l[1:3] == "''": # '''
++                      if l.find("'''", 3) < 0: # multiline
++                              l2, i = parse_pyobj_close("'''", lines, i)
++                              if l[-1] == '\\': l = l[:-1]
++                              l = "%s%s" % (l, l2)
++              elif l[-1] == '\\':
                        l2, i = parse_pyobj_close("'", lines, i)
                        l = "%s%s" % (l, l2)
                elif l[-1] == "'" and l[-2] !=  '\\': # single line: '...'
@@@ -543,6 -543,6 +549,7 @@@ BEVT_GMENU = range(100, len_gmenus + 10
  BEVT_VIEWSOURCE = 1
  BEVT_EXIT = 2
  BEVT_BACK = 3
++BEVT_EXEC = 4 # Executes Script
  
  # gui callbacks:
  
@@@ -551,7 -551,7 +558,7 @@@ def gui(): # drawing the scree
        global SCREEN, START_SCREEN, SCRIPT_SCREEN
        global SCRIPT_INFO, AllGroups, GROUP_MENUS
        global BEVT_EMAIL, BEVT_LINK
--      global BEVT_VIEWSOURCE, BEVT_EXIT, BEVT_BACK, BEVT_GMENU, BUT_GMENU
++      global BEVT_VIEWSOURCE, BEVT_EXIT, BEVT_BACK, BEVT_GMENU, BUT_GMENU, BEVT_EXEC
        global PADDING, WIN_W, WIN_H, SCROLL_DOWN, COLUMNS, FMODE
  
        theme = Theme.Get()[0]
                                'View this script\'s source code in the Text Editor (hotkey: S)')
                        Draw.PushButton('exit', BEVT_EXIT, x + 45, 17, 45, bh,
                                'Exit from Scripts Help Browser (hotkey: Q)')
--                      if not FMODE: Draw.PushButton('back', BEVT_BACK, x + 2*45, 17, 45, bh,
++                      if not FMODE: 
++                              Draw.PushButton('back', BEVT_BACK, x + 2*45, 17, 45, bh,
                                'Back to scripts selection screen (hotkey: ESC)')
++                              Draw.PushButton('run script', BEVT_EXEC, x + 3*45, 17, 60, bh, 'Run this script')
++
                        BGL.glColor3ub(COL_TXTHI[0],COL_TXTHI[1], COL_TXTHI[2])
                        BGL.glRasterPos2i(x, 5)
                        Draw.Text('use the arrow keys or the mouse wheel to scroll text', 'small')
@@@ -766,6 -766,6 +776,14 @@@ def button_event(evt): # gui button eve
                        SCRIPT_INFO = None
                        SCROLL_DOWN = 0
                        Draw.Redraw()
++      elif evt == BEVT_EXEC: # Execute script
++              exec_line = ''
++              if SCRIPT_INFO.script.userdir:
++                      exec_line = bsys.join(Blender.Get('uscriptsdir'), SCRIPT_INFO.script.fname)
++              else:
++                      exec_line = bsys.join(Blender.Get('scriptsdir'), SCRIPT_INFO.script.fname)
++
++              Blender.Run(exec_line)
  
  keepon = True
  FMODE = False # called by Blender.ShowHelp(name) API function ?
@@@ -1,16 -1,16 +1,16 @@@
  #!BPY
  """
  Name: 'Getting Started'
--Blender: 234
++Blender: 248
  Group: 'Help'
  Tooltip: 'Help for new users'
  """
  
  __author__ = "Matt Ebb"
  __url__ = ("blender", "blenderartists.org")
--__version__ = "1.0"
++__version__ = "1.0.1"
  __bpydoc__ = """\
--This script opens the user's default web browser at www.blender3d.org's
++This script opens the user's default web browser at www.blender.org's
  "Getting Started" page.
  """
  
@@@ -39,5 -39,5 +39,4 @@@
  # --------------------------------------------------------------------------
  
  import Blender, webbrowser
--version = str(Blender.Get('version'))
--webbrowser.open('http://www.blender3d.org/Help/?pg=GettingStarted&ver=' + version)
++webbrowser.open('http://www.blender.org/education-help/tutorials/getting-started/')
@@@ -1,17 -1,17 +1,17 @@@
  #!BPY
  """
  Name: 'Manual'
--Blender: 234
++Blender: 248
  Group: 'Help'
--Tooltip: 'The Blender reference manual'
++Tooltip: 'The Blender Wiki manual'
  """
  
  __author__ = "Matt Ebb"
  __url__ = ("blender", "blenderartists.org")
--__version__ = "1.0"
++__version__ = "1.0.1"
  __bpydoc__ = """\
--This script opens the user's default web browser at www.blender3d.org's
--"Blender Manual" page.
++This script opens the user's default web browser at www.blender.org's
++"Manual" page.
  """
  
  # --------------------------------------------------------------------------
@@@ -37,5 -37,5 +37,4 @@@
  # --------------------------------------------------------------------------
  
  import Blender, webbrowser
--version = str(Blender.Get('version'))
--webbrowser.open('http://www.blender3d.org/Help/?pg=Manual&ver=' + version)
++webbrowser.open('http://wiki.blender.org/index.php/Manual')
@@@ -1,17 -1,17 +1,17 @@@
  #!BPY
  """
--Name: 'Release Notes'
--Blender: 234
++Name: 'Release Logs'
++Blender: 248
  Group: 'Help'
  Tooltip: 'Information about the changes in this version of Blender'
  """
  
  __author__ = "Matt Ebb"
  __url__ = ("blender", "blenderartists.org")
--__version__ = "1.0"
++__version__ = "1.0.1"
  __bpydoc__ = """\
--This script opens the user's default web browser at www.blender3d.org's
--"Release Notes" page.
++This script opens the user's default web browser at www.blender.org's
++"Release Logs" page.
  """
  
  # --------------------------------------------------------------------------
@@@ -37,5 -37,5 +37,5 @@@
  # --------------------------------------------------------------------------
  
  import Blender, webbrowser
--version = str(Blender.Get('version'))
--webbrowser.open('http://www.blender3d.org/Help/?pg=ReleaseNotes&ver=' + version)
++
++webbrowser.open('http://www.blender.org/development/release-logs/')
@@@ -2,17 -2,17 +2,17 @@@
  
  """
  Name: 'Tutorials'
--Blender: 234
++Blender: 248
  Group: 'Help'
  Tooltip: 'Tutorials for learning to use Blender'
  """
  
  __author__ = "Matt Ebb"
  __url__ = ("blender", "blenderartists.org")
--__version__ = "1.0"
++__version__ = "1.0.1"
  __bpydoc__ = """\
--This script opens the user's default web browser at www.blender3d.org's
--"Blender Tutorials" page.
++This script opens the user's default web browser at www.blender.org's
++"Tutorials" page.
  """
  
  # --------------------------------------------------------------------------
@@@ -38,5 -38,5 +38,4 @@@
  # --------------------------------------------------------------------------
  
  import Blender, webbrowser
--version = str(Blender.Get('version'))
--webbrowser.open('http://www.blender3d.org/Help/?pg=Tutorials&ver=' + version)
++webbrowser.open('http://www.blender.org/education-help/tutorials/')
@@@ -2,17 -2,17 +2,17 @@@
  
  """
  Name: 'Blender Website'
--Blender: 234
++Blender: 248
  Group: 'HelpWebsites'
  Tooltip: 'The official Blender website'
  """
  
  __author__ = "Matt Ebb"
  __url__ = ("blender", "blenderartists.org")
--__version__ = "1.0"
++__version__ = "1.0.1"
  __bpydoc__ = """\
  This script opens the user's default web browser at Blender's main site,
--www.blender3d.org.
++www.blender.org.
  """
  
  
@@@ -39,4 -39,4 +39,4 @@@
  # --------------------------------------------------------------------------
  
  import Blender, webbrowser
--webbrowser.open('http://www.blender3d.org/')
++webbrowser.open('http://www.blender.org/')
@@@ -2,17 -2,17 +2,17 @@@
  
  """
  Name: 'Developer Community'
--Blender: 234
++Blender: 248
  Group: 'HelpWebsites'
  Tooltip: 'Get involved with Blender development'
  """
  
  __author__ = "Matt Ebb"
  __url__ = ("blender", "blenderartists.org")
--__version__ = "1.0"
++__version__ = "1.0.1"
  __bpydoc__ = """\
--This script opens the user's default web browser at www.blender.org, the
--Blender development portal.
++This script opens the user's default web browser at www.blender.org's
++"Get Involved" page.
  """
  
  # --------------------------------------------------------------------------
@@@ -38,4 -38,4 +38,4 @@@
  # --------------------------------------------------------------------------
  
  import webbrowser
--webbrowser.open('http://www.blender.org')
++webbrowser.open('http://www.blender.org/community/get-involved/')
@@@ -2,16 -2,16 +2,16 @@@
  
  """
  Name: 'Blender E-Shop'
--Blender: 234
++Blender: 248
  Group: 'HelpWebsites'
  Tooltip: 'Buy official Blender resources and merchandise online'
  """
  
  __author__ = "Matt Ebb"
  __url__ = ("blender", "blenderartists.org")
--__version__ = "1.0"
++__version__ = "1.0.1"
  __bpydoc__ = """\
--This script opens the user's default web browser at www.blender3d.org's
++This script opens the user's default web browser at www.blender.org's
  "E-Shop" section.
  """
  
@@@ -2,16 -2,16 +2,16 @@@
  
  """
  Name: 'User Community'
--Blender: 234
++Blender: 248
  Group: 'HelpWebsites'
  Tooltip: 'Get involved with other Blender users'
  """
  
  __author__ = "Matt Ebb"
  __url__ = ("blender", "blenderartists.org")
--__version__ = "1.0"
++__version__ = "1.0.1"
  __bpydoc__ = """\
--This script opens the user's default web browser at www.blender3d.org's
++This script opens the user's default web browser at www.blender.org's
  "User Community" page.
  """
  
@@@ -38,4 -38,4 +38,4 @@@
  # --------------------------------------------------------------------------
  
  import webbrowser
--webbrowser.open('http://www.blender3d.org/Community')
++webbrowser.open('http://www.blender.org/community/user-community/')
@@@ -36,6 -36,6 +36,8 @@@ __bpydoc__ = """
  This script is an importer for the X3D and VRML97 file formats.
  """
  
++DEBUG = False
++
  # This should work without a blender at all
  try:
        from Blender.sys import exists
@@@ -50,11 -50,11 +52,11 @@@ def dirName(path)
  
  def imageConvertCompat(path):
        
--      try:    import os
--      except:
--              return path
++      try:             import os
++      except:          return path
++      if os.sep=='\\': return path # assime win32 has quicktime, dont convert
        
--      if path.endswith('.gif'):
++      if path.lower().endswith('.gif'):
                path_to = path[:-3] + 'png'
                
                '''
@@@ -145,13 -145,13 +147,12 @@@ def vrmlFormat(data)
                                        data = data[:start] + data[end:]
                                        ok = True # keep looking
                                        
--                                      last_i = end - len(item) + 1
++                                      last_i = (end - len(item)) + 1
                                        # print last_i, item, '|' + data[last_i] + '|'
                
        # done with messy extracting strings part
        
        
--      
        # Bad, dont take strings into account
        '''
        data = data.replace('#', '\n#')
                while ok:
                        ok = False
                        i = data.find(search + '"', last_i)
--                      
++                      # print i
                        if i != -1:
                                start = i + len(search) # first char after end of search
                                item = string_ls.pop(0)
++                              # print item
                                data = data[:start] + item + data[start:]
                                
--                              last_i = start + len(item)
++                              last_i = start + len(item) + 1
                                
                                ok = True
        
  NODE_NORMAL = 1 # {}
  NODE_ARRAY = 2 # []
  NODE_REFERENCE = 3 # USE foobar
++# NODE_PROTO = 4 #
  
  lines = []
  
@@@ -211,6 -211,6 +214,10 @@@ def getNodePreText(i, words)
                
                if i>=len(lines):
                        break
++                      '''
++              elif lines[i].startswith('PROTO'):
++                      return NODE_PROTO, i+1
++                      '''
                elif lines[i]=='{':
                        # words.append(lines[i]) # no need
                        # print "OK"
@@@ -244,6 -244,6 +251,23 @@@ def is_nodeline(i, words)
        if not lines[i][0].isalpha():
                return 0, 0
        
++      #if lines[i].startswith('field'):
++      #       return 0, 0
++      
++      # Is this a prototype??
++      if lines[i].startswith('PROTO'):
++              words[:] = lines[i].split()
++              return NODE_NORMAL, i+1 # TODO - assumes the next line is a '[\n', skip that
++      if lines[i].startswith('EXTERNPROTO'):
++              words[:] = lines[i].split()
++              return NODE_ARRAY, i+1 # TODO - assumes the next line is a '[\n', skip that
++      
++      '''
++      proto_type, new_i = is_protoline(i, words, proto_field_defs)
++      if new_i != -1:
++              return proto_type, new_i
++      '''
++      
        # Simple "var [" type
        if lines[i+1] == '[':
                if lines[i].count('"') % 2 == 0:
        node_type, new_i = getNodePreText(i, words)
        
        if not node_type:
++              if DEBUG: print "not node_type", lines[i]
                return 0, 0
        
        # Ok, we have a { after some values
@@@ -311,10 -311,10 +336,10 @@@ def is_numline(i)
                return True
        except:
                return False
--      
++
  
  class vrmlNode(object):
--      __slots__ = 'id', 'fields', 'node_type', 'parent', 'children', 'parent', 'array_data', 'reference', 'lineno', 'filename', 'blendObject', 'DEF_NAMESPACE', 'ROUTE_IPO_NAMESPACE', 'FIELD_NAMESPACE', 'x3dNode'
++      __slots__ = 'id', 'fields', 'proto_node', 'proto_field_defs', 'proto_fields', 'node_type', 'parent', 'children', 'parent', 'array_data', 'reference', 'lineno', 'filename', 'blendObject', 'DEF_NAMESPACE', 'ROUTE_IPO_NAMESPACE', 'PROTO_NAMESPACE', 'x3dNode'
        def __init__(self, parent, node_type, lineno):
                self.id = None
                self.node_type = node_type
                # This is only set from the root nodes.
                # Having a filename also denotes a root node
                self.filename = None
++              self.proto_node = None # proto field definition eg: "field SFColor seatColor .6 .6 .1"
                
                # Store in the root node because each inline file needs its own root node and its own namespace
                self.DEF_NAMESPACE = None 
                self.ROUTE_IPO_NAMESPACE = None 
++              '''
                self.FIELD_NAMESPACE = None
++              '''
++              
++              
++              self.PROTO_NAMESPACE = None
                
                self.reference = None
                
                        return 
                
                self.fields = [] # fields have no order, in some cases rool level values are not unique so dont use a dict
++              
++              self.proto_field_defs = [] # proto field definition eg: "field SFColor seatColor .6 .6 .1"
++              self.proto_fields = [] # proto field usage "diffuseColor IS seatColor"
                self.children = []
                self.array_data = [] # use for arrays of data - should only be for NODE_ARRAY types
                
        
        # Only available from the root node
++      '''
        def getFieldDict(self):
                if self.FIELD_NAMESPACE != None:
                        return self.FIELD_NAMESPACE
                else:
                        return self.parent.getFieldDict()
++      '''
++      def getProtoDict(self):
++              if self.PROTO_NAMESPACE != None:
++                      return self.PROTO_NAMESPACE
++              else:
++                      return self.parent.getProtoDict()
        
        def getDefDict(self):
                if self.DEF_NAMESPACE != None:
        
        def setRoot(self, filename):
                self.filename = filename
--              self.FIELD_NAMESPACE =          {}
++              # self.FIELD_NAMESPACE =                {}
                self.DEF_NAMESPACE =            {}
                self.ROUTE_IPO_NAMESPACE =      {}
++              self.PROTO_NAMESPACE =          {}
        
        def isRoot(self):
                if self.filename == None:
                except:
                        return None
        
++      def findSpecRecursive(self, spec):
++              self_real = self.getRealNode()
++              if spec == self_real.getSpec():
++                      return self
++              
++              for child in self_real.children:
++                      if child.findSpecRecursive(spec):
++                              return child
++              
++              return None
++      
        def getPrefix(self):
                if self.id:
                        return self.id[0]
                return None
        
--      def getDefName(self):
++      def getSpecialTypeName(self, typename):
                self_real = self.getRealNode()
++              try:            return self_real.id[ list(self_real.id).index(typename)+1 ]
++              except: return None
++      
++      
++      def getDefName(self):
++              return self.getSpecialTypeName('DEF')
++      
++      def getProtoName(self):
++              return self.getSpecialTypeName('PROTO')
                
--              if 'DEF' in self_real.id:
--                      # print self_real.id
--                      return self_real.id[ list(self_real.id).index('DEF')+1 ]
--              else:
--                      return None
--              
++      def getExternprotoName(self):
++              return self.getSpecialTypeName('EXTERNPROTO')
        
        def getChildrenBySpec(self, node_spec): # spec could be Transform, Shape, Appearance
                self_real = self.getRealNode()
                ancestry.append(self)
                for child in self.getRealNode().children:
                        if child not in ancestry:
--                              child.getSerialized(results, ancestry)
++                              # We dont want to load proto's, they are only references
++                              # We could enforce this elsewhere
++                              
++                              # Only add this in a very special case
++                              # where the parent of this object is not the real parent
++                              # - In this case we have added the proto as a child to a node instancing it.
++                              # This is a bit arbitary, but its how Proto's are done with this importer.
++                              if child.getProtoName() == None and child.getExternprotoName() == None:
++                                      child.getSerialized(results, ancestry)
++                              else:
++                                      
++                                      if DEBUG: print 'getSerialized() is proto:', child.getProtoName(), child.getExternprotoName(), self.getSpec()
++                                      
++                                      self_spec = self.getSpec()
++                                      
++                                      if child.getProtoName() == self_spec or child.getExternprotoName() == self_spec:
++                                              if DEBUG: "FoundProto!"
++                                              child.getSerialized(results, ancestry)
++                                      
++                                      
                
                return results
                
                        child.searchNodeTypeID(node_spec, results)
                return results
        
--      def getFieldName(self, field):
++      def getFieldName(self, field, ancestry, AS_CHILD=False):
                self_real = self.getRealNode() # incase we're an instance
                
                for f in self_real.fields:
                        if f and f[0] == field:
                                # print '\tfound field', f
                                
--                              return f[1:]
++                              if len(f)>=3 and f[1] == 'IS': # eg: 'diffuseColor IS legColor'
++                                      field_id = f[2]
++                                      
++                                      # print "\n\n\n\n\n\nFOND IS!!!"
++                                      f_proto_lookup = None
++                                      f_proto_child_lookup = None
++                                      i = len(ancestry)
++                                      while i:
++                                              i -= 1
++                                              node = ancestry[i]
++                                              node = node.getRealNode()
++                                              
++                                              # proto settings are stored in "self.proto_node"
++                                              if node.proto_node: 
++                                                      # Get the default value from the proto, this can be overwridden by the proto instace
++                                                      # 'field SFColor legColor .8 .4 .7'
++                                                      if AS_CHILD:
++                                                              for child in node.proto_node.children:
++                                                                      #if child.id  and  len(child.id) >= 3  and child.id[2]==field_id:
++                                                                      if child.id and ('point' in child.id or 'points' in child.id):
++                                                                              f_proto_child_lookup = child
++                                                      
++                                                      else:
++                                                              for f_def in node.proto_node.proto_field_defs:
++                                                                      if len(f_def) >= 4:
++                                                                              if f_def[0]=='field' and f_def[2]==field_id:
++                                                                                      f_proto_lookup = f_def[3:]
++                                              
++                                              # Node instance, Will be 1 up from the proto-node in the ancestry list. but NOT its parent.
++                                              # This is the setting as defined by the instance, including this setting is optional,
++                                              # and will override the default PROTO value 
++                                              # eg: 'legColor 1 0 0'
++                                              if AS_CHILD:
++                                                      for child in node.children:
++                                                              if child.id and child.id[0]==field_id:
++                                                                      f_proto_child_lookup = child
++                                              else:
++                                                      for f_def in node.fields:
++                                                              if len(f_def) >= 2:
++                                                                      if f_def[0]==field_id:
++                                                                              if DEBUG: print "getFieldName(), found proto", f_def
++                                                                              f_proto_lookup = f_def[1:]
++                                              
++                                      
++                                      if AS_CHILD:
++                                              if f_proto_child_lookup:
++                                                      if DEBUG:
++                                                              print "getFieldName() - AS_CHILD=True, child found"
++                                                              print f_proto_child_lookup
++                                              return f_proto_child_lookup
++                                      else:
++                                              return f_proto_lookup
++                              else:
++                                      if AS_CHILD:
++                                              return None
++                                      else:
++                                              # Not using a proto
++                                              return f[1:]
++                                              
                # print '\tfield not found', field
++              
++              
++              # See if this is a proto name
++              if AS_CHILD:
++                      child_array = None
++                      for child in self_real.children:
++                              if child.id and len(child.id) == 1 and child.id[0] == field:
++                                      return child
++              
                return None
        
--      def getFieldAsInt(self, field, default):
++      def getFieldAsInt(self, field, default, ancestry):
                self_real = self.getRealNode() # incase we're an instance
                
--              f = self_real.getFieldName(field)
++              f = self_real.getFieldName(field, ancestry)
                if f==None:     return default
                if ',' in f: f = f[:f.index(',')] # strip after the comma
                
                        print '\tvalue "%s" could not be used as an int for field "%s"' % (f[0], field)
                        return default
        
--      def getFieldAsFloat(self, field, default):
++      def getFieldAsFloat(self, field, default, ancestry):
                self_real = self.getRealNode() # incase we're an instance
                
--              f = self_real.getFieldName(field)
++              f = self_real.getFieldName(field, ancestry)
                if f==None:     return default
                if ',' in f: f = f[:f.index(',')] # strip after the comma
                
                        print '\tvalue "%s" could not be used as a float for field "%s"' % (f[0], field)
                        return default
        
--      def getFieldAsFloatTuple(self, field, default):
++      def getFieldAsFloatTuple(self, field, default, ancestry):
                self_real = self.getRealNode() # incase we're an instance
                
--              f = self_real.getFieldName(field)
++              f = self_real.getFieldName(field, ancestry)
                if f==None:     return default
                # if ',' in f: f = f[:f.index(',')] # strip after the comma
                
                        print '\tvalue "%s" could not be used as a float tuple for field "%s"' % (f, field)
                        return default
        
--      def getFieldAsBool(self, field, default):
++      def getFieldAsBool(self, field, default, ancestry):
                self_real = self.getRealNode() # incase we're an instance
                
--              f = self_real.getFieldName(field)
++              f = self_real.getFieldName(field, ancestry)
                if f==None:     return default
                if ',' in f: f = f[:f.index(',')] # strip after the comma
                
                        print '\t"%s" could not be used as a bool for field "%s"' % (f[1], field)
                        return default
        
--      def getFieldAsString(self, field, default=None):
++      def getFieldAsString(self, field, default, ancestry):
                self_real = self.getRealNode() # incase we're an instance
                
--              f = self_real.getFieldName(field)
++              f = self_real.getFieldName(field, ancestry)
                if f==None:     return default
                if len(f) < 1:
                        print '\t"%s" wrong length for string conversion for field "%s"' % (f, field)
                        print '\tvalue "%s" could not be used as a string for field "%s"' % (f[0], field)
                        return default
        
--      def getFieldAsArray(self, field, group):
++      def getFieldAsArray(self, field, group, ancestry):
                '''
                For this parser arrays are children
                '''
                self_real = self.getRealNode() # incase we're an instance
                
--              child_array = None
--              for child in self_real.children:
--                      # print "ID IS", child.id
--                      if child.id and len(child.id) == 1 and child.id[0] == field:
--                              child_array = child
--                              break
++              child_array = self_real.getFieldName(field, ancestry, True)
                
++              #if type(child_array)==list: # happens occasionaly
++              #       array_data = child_array 
++                      
                if child_array==None:
                        
                        # For x3d, should work ok with vrml too
                        # for x3d arrays are fields, vrml they are nodes, annoying but not tooo bad.
--                      data_split = self.getFieldName(field)
++                      data_split = self.getFieldName(field, ancestry)
                        if not data_split:
                                return []
                        array_data = ' '.join(data_split)
                
                return new_array
        
--      def getFieldAsStringArray(self, field):
++      def getFieldAsStringArray(self, field, ancestry):
                '''
                Get a list of strings
                '''
        def __repr__(self):
                level = self.getLevel()
                ind = '  ' * level
--              
                if self.node_type==NODE_REFERENCE:
                        brackets = ''
                elif self.node_type==NODE_NORMAL:
                        text += ind + "(reference node)\n"
                        return text
                
--              text += ind + 'FIELDS:\n'
++              if self.proto_node:
++                      text += ind + 'PROTO NODE...\n'
++                      text += str(self.proto_node)
++                      text += ind + 'PROTO NODE_DONE\n'
++              
++              text += ind + 'FIELDS:' + str(len(self.fields)) + '\n'
                
                for i,item in enumerate(self.fields):
                        text += ind + 'FIELD:\n'
                        text += ind + str(item) +'\n'
++
++              text += ind + 'PROTO_FIELD_DEFS:' + str(len(self.proto_field_defs)) + '\n'
                
--              #text += ind + 'ARRAY: ' + str(len(self.array_data)) + ' ' + str(self.array_data) + '\n'
--              text += ind + 'ARRAY: ' + str(len(self.array_data)) + '[...] \n'
++              for i,item in enumerate(self.proto_field_defs):
++                      text += ind + 'PROTO_FIELD:\n'
++                      text += ind + str(item) +'\n'
++
++              text += ind + 'ARRAY: ' + str(len(self.array_data)) + ' ' + str(self.array_data) + '\n'
++              #text += ind + 'ARRAY: ' + str(len(self.array_data)) + '[...] \n'
                
                text += ind + 'CHILDREN: ' + str(len(self.children)) + '\n'
                for i, child in enumerate(self.children):
                
                return text
        
--      def parse(self, i):
--              new_i = self.__parse(i)
++      def parse(self, i, IS_PROTO_DATA=False):
++              new_i = self.__parse(i, IS_PROTO_DATA)
                
                # print self.id, self.getFilename()
                
--              # If we were an inline then try load the file
++              # Check if this node was an inline or externproto
++              
++              url_ls = []
++              
                if self.node_type == NODE_NORMAL and self.getSpec() == 'Inline':
++                      ancestry = [] # Warning! - PROTO's using this wont work at all.
++                      url = self.getFieldAsString('url', None, ancestry)
++                      if url:
++                              url_ls = [(url, None)]
++                      del ancestry
++              
++              elif self.getExternprotoName():
++                      # externproto
++                      url_ls = []
++                      for f in self.fields:
++                              
++                              if type(f)==str:
++                                      f = [f]
++                              
++                              for ff in f:
++                                      for f_split in ff.split('"'):
++                                              # print f_split
++                                              # "someextern.vrml#SomeID"
++                                              if '#' in f_split:
++                                                      
++                                                      f_split, f_split_id = f_split.split('#') # there should only be 1 # anyway
++                                                      
++                                                      url_ls.append( (f_split, f_split_id) )
++                                              else:
++                                                      url_ls.append( (f_split, None) )
++              
++              
++              # Was either an Inline or an EXTERNPROTO
++              if url_ls:
                        
--                      url = self.getFieldAsString('url', None)
++                      # print url_ls
                        
--                      if url != None:
++                      for url, extern_key in url_ls:
++                              print url
                                urls = []
                                urls.append( url )
                                urls.append( BPySys.caseInsensitivePath(urls[-1]) )
                                
++                              urls.append( dirName(self.getFilename()) + url )
++                              urls.append( BPySys.caseInsensitivePath(urls[-1]) )
++                              
                                urls.append( dirName(self.getFilename()) + baseName(url) )
                                urls.append( BPySys.caseInsensitivePath(urls[-1]) )
                                
                                                        lines.insert(0, 'root_node____')
                                                        lines.append('}')
                                                        '''
--                                                      ff = open('/test.txt', 'w')
++                                                      ff = open('/tmp/test.txt', 'w')
                                                        ff.writelines([l+'\n' for l in lines])
                                                        '''
                                                        
                                                        child.setRoot(url) # initialized dicts
                                                        child.parse(0)
                                                        
++                                                      # if self.getExternprotoName():
++                                                      if self.getExternprotoName():
++                                                              if not extern_key: # if none is spesified - use the name
++                                                                      extern_key = self.getSpec()
++                                                              
++                                                              if extern_key:
++                                                                      
++                                                                      self.children.remove(child)
++                                                                      child.parent = None
++                                                                      
++                                                                      extern_child = child.findSpecRecursive(extern_key)
++                                                                      
++                                                                      if extern_child:
++                                                                              self.children.append(extern_child)
++                                                                              extern_child.parent = self
++                                                                              
++                                                                              if DEBUG: print "\tEXTERNPROTO ID found!:", extern_key
++                                                                      else:
++                                                                              print "\tEXTERNPROTO ID not found!:", extern_key
++                                                                      
                                                        # Watch it! - restore lines
                                                        lines[:] = lines_old
--                                      
                
                return new_i
        
--      def __parse(self, i):
--              # print 'parsing at', i,
--              # print i, self.id, self.lineno
++      def __parse(self, i, IS_PROTO_DATA=False):
++              '''
++              print 'parsing at', i,
++              print i, self.id, self.lineno
++              '''
                l = lines[i]
                
                if l=='[':
                        i+=1
                else:
                        words = []
++                      
                        node_type, new_i = is_nodeline(i, words)
                        if not node_type: # fail for parsing new node.
--                              raise "error"
++                              print "Failed to parse new node"
++                              raise ValueError
                        
                        if self.node_type==NODE_REFERENCE:
                                # Only assign the reference and quit
                        
                        # fill in DEF/USE
                        key = self.getDefName()
--                      
                        if key != None:
                                self.getDefDict()[ key ] = self
                        
++                      key = self.getProtoName()
++                      if not key:     key = self.getExternprotoName()
++                      
++                      proto_dict = self.getProtoDict()
++                      if key != None:
++                              proto_dict[ key ] = self
++                              
++                              # Parse the proto nodes fields
++                              self.proto_node = vrmlNode(self, NODE_ARRAY, new_i)
++                              new_i = self.proto_node.parse(new_i)
++                              
++                              self.children.remove(self.proto_node)
++                              
++                              # print self.proto_node
++                              
++                              new_i += 1 # skip past the {
++                              
++                      
++                      else: # If we're a proto instance, add the proto node as our child.
++                              spec = self.getSpec()
++                              try:
++                                      self.children.append( proto_dict[spec] )
++                                      #pass
++                              except:
++                                      pass
++                              
++                              del spec
++                      
++                      del proto_dict, key
++                      
                        i = new_i
                
                # print self.id
                ok = True
                while ok:
++                      if i>=len(lines):
++                              return len(lines)-1
++                      
                        l = lines[i]
--                      # print '\t', i, l
++                      # print '\tDEBUG:', i, self.node_type, l
                        if l=='':
                                i+=1
                                continue 
                        
                        if l=='}':
--                              if self.node_type != NODE_NORMAL:
--                                      print 'wrong node ending, expected an } ' + str(i)
--                                      raise ""
++                              if self.node_type != NODE_NORMAL: # also ends proto nodes, we may want a type for these too.
++                                      print 'wrong node ending, expected an } ' + str(i) + ' ' + str(self.node_type)
++                                      if DEBUG:
++                                              raise ValueError
                                ### print "returning", i
                                return i+1
                        if l==']':
                                if self.node_type != NODE_ARRAY:
--                                      print 'wrong node ending, expected a ] ' + str(i)
--                                      raise ""
++                                      print 'wrong node ending, expected a ] ' + str(i) + ' ' + str(self.node_type)
++                                      if DEBUG:
++                                              raise ValueError
                                ### print "returning", i
                                return i+1
                                
                        node_type, new_i = is_nodeline(i, [])
                        if node_type: # check text\n{
--                              ### print '\t\tgroup', i
                                child = vrmlNode(self, node_type, i)
                                i = child.parse(i)
--                              # print child.id, 'YYY'
                                
                        elif l=='[': # some files have these anonymous lists
                                child = vrmlNode(self, NODE_ARRAY, i)
                                                                        # this IS a key but the previous value was not a key, ot it was a defined field.
                                                                        if (not iskey(field_context[-1])) or ((len(field_context)==3 and field_context[1]=='IS')):
                                                                                field_list.append(field_context)
++                                                                              
                                                                                field_context = [value[j]]
                                                                        else:
                                                                                # The last item was not a value, multiple keys are needed in some cases.
                                                
                                                if value[0]=='field':
                                                        # field SFFloat creaseAngle 4
--                                                      self.getFieldDict()[value[2]] = value[3:] # skip the first 3 values
++                                                      self.proto_field_defs.append(value)
                                                else:
--                                                      # Get referenced field
--                                                      if len(value) >= 3 and value[1]=='IS':
--                                                              try:
--                                                                      value = [ value[0] ] + self.getFieldDict()[ value[2] ]
--                                                              except:
--                                                                      print '\tWarning, field could not be found:', value, 'TODO add support for exposedField'
--                                                                      print '\t', self.getFieldDict()
--                                                                      self.fields.append(value)
--                                                      else:
--                                                              self.fields.append(value)
++                                                      self.fields.append(value)
                                i+=1
  
  def gzipOpen(path):
@@@ -1015,8 -1015,8 +1250,9 @@@ def vrml_parse(path)
        # Use for testing our parsed output, so we can check on line numbers.
        
        '''
--      ff = open('/test.txt', 'w')
++      ff = open('/tmp/test.txt', 'w')
        ff.writelines([l+'\n' for l in lines])
++      ff.close()
        '''
        
        # Now evaluate it
        root.parse(0)
        
        # This prints a load of text
--      '''
--      print root
--      '''
++      if DEBUG:
++              print root
        
        return root, ''
  
@@@ -1055,7 -1055,7 +1290,7 @@@ class x3dNode(vrmlNode)
                vrmlNode.__init__(self, parent, node_type, -1)
                self.x3dNode = x3dNode
                
--      def parse(self):
++      def parse(self, IS_PROTO_DATA=False):
                # print self.x3dNode.tagName
                
                define = self.x3dNode.getAttributeNode('DEF')
@@@ -1195,12 -1195,12 +1430,12 @@@ def translateScale(sca)
        mat[2][2] = sca[2]
        return mat
  
--def translateTransform(node):
--      cent =          node.getFieldAsFloatTuple('center', None) # (0.0, 0.0, 0.0)
--      rot =           node.getFieldAsFloatTuple('rotation', None) # (0.0, 0.0, 1.0, 0.0)
--      sca =           node.getFieldAsFloatTuple('scale', None) # (1.0, 1.0, 1.0)
--      scaori =        node.getFieldAsFloatTuple('scaleOrientation', None) # (0.0, 0.0, 1.0, 0.0)
--      tx =            node.getFieldAsFloatTuple('translation', None) # (0.0, 0.0, 0.0)
++def translateTransform(node, ancestry):
++      cent =          node.getFieldAsFloatTuple('center', None, ancestry) # (0.0, 0.0, 0.0)
++      rot =           node.getFieldAsFloatTuple('rotation', None, ancestry) # (0.0, 0.0, 1.0, 0.0)
++      sca =           node.getFieldAsFloatTuple('scale', None, ancestry) # (1.0, 1.0, 1.0)
++      scaori =        node.getFieldAsFloatTuple('scaleOrientation', None, ancestry) # (0.0, 0.0, 1.0, 0.0)
++      tx =            node.getFieldAsFloatTuple('translation', None, ancestry) # (0.0, 0.0, 0.0)
        
        if cent:
                cent_mat = TranslationMatrix(Vector(cent)).resize4x4()
        
        return new_mat
  
--def translateTexTransform(node):
--      cent =          node.getFieldAsFloatTuple('center', None) # (0.0, 0.0)
--      rot =           node.getFieldAsFloat('rotation', None) # 0.0
--      sca =           node.getFieldAsFloatTuple('scale', None) # (1.0, 1.0)
--      tx =            node.getFieldAsFloatTuple('translation', None) # (0.0, 0.0)
++def translateTexTransform(node, ancestry):
++      cent =          node.getFieldAsFloatTuple('center', None, ancestry) # (0.0, 0.0)
++      rot =           node.getFieldAsFloat('rotation', None, ancestry) # 0.0
++      sca =           node.getFieldAsFloatTuple('scale', None, ancestry) # (1.0, 1.0)
++      tx =            node.getFieldAsFloatTuple('translation', None, ancestry) # (0.0, 0.0)
        
        
        if cent:
@@@ -1279,17 -1279,17 +1514,17 @@@ def getFinalMatrix(node, mtx, ancestry)
                mtx = Matrix()
        
        for node_tx in transform_nodes:
--              mat = translateTransform(node_tx)
++              mat = translateTransform(node_tx, ancestry)
                mtx = mtx * mat
        
        return mtx
  
--def importMesh_IndexedFaceSet(geom, bpyima):
++def importMesh_IndexedFaceSet(geom, bpyima, ancestry):
        # print geom.lineno, geom.id, vrmlNode.DEF_NAMESPACE.keys()
        
--      ccw =                           geom.getFieldAsBool('ccw', True)
--      ifs_colorPerVertex =    geom.getFieldAsBool('colorPerVertex', True) # per vertex or per face
--      ifs_normalPerVertex =   geom.getFieldAsBool('normalPerVertex', True)
++      ccw =                           geom.getFieldAsBool('ccw', True, ancestry)
++      ifs_colorPerVertex =    geom.getFieldAsBool('colorPerVertex', True, ancestry) # per vertex or per face
++      ifs_normalPerVertex =   geom.getFieldAsBool('normalPerVertex', True, ancestry)
        
        # This is odd how point is inside Coordinate
        
        
        coord = geom.getChildBySpec('Coordinate') # works for x3d and vrml
        
--      if coord:       ifs_points = coord.getFieldAsArray('point', 3)
++      if coord:       ifs_points = coord.getFieldAsArray('point', 3, ancestry)
        else:           coord = []
        
        if not coord:
                print '\tWarnint: IndexedFaceSet has no points'
                return None, ccw
        
--      ifs_faces = geom.getFieldAsArray('coordIndex', 0)
++      ifs_faces = geom.getFieldAsArray('coordIndex', 0, ancestry)
        
        coords_tex = None
        if ifs_faces: # In rare cases this causes problems - no faces but UVs???
                coords_tex = geom.getChildBySpec('TextureCoordinate')
                
                if coords_tex:
--                      ifs_texpoints = coords_tex.getFieldAsArray('point', 2)
--                      ifs_texfaces = geom.getFieldAsArray('texCoordIndex', 0)
++                      ifs_texpoints = coords_tex.getFieldAsArray('point', 2, ancestry)
++                      ifs_texfaces = geom.getFieldAsArray('texCoordIndex', 0, ancestry)
                        
                        if not ifs_texpoints:
                                # IF we have no coords, then dont bother
        vcolor_spot = None # spot color when we dont have an array of colors
        if vcolor:
                # float to char
--              ifs_vcol = [[int(c*256) for c in col] for col in vcolor.getFieldAsArray('color', 3)]
--              ifs_color_index = geom.getFieldAsArray('colorIndex', 0)
++              ifs_vcol = [[int(c*256) for c in col] for col in vcolor.getFieldAsArray('color', 3, ancestry)]
++              ifs_color_index = geom.getFieldAsArray('colorIndex', 0, ancestry)
                
                if not ifs_vcol:
--                      vcolor_spot = [int(c*256) for c in vcolor.getFieldAsFloatTuple('color', [])]
++                      vcolor_spot = [int(c*256) for c in vcolor.getFieldAsFloatTuple('color', [], ancestry)]
        
        # Convert faces into somthing blender can use
        edges = []
                                fv = f.verts
                                for i,c in enumerate(fcol):
                                        color_index = fv[i].index # color index is vert index
--                                      if ifs_color_index: color_index = ifs_color_index[color_index]
++                                      if ifs_color_index:
++                                              try:
++                                                      color_index = ifs_color_index[color_index]
++                                              except:
++                                                      print '\tWarning: per vertex color index out of range'
++                                                      continue
                                        
                                        if len(ifs_vcol) < color_index:
                                                c.r, c.g, c.b = ifs_vcol[color_index]
                                        
                                        col = ifs_vcol[color_index]
                                        for i,c in enumerate(fcol):
--                                              c.r, c.g, c.b = col
++                                              try:
++                                                      c.r, c.g, c.b = col
++                                              except:
++                                                      pass # incase its not between 0 and 255
        
        bpymesh.verts.delete([0,]) # EEKADOODLE
        
        return bpymesh, ccw
  
--def importMesh_IndexedLineSet(geom):
++def importMesh_IndexedLineSet(geom, ancestry):
        # VRML not x3d
        #coord = geom.getChildByName('coord') # 'Coordinate'
        coord = geom.getChildBySpec('Coordinate') # works for x3d and vrml
--      if coord:       points = coord.getFieldAsArray('point', 3)
++      if coord:       points = coord.getFieldAsArray('point', 3, ancestry)
        else:           points = []
        
        if not points:
                print '\tWarning: IndexedLineSet had no points'
                return None
        
--      ils_lines = geom.getFieldAsArray('coordIndex', 0)
++      ils_lines = geom.getFieldAsArray('coordIndex', 0, ancestry)
        
        lines = []
        line = []
        return bpycurve
  
  
--def importMesh_PointSet(geom):
++def importMesh_PointSet(geom, ancestry):
        # VRML not x3d
        #coord = geom.getChildByName('coord') # 'Coordinate'
        coord = geom.getChildBySpec('Coordinate')  # works for x3d and vrml
--      if coord:       points = coord.getFieldAsArray('point', 3)
++      if coord:       points = coord.getFieldAsArray('point', 3, ancestry)
        else:           points = []
        
        # vcolor = geom.getChildByName('color') # blender dosnt have per vertex color
@@@ -1614,26 -1614,26 +1857,26 @@@ GLOBALS['CIRCLE_DETAIL'] = 1
  
  MATRIX_Z_TO_Y = RotationMatrix(90, 4, 'x')
  
--def importMesh_Sphere(geom):
++def importMesh_Sphere(geom, ancestry):
        # bpymesh = bpy.data.meshes.new()
--      diameter = geom.getFieldAsFloat('radius', 0.5) * 2 # * 2 for the diameter
++      diameter = geom.getFieldAsFloat('radius', 0.5, ancestry) * 2 # * 2 for the diameter
        bpymesh = Mesh.Primitives.UVsphere(GLOBALS['CIRCLE_DETAIL'], GLOBALS['CIRCLE_DETAIL'], diameter)  
        bpymesh.transform(MATRIX_Z_TO_Y)
        return bpymesh
  
--def importMesh_Cylinder(geom):
++def importMesh_Cylinder(geom, ancestry):
        # bpymesh = bpy.data.meshes.new()
--      diameter = geom.getFieldAsFloat('radius', 1.0) * 2 # * 2 for the diameter
--      height = geom.getFieldAsFloat('height', 2)
++      diameter = geom.getFieldAsFloat('radius', 1.0, ancestry) * 2 # * 2 for the diameter
++      height = geom.getFieldAsFloat('height', 2, ancestry)
        bpymesh = Mesh.Primitives.Cylinder(GLOBALS['CIRCLE_DETAIL'], diameter, height) 
        bpymesh.transform(MATRIX_Z_TO_Y)
        
        # Warning - Rely in the order Blender adds verts
        # not nice design but wont change soon.
        
--      bottom = geom.getFieldAsBool('bottom', True)
--      side = geom.getFieldAsBool('side', True)
--      top = geom.getFieldAsBool('top', True)
++      bottom = geom.getFieldAsBool('bottom', True, ancestry)
++      side = geom.getFieldAsBool('side', True, ancestry)
++      top = geom.getFieldAsBool('top', True, ancestry)
        
        if not top: # last vert is top center of tri fan.
                bpymesh.verts.delete([(GLOBALS['CIRCLE_DETAIL']+GLOBALS['CIRCLE_DETAIL'])+1])
        
        return bpymesh
  
--def importMesh_Cone(geom):
++def importMesh_Cone(geom, ancestry):
        # bpymesh = bpy.data.meshes.new()
--      diameter = geom.getFieldAsFloat('bottomRadius', 1.0) * 2 # * 2 for the diameter
--      height = geom.getFieldAsFloat('height', 2)
++      diameter = geom.getFieldAsFloat('bottomRadius', 1.0, ancestry) * 2 # * 2 for the diameter
++      height = geom.getFieldAsFloat('height', 2, ancestry)
        bpymesh = Mesh.Primitives.Cone(GLOBALS['CIRCLE_DETAIL'], diameter, height) 
        bpymesh.transform(MATRIX_Z_TO_Y)
        
        # Warning - Rely in the order Blender adds verts
        # not nice design but wont change soon.
        
--      bottom = geom.getFieldAsBool('bottom', True)
--      side = geom.getFieldAsBool('side', True)
++      bottom = geom.getFieldAsBool('bottom', True, ancestry)
++      side = geom.getFieldAsBool('side', True, ancestry)
        
        if not bottom: # last vert is on the bottom
                bpymesh.verts.delete([GLOBALS['CIRCLE_DETAIL']+1])
        
        return bpymesh
  
--def importMesh_Box(geom):
++def importMesh_Box(geom, ancestry):
        # bpymesh = bpy.data.meshes.new()
        
--      size = geom.getFieldAsFloatTuple('size', (2.0, 2.0, 2.0))
++      size = geom.getFieldAsFloatTuple('size', (2.0, 2.0, 2.0), ancestry)
        bpymesh = Mesh.Primitives.Cube(1.0) 
  
        # Scale the box to the size set
@@@ -1714,7 -1714,7 +1957,7 @@@ def importShape(node, ancestry)
                        textx = appr.getChildBySpec('TextureTransform')
                        
                        if textx:
--                              texmtx = translateTexTransform(textx)
++                              texmtx = translateTexTransform(textx, ancestry)
                        
  
                        
                                
                                # all values between 0.0 and 1.0, defaults from VRML docs
                                bpymat = bpy.data.materials.new()
--                              bpymat.amb =            mat.getFieldAsFloat('ambientIntensity', 0.2)
--                              bpymat.rgbCol =         mat.getFieldAsFloatTuple('diffuseColor', [0.8, 0.8, 0.8])
++                              bpymat.amb =            mat.getFieldAsFloat('ambientIntensity', 0.2, ancestry)
++                              bpymat.rgbCol =         mat.getFieldAsFloatTuple('diffuseColor', [0.8, 0.8, 0.8], ancestry)
                                
                                # NOTE - blender dosnt support emmisive color
                                # Store in mirror color and approximate with emit.
--                              emit =                          mat.getFieldAsFloatTuple('emissiveColor', [0.0, 0.0, 0.0])
++                              emit =                          mat.getFieldAsFloatTuple('emissiveColor', [0.0, 0.0, 0.0], ancestry)
                                bpymat.mirCol =         emit
                                bpymat.emit =           (emit[0]+emit[1]+emit[2])/3.0
                                
--                              bpymat.hard =           int(1+(510*mat.getFieldAsFloat('shininess', 0.2))) # 0-1 -> 1-511
--                              bpymat.specCol =        mat.getFieldAsFloatTuple('specularColor', [0.0, 0.0, 0.0])
--                              bpymat.alpha =          1.0 - mat.getFieldAsFloat('transparency', 0.0)
++                              bpymat.hard =           int(1+(510*mat.getFieldAsFloat('shininess', 0.2, ancestry))) # 0-1 -> 1-511
++                              bpymat.specCol =        mat.getFieldAsFloatTuple('specularColor', [0.0, 0.0, 0.0], ancestry)
++                              bpymat.alpha =          1.0 - mat.getFieldAsFloat('transparency', 0.0, ancestry)
                                if bpymat.alpha < 0.999:
                                        bpymat.mode |= Material.Modes.ZTRANSP
                        
                        
                        if ima:
                                
--                              ima_url =                       ima.getFieldAsString('url')
++                              ima_url =                       ima.getFieldAsString('url', None, ancestry)
                                
                                if ima_url==None:
--                                      try:            ima_url = ima.getFieldAsStringArray('url')[0] # in some cases we get a list of images.
++                                      try:            ima_url = ima.getFieldAsStringArray('url', ancestry)[0] # in some cases we get a list of images.
                                        except:         ima_url = None
                                
                                if ima_url==None:
                                                else:
                                                        bpymat.setTexture(0, texture, Texture.TexCo.UV, Texture.MapTo.COL)
                                                        
--                                              ima_repS =                      ima.getFieldAsBool('repeatS', True)
--                                              ima_repT =                      ima.getFieldAsBool('repeatT', True)
++                                              ima_repS =                      ima.getFieldAsBool('repeatS', True, ancestry)
++                                              ima_repT =                      ima.getFieldAsBool('repeatT', True, ancestry)
                                                
                                                # To make this work properly we'd need to scale the UV's too, better to ignore th
                                                # texture.repeat =      max(1, ima_repS * 512), max(1, ima_repT * 512)
                geom_spec = geom.getSpec()
                ccw = True
                if geom_spec == 'IndexedFaceSet':
--                      bpydata, ccw = importMesh_IndexedFaceSet(geom, bpyima)
++                      bpydata, ccw = importMesh_IndexedFaceSet(geom, bpyima, ancestry)
                elif geom_spec == 'IndexedLineSet':
--                      bpydata = importMesh_IndexedLineSet(geom)
++                      bpydata = importMesh_IndexedLineSet(geom, ancestry)
                elif geom_spec == 'PointSet':
--                      bpydata = importMesh_PointSet(geom)
++                      bpydata = importMesh_PointSet(geom, ancestry)
                elif geom_spec == 'Sphere':
--                      bpydata = importMesh_Sphere(geom)
++                      bpydata = importMesh_Sphere(geom, ancestry)
                elif geom_spec == 'Box':
--                      bpydata = importMesh_Box(geom)
++                      bpydata = importMesh_Box(geom, ancestry)
                elif geom_spec == 'Cylinder':
--                      bpydata = importMesh_Cylinder(geom)
++                      bpydata = importMesh_Cylinder(geom, ancestry)
                elif geom_spec == 'Cone':
--                      bpydata = importMesh_Cone(geom)
++                      bpydata = importMesh_Cone(geom, ancestry)
                else:
                        print '\tWarning: unsupported type "%s"' % geom_spec
                        return
                        bpyob  = node.blendObject = bpy.data.scenes.active.objects.new(bpydata)
                        
                        if type(bpydata) == Types.MeshType:
--                              is_solid =                      geom.getFieldAsBool('solid', True)
--                              creaseAngle =           geom.getFieldAsFloat('creaseAngle', None)
++                              is_solid =                      geom.getFieldAsBool('solid', True, ancestry)
++                              creaseAngle =           geom.getFieldAsFloat('creaseAngle', None, ancestry)
                                
                                if creaseAngle != None:
                                        bpydata.maxSmoothAngle = 1+int(min(79, creaseAngle * RAD_TO_DEG))
                        bpyob.setMatrix( getFinalMatrix(node, None, ancestry) )
  
  
--def importLamp_PointLight(node):
++def importLamp_PointLight(node, ancestry):
        vrmlname = node.getDefName()
        if not vrmlname: vrmlname = 'PointLight'
        
--      # ambientIntensity = node.getFieldAsFloat('ambientIntensity', 0.0) # TODO
--      # attenuation = node.getFieldAsFloatTuple('attenuation', (1.0, 0.0, 0.0)) # TODO
--      color = node.getFieldAsFloatTuple('color', (1.0, 1.0, 1.0))
--      intensity = node.getFieldAsFloat('intensity', 1.0) # max is documented to be 1.0 but some files have higher.
--      location = node.getFieldAsFloatTuple('location', (0.0, 0.0, 0.0))
--      # is_on = node.getFieldAsBool('on', True) # TODO
--      radius = node.getFieldAsFloat('radius', 100.0)
++      # ambientIntensity = node.getFieldAsFloat('ambientIntensity', 0.0, ancestry) # TODO
++      # attenuation = node.getFieldAsFloatTuple('attenuation', (1.0, 0.0, 0.0), ancestry) # TODO
++      color = node.getFieldAsFloatTuple('color', (1.0, 1.0, 1.0), ancestry)
++      intensity = node.getFieldAsFloat('intensity', 1.0, ancestry) # max is documented to be 1.0 but some files have higher.
++      location = node.getFieldAsFloatTuple('location', (0.0, 0.0, 0.0), ancestry)
++      # is_on = node.getFieldAsBool('on', True, ancestry) # TODO
++      radius = node.getFieldAsFloat('radius', 100.0, ancestry)
        
        bpylamp = bpy.data.lamps.new()
        bpylamp.setType('Lamp')
        
        return bpylamp, mtx
  
--def importLamp_DirectionalLight(node):
++def importLamp_DirectionalLight(node, ancestry):
        vrmlname = node.getDefName()
        if not vrmlname: vrmlname = 'DirectLight'
        
        # ambientIntensity = node.getFieldAsFloat('ambientIntensity', 0.0) # TODO
--      color = node.getFieldAsFloatTuple('color', (1.0, 1.0, 1.0))
--      direction = node.getFieldAsFloatTuple('direction', (0.0, 0.0, -1.0))
--      intensity = node.getFieldAsFloat('intensity', 1.0) # max is documented to be 1.0 but some files have higher.
--      # is_on = node.getFieldAsBool('on', True) # TODO
++      color = node.getFieldAsFloatTuple('color', (1.0, 1.0, 1.0), ancestry)
++      direction = node.getFieldAsFloatTuple('direction', (0.0, 0.0, -1.0), ancestry)
++      intensity = node.getFieldAsFloat('intensity', 1.0, ancestry) # max is documented to be 1.0 but some files have higher.
++      # is_on = node.getFieldAsBool('on', True, ancestry) # TODO
        
        bpylamp = bpy.data.lamps.new(vrmlname)
        bpylamp.setType('Sun')
  
  # looks like default values for beamWidth and cutOffAngle were swapped in VRML docs.
  
--def importLamp_SpotLight(node):
++def importLamp_SpotLight(node, ancestry):
        vrmlname = node.getDefName()
        if not vrmlname: vrmlname = 'SpotLight'
        
--      # ambientIntensity = geom.getFieldAsFloat('ambientIntensity', 0.0) # TODO
--      # attenuation = geom.getFieldAsFloatTuple('attenuation', (1.0, 0.0, 0.0)) # TODO
--      beamWidth = node.getFieldAsFloat('beamWidth', 1.570796) * RAD_TO_DEG # max is documented to be 1.0 but some files have higher.
--      color = node.getFieldAsFloatTuple('color', (1.0, 1.0, 1.0))
--      cutOffAngle = node.getFieldAsFloat('cutOffAngle', 0.785398) * RAD_TO_DEG # max is documented to be 1.0 but some files have higher.
--      direction = node.getFieldAsFloatTuple('direction', (0.0, 0.0, -1.0))
--      intensity = node.getFieldAsFloat('intensity', 1.0) # max is documented to be 1.0 but some files have higher.
--      location = node.getFieldAsFloatTuple('location', (0.0, 0.0, 0.0))
--      # is_on = node.getFieldAsBool('on', True) # TODO
--      radius = node.getFieldAsFloat('radius', 100.0)
++      # ambientIntensity = geom.getFieldAsFloat('ambientIntensity', 0.0, ancestry) # TODO
++      # attenuation = geom.getFieldAsFloatTuple('attenuation', (1.0, 0.0, 0.0), ancestry) # TODO
++      beamWidth = node.getFieldAsFloat('beamWidth', 1.570796, ancestry) * RAD_TO_DEG # max is documented to be 1.0 but some files have higher.
++      color = node.getFieldAsFloatTuple('color', (1.0, 1.0, 1.0), ancestry)
++      cutOffAngle = node.getFieldAsFloat('cutOffAngle', 0.785398, ancestry) * RAD_TO_DEG # max is documented to be 1.0 but some files have higher.
++      direction = node.getFieldAsFloatTuple('direction', (0.0, 0.0, -1.0), ancestry)
++      intensity = node.getFieldAsFloat('intensity', 1.0, ancestry) # max is documented to be 1.0 but some files have higher.
++      location = node.getFieldAsFloatTuple('location', (0.0, 0.0, 0.0), ancestry)
++      # is_on = node.getFieldAsBool('on', True, ancestry) # TODO
++      radius = node.getFieldAsFloat('radius', 100.0, ancestry)
        
        bpylamp = bpy.data.lamps.new(vrmlname)
        bpylamp.setType('Spot')
  
  def importLamp(node, spec, ancestry):
        if spec=='PointLight':
--              bpylamp,mtx = importLamp_PointLight(node)
++              bpylamp,mtx = importLamp_PointLight(node, ancestry)
        elif spec=='DirectionalLight':
--              bpylamp,mtx = importLamp_DirectionalLight(node)
++              bpylamp,mtx = importLamp_DirectionalLight(node, ancestry)
        elif spec=='SpotLight':
--              bpylamp,mtx = importLamp_SpotLight(node)
++              bpylamp,mtx = importLamp_SpotLight(node, ancestry)
        else:
                print "Error, not a lamp"
--              raise ""
++              raise ValueError
        
        bpyob = node.blendObject = bpy.data.scenes.active.objects.new(bpylamp)
        bpyob.setMatrix( getFinalMatrix(node, mtx, ancestry) )
@@@ -1952,11 -1952,11 +2195,11 @@@ def importViewpoint(node, ancestry)
        name = node.getDefName()
        if not name: name = 'Viewpoint'
        
--      fieldOfView = node.getFieldAsFloat('fieldOfView', 0.785398) * RAD_TO_DEG # max is documented to be 1.0 but some files have higher.
--      # jump = node.getFieldAsBool('jump', True)
--      orientation = node.getFieldAsFloatTuple('orientation', (0.0, 0.0, 1.0, 0.0))
--      position = node.getFieldAsFloatTuple('position', (0.0, 0.0, 0.0))
--      description = node.getFieldAsString('description', '')
++      fieldOfView = node.getFieldAsFloat('fieldOfView', 0.785398, ancestry) * RAD_TO_DEG # max is documented to be 1.0 but some files have higher.
++      # jump = node.getFieldAsBool('jump', True, ancestry)
++      orientation = node.getFieldAsFloatTuple('orientation', (0.0, 0.0, 1.0, 0.0), ancestry)
++      position = node.getFieldAsFloatTuple('position', (0.0, 0.0, 0.0), ancestry)
++      description = node.getFieldAsString('description', '', ancestry)
        
        bpycam = bpy.data.cameras.new(name)
        
@@@ -1976,63 -1976,63 +2219,80 @@@ def importTransform(node, ancestry)
        bpyob = node.blendObject = bpy.data.scenes.active.objects.new('Empty', name) # , name)
        bpyob.setMatrix( getFinalMatrix(node, None, ancestry) )
  
++      # so they are not too annoying
++      bpyob.emptyShape= Blender.Object.EmptyShapes.AXES
++      bpyob.drawSize= 0.2
++
        
  #def importTimeSensor(node):
  
  
--def translatePositionInterpolator(node, ipo):
--      key = node.getFieldAsArray('key', 0)
--      keyValue = node.getFieldAsArray('keyValue', 3)
--      
--      loc_x = ipo.addCurve('LocX')
--      loc_y = ipo.addCurve('LocY')
--      loc_z = ipo.addCurve('LocZ')
++def translatePositionInterpolator(node, ipo, ancestry):
++      key = node.getFieldAsArray('key', 0, ancestry)
++      keyValue = node.getFieldAsArray('keyValue', 3, ancestry)
        
++      try:
++              loc_x = ipo.addCurve('LocX')
++              loc_y = ipo.addCurve('LocY')
++              loc_z = ipo.addCurve('LocZ')
++      except ValueError:
++              return
++              
        loc_x.interpolation = loc_y.interpolation = loc_z.interpolation = Blender.IpoCurve.InterpTypes.LINEAR
        
        for i, time in enumerate(key):
--              x,y,z = keyValue[i]
++              try:            x,y,z = keyValue[i]
++              except: continue
                
                loc_x.append((time,x))
                loc_y.append((time,y))
                loc_z.append((time,z))
  
--def translateOrientationInterpolator(node, ipo):
--      key = node.getFieldAsArray('key', 0)
--      keyValue = node.getFieldAsArray('keyValue', 4)
++def translateOrientationInterpolator(node, ipo, ancestry):
++      key = node.getFieldAsArray('key', 0, ancestry)
++      keyValue = node.getFieldAsArray('keyValue', 4, ancestry)
        
--      rot_x = ipo.addCurve('RotX')
--      rot_y = ipo.addCurve('RotY')
--      rot_z = ipo.addCurve('RotZ')
++      try:
++              rot_x = ipo.addCurve('RotX')
++              rot_y = ipo.addCurve('RotY')
++              rot_z = ipo.addCurve('RotZ')
++      except ValueError:
++              return
        
        rot_x.interpolation = rot_y.interpolation = rot_z.interpolation = Blender.IpoCurve.InterpTypes.LINEAR
        
        for i, time in enumerate(key):
++              try:            x,y,z,w = keyValue[i]
++              except: continue
                
--              mtx = translateRotation(keyValue[i])
++              mtx = translateRotation((x,y,z,w))
                eul = mtx.toEuler()
                rot_x.append((time,eul.x/10.0))
                rot_y.append((time,eul.y/10.0))
                rot_z.append((time,eul.z/10.0))
  
  # Untested!
--def translateScalarInterpolator(node, ipo):
--      key = node.getFieldAsArray('key', 0)
--      keyValue = node.getFieldAsArray('keyValue', 4)
++def translateScalarInterpolator(node, ipo, ancestry):
++      key = node.getFieldAsArray('key', 0, ancestry)
++      keyValue = node.getFieldAsArray('keyValue', 4, ancestry)
        
--      sca_x = ipo.addCurve('SizeX')
--      sca_y = ipo.addCurve('SizeY')
--      sca_z = ipo.addCurve('SizeZ')
++      try:
++              sca_x = ipo.addCurve('ScaleX')
++              sca_y = ipo.addCurve('ScaleY')
++              sca_z = ipo.addCurve('ScaleZ')
++      except ValueError:
++              return
        
        sca_x.interpolation = sca_y.interpolation = sca_z.interpolation = Blender.IpoCurve.InterpTypes.LINEAR
        
        for i, time in enumerate(key):
--              x,y,z = keyValue[i]
++              try:            x,y,z = keyValue[i]
++              except: continue
                sca_x.append((time,x/10.0))
                sca_y.append((time,y/10.0))
                sca_z.append((time,z/10.0))
  
--def translateTimeSensor(node, ipo):
++def translateTimeSensor(node, ipo, ancestry):
        '''
        Apply a time sensor to an IPO, VRML has many combinations of loop/start/stop/cycle times
        to give different results, for now just do the basics
        time_cu = ipo.addCurve('Time')
        time_cu.interpolation = Blender.IpoCurve.InterpTypes.LINEAR
        
--      cycleInterval = node.getFieldAsFloat('cycleInterval', None)
++      cycleInterval = node.getFieldAsFloat('cycleInterval', None, ancestry)
        
--      startTime = node.getFieldAsFloat('startTime', 0.0)
--      stopTime = node.getFieldAsFloat('stopTime', 250.0)
++      startTime = node.getFieldAsFloat('startTime', 0.0, ancestry)
++      stopTime = node.getFieldAsFloat('stopTime', 250.0, ancestry)
                
        if cycleInterval != None:
                stopTime = startTime+cycleInterval
        
--      loop = node.getFieldAsBool('loop', False)
++      loop = node.getFieldAsBool('loop', False, ancestry)
        
        time_cu.append((1+startTime, 0.0))
        time_cu.append((1+stopTime, 1.0/10.0))# anoying, the UI uses /10
                time_cu.extend = Blender.IpoCurve.ExtendTypes.CYCLIC # or - EXTRAP, CYCLIC_EXTRAP, CONST, 
  
  
--def importRoute(node):
++def importRoute(node, ancestry):
        '''
        Animation route only at the moment
        '''
        
++      if not hasattr(node, 'fields'):
++              return
++      
        routeIpoDict = node.getRouteIpoDict()
        
        def getIpo(id):
@@@ -2093,29 -2093,29 +2356,33 @@@ ROUTE champFly001.bindTime TO vpTs.set_
        
        for field in node.fields:
                if field and field[0]=='ROUTE':
--                      from_id, from_type = field[1].split('.')
--                      to_id, to_type = field[3].split('.')
++                      try:
++                              from_id, from_type = field[1].split('.')
++                              to_id, to_type = field[3].split('.')
++                      except:
++                              print "Warning, invalid ROUTE", field
++                              continue
                        
                        if from_type == 'value_changed':
                                if to_type == 'set_position':
                                        ipo = getIpo(to_id)
                                        set_data_from_node = defDict[from_id]
--                                      translatePositionInterpolator(set_data_from_node, ipo)
++                                      translatePositionInterpolator(set_data_from_node, ipo, ancestry)
                                
--                              if to_type == 'set_orientation':
++                              if to_type in ('set_orientation', 'rotation'):
                                        ipo = getIpo(to_id)
                                        set_data_from_node = defDict[from_id]
--                                      translateOrientationInterpolator(set_data_from_node, ipo)
++                                      translateOrientationInterpolator(set_data_from_node, ipo, ancestry)
                                
                                if to_type == 'set_scale':
                                        ipo = getIpo(to_id)
                                        set_data_from_node = defDict[from_id]
--                                      translateScalarInterpolator(set_data_from_node, ipo)
++                                      translateScalarInterpolator(set_data_from_node, ipo, ancestry)
                                
--                      elif from_type == 'bindTime':
++                      elif from_type =='bindTime':
                                ipo = getIpo(from_id)
                                time_node = defDict[to_id]
--                              translateTimeSensor(time_node, ipo)
++                              translateTimeSensor(time_node, ipo, ancestry)
                        
                
  
@@@ -2147,6 -2147,6 +2414,16 @@@ def load_web3d(path, PREF_FLAT=False, P
                #       continue
                
                spec = node.getSpec()
++              '''
++              prefix = node.getPrefix()
++              if prefix=='PROTO':
++                      pass
++              else
++              '''
++              if HELPER_FUNC and HELPER_FUNC(node, ancestry):
++                      # Note, include this function so the VRML/X3D importer can be extended
++                      # by an external script. - gets first pick 
++                      pass
                if spec=='Shape':
                        importShape(node, ancestry)
                elif spec in ('PointLight', 'DirectionalLight', 'SpotLight'):
                        ipo = bpy.data.ipos.new('web3d_ipo', 'Object')
                        translatePositionInterpolator(node, ipo)
                        '''
--                      
--              else:
--                      # Note, include this function so the VRML/X3D importer can be extended
--                      # by an external script.
--                      if HELPER_FUNC:
--                              HELPER_FUNC(node, ancestry)
--
--
--
++      
++      
++      
        # After we import all nodes, route events - anim paths
        for node, ancestry in all_nodes:
--              importRoute(node)
++              importRoute(node, ancestry)
        
        for node, ancestry in all_nodes:
                if node.isRoot():
@@@ -2289,24 -2289,24 +2560,32 @@@ if __name__ == '__main__'
  
  # load_web3d('/fe/x3d/www.web3d.org/x3d/content/examples/Basic/StudentProjects/PlayRoom.x3d') # invalid UVs
  
--'''
--import os
--# files = os.popen('find /fe/wrl -iname "*.wrl"').readlines()
--# files = os.popen('find /fe/x3d -iname "*.x3d"').readlines()
--files = os.popen('find   /fe/x3d/X3dExamplesSavage   -iname "*.x3d"').readlines()
  
--files.sort()
--tot = len(files)
--for i, f in enumerate(files):
--      if i < 12803 or i > 1000000:
--              continue
--      #if i != 12686:
--      #       continue
++
++def test():
++      import os
        
--      f = f.strip()
--      print f, i, tot
--      sce = bpy.data.scenes.new(f.split('/')[-1])
--      bpy.data.scenes.active = sce
--      # Window.
--      load_web3d(f, PREF_FLAT=True)
--'''
++      files = os.popen('find /fe/wrl -iname "*.wrl"').readlines()
++      # files = os.popen('find /fe/x3d -iname "*.x3d"').readlines()
++      # files = os.popen('find   /fe/x3d/X3dExamplesSavage   -iname "*.x3d"').readlines()
++
++      files.sort()
++      tot = len(files)
++      for i, f in enumerate(files):
++              if i < 124 or i > 1000000:
++                      continue
++              
++              #if i != 1068:
++              #       continue
++              
++              #if i != 12686:
++              #       continue
++              
++              f = f.strip()
++              print f, i, tot
++              sce = bpy.data.scenes.new(str(i) + '_' + f.split('/')[-1])
++              bpy.data.scenes.active = sce
++              # Window.
++              load_web3d(f, PREF_FLAT=True)
++      
++# test()
@@@ -112,7 -112,7 +112,7 @@@ def mesh2polys()
        Window.EditMode(0)
        me = meshOb.getData(mesh=1)
        polygons= polysFromMesh(me)
--      w=t=1
++      w = 1.0
        cu= Curve.New()
        cu.name = me.name
        cu.setFlag(1)
                        vIdx= 0
                
                v= poly[vIdx]
--              cu.appendNurb([v.co.x, v.co.y, v.co.z, w, t])
++              cu.appendNurb((v.co.x, v.co.y, v.co.z, w))
                vIdx += 1
                cu[i].type= 0 # Poly Line
                
                # Add all the points in the polyline.
                while vIdx<len(poly):
                        v= poly[vIdx]
--                      cu.appendPoint(i, [v.co.x, v.co.y, v.co.z, w])
++                      cu.appendPoint(i, (v.co.x, v.co.y, v.co.z, w))
                        vIdx+=1
                i+=1
        Window.WaitCursor(0)
index 0000000,0000000..86b5899
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,124 @@@
++#!BPY
++"""
++Name: 'Background Job Example'
++Blender: 248
++Group: 'ScriptTemplate'
++Tooltip: 'Script template for automating tasks from the command line with blender'
++"""
++
++from Blender import Window
++import bpy
++
++script_data = \
++'''# This script is an example of how you can run blender from the command line (in background mode with no interface)
++# to automate tasks, in this example it creates a text object, camera and light, then renders and/or saves it.
++# This example also shows how you can parse command line options to python scripts.
++# 
++# Example usage for this test.
++#  blender -b -P $HOME/background_job.py -- --text="Hello World" --render="/tmp/hello" --save="/tmp/hello.blend"
++# 
++# Notice all python args are after the '--' argument.
++
++import Blender
++import bpy
++
++def example_function(body_text, save_path, render_path):
++      
++      sce= bpy.data.scenes.active
++
++      txt_data= bpy.data.curves.new('MyText', 'Text3d')
++      
++      # Text Object
++      txt_ob = sce.objects.new(txt_data)                      # add the data to the scene as an object
++      txt_data.setText(body_text)                                     # set the body text to the command line arg given
++      txt_data.setAlignment(Blender.Text3d.MIDDLE)# center text
++      
++      # Camera
++      cam_data= bpy.data.cameras.new('MyCam')         # create new camera data
++      cam_ob= sce.objects.new(cam_data)                       # add the camera data to the scene (creating a new object)
++      sce.objects.camera= cam_ob                                      # set the active camera
++      cam_ob.loc= 0,0,10
++      
++      # Lamp
++      lamp_data= bpy.data.lamps.new('MyLamp')
++      lamp_ob= sce.objects.new(lamp_data)
++      lamp_ob.loc= 2,2,5
++
++      if save_path:
++              try:
++                      f= open(save_path, 'w')
++                      f.close()
++                      ok= True
++              except:
++                      print 'Cannot save to path "%s"' % save_path
++                      ok= False
++              
++              if ok:
++                      Blender.Save(save_path, 1)
++      
++      if render_path:
++              render= sce.render
++              render.extensions= True
++              render.renderPath = render_path
++              render.sFrame= 1
++              render.eFrame= 1
++              render.renderAnim()
++
++
++
++import sys            # to get command line args
++import optparse       # to parse options for us and print a nice help message
++
++script_name= 'background_job.py'
++
++def main():
++      
++      # get the args passed to blender after "--", all of which are ignored by blender specifically
++      # so python may receive its own arguments
++      argv= sys.argv
++
++      if '--' not in argv:
++              argv = [] # as if no args are passed
++      else:   
++              argv = argv[argv.index('--')+1: ] # get all args after "--"
++      
++      # When --help or no args are given, print this help
++      usage_text =  'Run blender in background mode with this script:\n'
++      usage_text += '  blender -b -P ' + script_name + ' -- [options]'
++                      
++      parser = optparse.OptionParser(usage = usage_text)
++      
++
++      # Example background utility, add some text and renders or saves it (with options)
++      # Possible types are: string, int, long, choice, float and complex.
++      parser.add_option('-t', '--text', dest='body_text', help='This text will be used to render an image', type='string')
++
++      parser.add_option('-s', '--save', dest='save_path', help='Save the generated file to the specified path', metavar='FILE')
++      parser.add_option('-r', '--render', dest='render_path', help='Render an image to the specified path', metavar='FILE')
++
++      options, args = parser.parse_args(argv) # In this example we wont use the args
++      
++      if not argv:
++              parser.print_help()
++              return
++
++      if not options.body_text:
++              print 'Error: --text="some string" argument not given, aborting.\n'
++              parser.print_help()
++              return
++      
++      # Run the example function
++      example_function(options.body_text, options.save_path, options.render_path)
++
++      print 'batch job finished, exiting'
++
++
++if __name__ == '__main__':
++      main()
++'''
++
++new_text = bpy.data.texts.new('background_job.py')
++new_text.write(script_data)
++bpy.data.texts.active = new_text
++Window.RedrawAll()
++
@@@ -42,28 -42,28 +42,15 @@@ from Blender import 
  import bpy
  import BPyMesh
  
--def extend():
--      sce = bpy.data.scenes.active
--      ob = sce.objects.active
--      
--      # print ob, ob.type
--      if ob == None or ob.type != 'Mesh':
--              Draw.PupMenu('ERROR: No mesh object.')
++def extend(EXTEND_MODE,ob):
++      if EXTEND_MODE == -1:
                return
--      
--      # Toggle Edit mode
++      me = ob.getData(mesh=1)
++      me_verts = me.verts
++              # Toggle Edit mode
        is_editmode = Window.EditMode()
        if is_editmode:
                Window.EditMode(0)
--      
--      me = ob.getData(mesh=1)
--      me_verts = me.verts
--      
--      # 0:normal extend, 1:edge length
--      EXTEND_MODE = Draw.PupMenu("Use Face Area%t|Loop Average%x2|None%x0")
--      if EXTEND_MODE == -1:
--              return
--      
        Window.WaitCursor(1)
        t = sys.time()
        edge_average_lengths = {}
                        uvs_vhash_target[edgepair_outer_target[iA]][:] = uvs_vhash_source[edgepair_inner_source[1]] + (uvs_vhash_source[edgepair_inner_source[1]] - uvs_vhash_source[edgepair_outer_source[0]])
        
        if not me.faceUV:
--              Draw.PupMenu('ERROR: Mesh has no face UV coords.')
--              return
++              me.faceUV= True
        
        face_act =      me.activeFace
        if face_act == -1:
        Window.RedrawAll()
        Window.WaitCursor(0)
  
--if __name__ == '__main__':
--      extend()
++
++def main():
++      sce = bpy.data.scenes.active
++      ob = sce.objects.active
++      
++      # print ob, ob.type
++      if ob == None or ob.type != 'Mesh':
++              Draw.PupMenu('ERROR: No mesh object.')
++              return
        
--      
++
++      
++      # 0:normal extend, 1:edge length
++      EXTEND_MODE = Draw.PupMenu("Use Face Area%t|Loop Average%x2|None%x0")
++      extend(EXTEND_MODE,ob)
++
++if __name__ == '__main__':
++      main()
++
@@@ -171,6 -171,6 +171,9 @@@ def main()
                f_uv = f.uv
                return [(v.co-face_corner_main, f_uv[i]) for i,v in enumerate(f.v)]
        
++      if me.faceUV==False:
++              me.faceUV= True
++
        coords = [ (co,uv) for f in me.faces if f.sel for co, uv in get_face_coords(f)]
        
        coords_orig = [uv.copy() for co, uv in coords]
        
  if __name__=='__main__':
        main()
--      Window.DrawProgressBar(1.0, '')
++      Window.DrawProgressBar(1.0, '')
++
@@@ -27,6 -27,6 +27,7 @@@ def matcol(mat)
                int(mat.R*255),\
                int(mat.G*255),\
                int(mat.B*255)
++      else:
                return None
  
  def mat2vcol(PREF_SEL_FACES_ONLY, PREF_ACTOB_ONLY, PREF_MULTIPLY_COLOR):
@@@ -47,7 -47,7 +48,7 @@@
                me= ob.getData(mesh=1)
                
                try:
--                      me.faceUV=True
++                      me.vertexColors=True
                except: # no faces
                        continue
                
@@@ -178,6 -227,6 +178,7 @@@ typedef struct Global 
  #define G_FILE_GLSL_NO_RAMPS   (1 << 19)
  #define G_FILE_GLSL_NO_NODES   (1 << 20)
  #define G_FILE_GLSL_NO_EXTRA_TEX (1 << 21)
++#define G_FILE_IGNORE_DEPRECATION_WARNINGS    (1 << 22)
  
  /* G.windowstate */
  #define G_WINDOWSTATE_USERDEF         0
@@@ -35,6 -42,6 +35,9 @@@ if env['WITH_BF_INTERNATIONAL']
  if env['WITH_BF_OPENEXR']:
      defs += ' WITH_OPENEXR'
  
++if env['WITH_BF_OPENJPEG']:
++    defs += ' WITH_OPENJPEG'
++
  if env['WITH_BF_DDS']:
      defs += ' WITH_DDS'
  
@@@ -46,6 -53,6 +49,9 @@@ if env['WITH_BF_QUICKTIME']
      defs += ' WITH_QUICKTIME'
      incs += ' ' + env['BF_QUICKTIME_INC']
  
++if env['WITH_BF_BULLET']:
++    defs += ' WITH_BULLET'
++
  if env['BF_NO_ELBEEM']:
      defs += ' DISABLE_ELBEEM'
  
@@@ -1237,7 -1236,7 +1237,7 @@@ int cloth_collision_moving_edges ( Clot
                                                if(out_normalVelocity < 0.0)
                                                {
                                                        out_normalVelocity*= -1.0;
--                                                      VecMulf(out_normal, -1.0);
++                                                      VecNegf(out_normal);
                                                }
  */
                                                /* Inelastic repulsion impulse. */
@@@ -898,7 -1044,7 +898,7 @@@ static void vectomat (float *vec, floa
                n[2] = 1.0;
        }
        if (axis > 2) axis -= 3;
--      else VecMulf(n,-1);
++      else VecNegf(n);
  
        /* n specifies the transformation of the track axis */
        if (flags & TARGET_Z_UP) { 
@@@ -2039,7 -2182,7 +2039,7 @@@ static void locktrack_evaluate (bConstr
                                        Projf(vec2, vec, cob->matrix[0]);
                                        VecSubf(totmat[1], vec, vec2);
                                        Normalize(totmat[1]);
--                                      VecMulf(totmat[1],-1);
++                                      VecNegf(totmat[1]);
                                        
                                        /* the x axis is fixed */
                                        totmat[0][0] = cob->matrix[0][0];
                                        Projf(vec2, vec, cob->matrix[0]);
                                        VecSubf(totmat[2], vec, vec2);
                                        Normalize(totmat[2]);
--                                      VecMulf(totmat[2],-1);
++                                      VecNegf(totmat[2]);
                                                
                                        /* the x axis is fixed */
                                        totmat[0][0] = cob->matrix[0][0];
                                        Projf(vec2, vec, cob->matrix[1]);
                                        VecSubf(totmat[0], vec, vec2);
                                        Normalize(totmat[0]);
--                                      VecMulf(totmat[0],-1);
++                                      VecNegf(totmat[0]);
                                        
                                        /* the y axis is fixed */
                                        totmat[1][0] = cob->matrix[1][0];
                                        Projf(vec2, vec, cob->matrix[1]);
                                        VecSubf(totmat[2], vec, vec2);
                                        Normalize(totmat[2]);
--                                      VecMulf(totmat[2],-1);
++                                      VecNegf(totmat[2]);
                                        
                                        /* the y axis is fixed */
                                        totmat[1][0] = cob->matrix[1][0];
                                        Projf(vec2, vec, cob->matrix[2]);
                                        VecSubf(totmat[0], vec, vec2);
                                        Normalize(totmat[0]);
--                                      VecMulf(totmat[0],-1);
++                                      VecNegf(totmat[0]);
                                        
                                        /* the z axis is fixed */
                                        totmat[2][0] = cob->matrix[2][0];
                                        Projf(vec2, vec, cob->matrix[2]);
                                        VecSubf(totmat[1], vec, vec2);
                                        Normalize(totmat[1]);
--                                      VecMulf(totmat[1],-1);
++                                      VecNegf(totmat[1]);
                                        
                                        /* the z axis is fixed */
                                        totmat[2][0] = cob->matrix[2][0];
@@@ -252,7 -251,7 +252,7 @@@ static float eff_calc_visibility(Scene 
                return 0;
        
        VECCOPY(norm, dir);
--      VecMulf(norm, -1.0);
++      VecNegf(norm);
        len = Normalize(norm);
        
        // check all collision objects
@@@ -766,6 -767,6 +766,10 @@@ int BKE_imtype_to_ftype(int imtype
                return RAWTGA;
        else if(imtype==R_HAMX)
                return AN_hamx;
++#ifdef WITH_OPENJPEG
++      else if(imtype==R_JP2)
++              return JP2;
++#endif
        else
                return JPG|90;
  }
@@@ -800,6 -801,6 +804,10 @@@ int BKE_ftype_to_imtype(int ftype
                return R_RAWTGA;
        else if(ftype == AN_hamx)
                return R_HAMX;
++#ifdef WITH_OPENJPEG
++      else if(ftype & JP2)
++              return R_JP2;
++#endif
        else
                return R_JPEG90;
  }
@@@ -876,6 -877,6 +884,12 @@@ void BKE_add_image_extension(Scene *sce
                if(!BLI_testextensie(string, ".tga"))
                        extension= ".tga";
        }
++#ifdef WITH_OPENJPEG
++      else if(imtype==R_JP2) {
++              if(!BLI_testextensie(string, ".jp2"))
++                      extension= ".jp2";
++      }
++#endif
        else { //   R_MOVIE, R_AVICODEC, R_AVIRAW, R_AVIJPEG, R_JPEG90, R_QUICKTIME etc
                if(!( BLI_testextensie(string, ".jpg") || BLI_testextensie(string, ".jpeg")))
                        extension= ".jpg";
@@@ -1219,6 -1220,6 +1233,28 @@@ int BKE_write_ibuf(Scene *scene, ImBuf 
        else if(imtype==R_HAMX) {
                ibuf->ftype= AN_hamx;
        }
++#ifdef WITH_OPENJPEG
++      else if(imtype==R_JP2) {
++              if(quality < 10) quality= 90;
++              ibuf->ftype= JP2|quality;
++              
++              if (subimtype & R_JPEG2K_16BIT) {
++                      ibuf->ftype |= JP2_16BIT;
++              } else if (subimtype & R_JPEG2K_12BIT) {
++                      ibuf->ftype |= JP2_12BIT;
++              }
++              
++              if (subimtype & R_JPEG2K_YCC) {
++                      ibuf->ftype |= JP2_YCC;
++              }
++              
++              if (subimtype & R_JPEG2K_CINE_PRESET) {
++                      ibuf->ftype |= JP2_CINE;
++                      if (subimtype & R_JPEG2K_CINE_48FPS)
++                              ibuf->ftype |= JP2_CINE_48FPS;
++              }
++      }
++#endif
        else {
                /* R_JPEG90, R_MOVIE, etc. default we save jpegs */
                if(quality < 10) quality= 90;
@@@ -824,7 -831,7 +824,7 @@@ void psys_thread_distribute_particle(Pa
                                        VecCopyf(tan,seam->tan);
                                        VecSubf(temp2,co1,temp);
                                        if(Inpf(tan,temp2)<0.0f)
--                                              VecMulf(tan,-1.0f);
++                                              VecNegf(tan);
                                }
                                for(w=0; w<maxw; w++){
                                        VecSubf(temp2,ptn[w].co,temp);
@@@ -1878,7 -1877,7 +1878,7 @@@ void reset_particle(Scene *scene, Parti
                }
                
                /* create rotation quat */
--              VecMulf(rot_vec,-1.0);
++              VecNegf(rot_vec);
                vectoquat(rot_vec, OB_POSX, OB_POSZ, q2);
  
                /* randomize rotation quat */
@@@ -3025,7 -3022,7 +3025,7 @@@ static void particle_intersect_face(voi
                                        CalcNormFloat(t0, t1, t2, col->nor);
                                        VECSUB(temp, co2, co1);
                                        if(Inpf(col->nor, temp) > 0.0f)
--                                              VecMulf(col->nor, -1.0f);
++                                              VecNegf(col->nor);
  
                                        VECCOPY(col->vel,vel);
  
@@@ -3805,7 -3802,7 +3805,7 @@@ static void boid_body(Scene *scene, Boi
        VecRotToQuat(pa->state.vel,bank,q);
  
        VECCOPY(dvec,pa->state.vel);
--      VecMulf(dvec,-1.0f);
++      VecNegf(dvec);
        vectoquat(dvec, OB_POSX, OB_POSZ, q2);
  
        QuatMul(pa->state.rot,q,q2);
@@@ -242,6 -241,6 +242,7 @@@ int VecLen(int *v1, int *v2)
  float VecLenf(float *v1, float *v2);
  float VecLength(float *v);
  void VecMulf(float *v1, float f);
++void VecNegf(float *v1);
  
  int VecLenCompare(float *v1, float *v2, float limit);
  int VecCompare(float *v1, float *v2, float limit);
@@@ -2188,6 -2183,6 +2188,13 @@@ void VecMulf(float *v1, float f
        v1[2]*= f;
  }
  
++void VecNegf(float *v1)
++{
++      v1[0] = -v1[0];
++      v1[1] = -v1[1];
++      v1[2] = -v1[2];
++}
++
  void VecOrthoBasisf(float *v, float *v1, float *v2)
  {
        float f = sqrt(v[0]*v[0] + v[1]*v[1]);
@@@ -3950,7 -3945,7 +3957,7 @@@ int SweepingSphereIntersectsTriangleUV(
        Normalize(nor);
  
        /* flip normal */
--      if(Inpf(nor,vel)>0.0f) VecMulf(nor,-1.0f);
++      if(Inpf(nor,vel)>0.0f) VecNegf(nor);
        
        a=Inpf(p1,nor)-Inpf(v0,nor);
        nordotv=Inpf(nor,vel);
@@@ -4682,7 -4616,7 +4689,7 @@@ void tangent_from_uv(float *uv1, float 
  
        /* check flip */
        if ((ct[0]*n[0] + ct[1]*n[1] + ct[2]*n[2]) < 0.0f)
--              VecMulf(tang, -1.0f);
++              VecNegf(tang);
  }
  
  /* used for zoom values*/
@@@ -807,15 -809,15 +807,15 @@@ static void testAxialSymmetry(BGraph *g
        
        if (abs(nor[0]) > abs(nor[1]) && abs(nor[0]) > abs(nor[2]) && nor[0] < 0)
        {
--              VecMulf(nor, -1);
++              VecNegf(nor);
        }
        else if (abs(nor[1]) > abs(nor[0]) && abs(nor[1]) > abs(nor[2]) && nor[1] < 0)
        {
--              VecMulf(nor, -1);
++              VecNegf(nor);
        }
        else if (abs(nor[2]) > abs(nor[1]) && abs(nor[2]) > abs(nor[0]) && nor[2] < 0)
        {
--              VecMulf(nor, -1);
++              VecNegf(nor);
        }
        
        /* mirror node2 along axis */
@@@ -3396,6 -3179,6 +3396,7 @@@ static void direct_link_modifiers(FileD
                        FluidsimModifierData *fluidmd = (FluidsimModifierData*) md;
                        
                        fluidmd->fss= newdataadr(fd, fluidmd->fss);
++                      fluidmd->fss->meshSurfNormals = 0;
                }
                else if (md->type==eModifierType_Collision) {
                        
@@@ -8517,6 -7856,6 +8518,7 @@@ static void do_versions(FileData *fd, L
                                
                                fluidmd->fss->lastgoodframe = INT_MAX;
                                fluidmd->fss->flag = 0;
++                              fluidmd->fss->meshSurfNormals = 0;
                        }
                }
        }
  #endif
  #define RADHDR  (1<<24)
  
++#ifdef WITH_OPENJPEG
++#define JP2                            (1 << 18)
++#endif
++
  #define RAWTGA        (TGA | 1)
  
  #define JPG_STD       (JPG | (0 << 8))
  #define IS_tim(x)             (x->ftype & TIM)
  #define IS_tiff(x)            (x->ftype & TIFF)
  #define IS_openexr(x)           (x->ftype & OPENEXR)
++#define IS_jp2(x)           (x->ftype & JP2)
  
  
  #define IMAGIC        0732
index 2bd91ec,0000000..947b3ba
mode 100644,000000..100644
--- /dev/null
@@@ -1,851 -1,0 +1,873 @@@
 +/**
 + * $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) 2008 Blender Foundation.
 + * All rights reserved.
 + *
 + * 
 + * Contributor(s): Blender Foundation
 + *
 + * ***** END GPL LICENSE BLOCK *****
 + */
 +
 +#include <stdlib.h>
 +#include <math.h>
 +
 +#include "MEM_guardedalloc.h"
 +
 +#include "DNA_scene_types.h"
 +#include "DNA_screen_types.h"
 +#include "DNA_space_types.h"
 +#include "DNA_view2d_types.h"
 +#include "DNA_userdef_types.h"
 +#include "DNA_windowmanager_types.h"
 +
 +#include "RNA_access.h"
 +#include "RNA_define.h"
 +
 +#include "BLI_blenlib.h"
 +
 +#include "BKE_context.h"
 +#include "BKE_global.h"
 +#include "BKE_utildefines.h"
 +
 +#include "WM_api.h"
 +#include "WM_types.h"
 +
 +#include "BIF_gl.h"
 +#include "BIF_glutil.h"
 +
 +#include "UI_interface.h"
 +#include "UI_interface_icons.h"
 +#include "UI_view2d.h"
 +#include "UI_resources.h"
 +#include "UI_text.h"
 +
 +#include "ED_markers.h"
 +#include "ED_screen.h"
 +#include "ED_types.h"
 +#include "ED_util.h"
 +
 +/* ************* Marker API **************** */
 +
 +static ListBase *context_get_markers(const bContext *C)
 +{
 +      
 +#if 0
 +      /* XXX get them from pose */
 +      if ((slink->spacetype == SPACE_ACTION) && (saction->flag & SACTION_POSEMARKERS_MOVE)) {
 +              if (saction->action)
 +                      markers= &saction->action->markers;
 +              else
 +                      markers= NULL;
 +      }
 +      else
 +#endif
 +      
 +      return &CTX_data_scene(C)->markers;
 +}
 +
 +/* ************* Marker Drawing ************ */
 +
 +/* XXX */
 +extern void ui_rasterpos_safe(float x, float y, float aspect);
 +
 +/* function to draw markers */
 +static void draw_marker(View2D *v2d, TimeMarker *marker, int cfra, int flag)
 +{
 +      float xpos, ypixels, xscale, yscale;
 +      int icon_id= 0;
 +      
 +      xpos = marker->frame;
 +      
 +      /* no time correction for framelen! space is drawn with old values */
 +      ypixels= v2d->mask.ymax-v2d->mask.ymin;
 +      UI_view2d_getscale(v2d, &xscale, &yscale);
 +      
 +      glScalef(1.0/xscale, 1.0, 1.0);
 +      
 +      glEnable(GL_BLEND);
 +      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);                      
 +      
 +      /* vertical line - dotted */
 +      if (flag & DRAW_MARKERS_LINES) {
 +              setlinestyle(3);
 +              
 +              if (marker->flag & SELECT)
 +                      glColor4ub(255, 255, 255, 96);
 +              else
 +                      glColor4ub(0, 0, 0, 96);
 +              
 +              glBegin(GL_LINES);
 +                      glVertex2f((xpos*xscale)+0.5, 12);
 +                      glVertex2f((xpos*xscale)+0.5, 34*yscale); /* a bit lazy but we know it cant be greater then 34 strips high*/
 +              glEnd();
 +              
 +              setlinestyle(0);
 +      }
 +      
 +      /* 5 px to offset icon to align properly, space / pixels corrects for zoom */
 +      if (flag & DRAW_MARKERS_LOCAL) {
 +              icon_id= (marker->flag & ACTIVE) ? ICON_PMARKER_ACT : 
 +              (marker->flag & SELECT) ? ICON_PMARKER_SEL : 
 +              ICON_PMARKER;
 +      }
 +      else {
 +              icon_id= (marker->flag & SELECT) ? ICON_MARKER_HLT : 
 +              ICON_MARKER;
 +      }
 +      
 +      UI_icon_draw(xpos*xscale-5.0, 16.0, icon_id);
 +      
 +      glBlendFunc(GL_ONE, GL_ZERO);
 +      glDisable(GL_BLEND);
 +      
 +      /* and the marker name too, shifted slightly to the top-right */
 +      if (marker->name && marker->name[0]) {
 +              if(marker->flag & SELECT) {
 +                      UI_ThemeColor(TH_TEXT_HI);
 +                      ui_rasterpos_safe(xpos*xscale+4.0, (ypixels<=39.0)?(ypixels-10.0):29.0, 1.0);
 +              }
 +              else {
 +                      UI_ThemeColor(TH_TEXT);
 +                      if((marker->frame <= cfra) && (marker->frame+5 > cfra))
 +                              ui_rasterpos_safe(xpos*xscale+4.0, (ypixels<=39.0)?(ypixels-10.0):29.0, 1.0);
 +                      else
 +                              ui_rasterpos_safe(xpos*xscale+4.0, 17.0, 1.0);
 +              }
 +              UI_DrawString(G.font, marker->name, 0);
 +      }
 +      glScalef(xscale, 1.0, 1.0);
 +}
 +
 +/* Draw Scene-Markers in time window */
 +void draw_markers_time(const bContext *C, int flag)
 +{
 +      ListBase *markers= context_get_markers(C);
 +      View2D *v2d= UI_view2d_fromcontext(C);
 +      TimeMarker *marker;
 +      
++      if(markers == NULL)
++              return;
++      
 +      /* unselected markers are drawn at the first time */
 +      for (marker= markers->first; marker; marker= marker->next) {
 +              if (!(marker->flag & SELECT)) draw_marker(v2d, marker, CTX_data_scene(C)->r.cfra, flag);
 +      }
 +      
 +      /* selected markers are drawn later */
 +      for (marker= markers->first; marker; marker= marker->next) {
 +              if (marker->flag & SELECT) draw_marker(v2d, marker, CTX_data_scene(C)->r.cfra, flag);
 +      }
 +}
 +
 +
 +
 +/* ************************** add markers *************************** */
 +
 +/* add TimeMarker at curent frame */
 +static int ed_marker_add(bContext *C, wmOperator *op)
 +{
 +      ListBase *markers= context_get_markers(C);
 +      TimeMarker *marker;
 +      int frame= CTX_data_scene(C)->r.cfra;
 +      
++      if(markers == NULL)
++              return OPERATOR_CANCELLED;
++      
 +      /* two markers can't be at the same place */
 +      for(marker= markers->first; marker; marker= marker->next)
 +              if(marker->frame == frame) 
 +                      return OPERATOR_CANCELLED;
 +      
 +      /* deselect all */
 +      for(marker= markers->first; marker; marker= marker->next)
 +              marker->flag &= ~SELECT;
 +      
 +      marker = MEM_callocN(sizeof(TimeMarker), "TimeMarker");
 +      marker->flag= SELECT;
 +      marker->frame= frame;
 +      sprintf(marker->name, "Frame %d", frame); // XXX - temp code only
 +      BLI_addtail(markers, marker);
 +      
 +      WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL);
 +      //BIF_undo_push("Add Marker");
 +      
 +      return OPERATOR_FINISHED;
 +}
 +
 +static void MARKER_OT_add(wmOperatorType *ot)
 +{
 +      /* identifiers */
 +      ot->name= "Add Time Marker";
 +      ot->idname= "MARKER_OT_add";
 +      
 +      /* api callbacks */
 +      ot->exec= ed_marker_add;
 +      ot->poll= ED_operator_areaactive;
 +      
 +}
 +
 +/* ************************** transform markers *************************** */
 +
 +
 +/* operator state vars used:  
 +      frs: delta movement
 +
 +functions:
 +
 +      init()   check selection, add customdata with old values and some lookups
 +
 +      apply()  do the actual movement
 +
 +      exit()  cleanup, send notifier
 +
 +    cancel() to escpae from modal
 +
 +callbacks:
 +
 +      exec()  calls init, apply, exit 
 +
 +      invoke() calls init, adds modal handler
 +
 +      modal() accept modal events while doing it, ends with apply and exit, or cancel
 +
 +*/
 +
 +typedef struct MarkerMove {
 +      SpaceLink *slink;
 +      ListBase *markers;
 +      int event_type;         /* store invoke-event, to verify */
 +      int *oldframe, evtx, firstx;
 +} MarkerMove;
 +
 +/* copy selection to temp buffer */
 +/* return 0 if not OK */
 +static int ed_marker_move_init(bContext *C, wmOperator *op)
 +{
 +      ListBase *markers= context_get_markers(C);
 +      MarkerMove *mm;
 +      TimeMarker *marker;
 +      int totmark=0;
 +      int a;
++
++      if(markers == NULL) return 0;
 +      
 +      for (marker= markers->first; marker; marker= marker->next)
 +              if (marker->flag & SELECT) totmark++;
 +      
 +      if (totmark==0) return 0;
 +      
 +      op->customdata= mm= MEM_callocN(sizeof(MarkerMove), "Markermove");
 +      mm->slink= CTX_wm_space_data(C);
 +      mm->markers= markers;
 +      mm->oldframe= MEM_callocN(totmark*sizeof(int), "MarkerMove oldframe");
 +      
 +      for (a=0, marker= markers->first; marker; marker= marker->next) {
 +              if (marker->flag & SELECT) {
 +                      mm->oldframe[a]= marker->frame;
 +                      a++;
 +              }
 +      }
 +      
 +      return 1;
 +}
 +
 +/* free stuff */
 +static void ed_marker_move_exit(bContext *C, wmOperator *op)
 +{
 +      MarkerMove *mm= op->customdata;
 +      
 +      MEM_freeN(mm->oldframe);
 +      MEM_freeN(op->customdata);
 +      op->customdata= NULL;
 +}
 +
 +static int ed_marker_move_invoke(bContext *C, wmOperator *op, wmEvent *evt)
 +{
 +      if(ed_marker_move_init(C, op)) {
 +              MarkerMove *mm= op->customdata;
 +              
 +              mm->evtx= evt->x;
 +              mm->firstx= evt->x;
 +              mm->event_type= evt->type;
 +              
 +              /* add temp handler */
 +              WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
 +              
 +              /* reset frs delta */
 +              RNA_int_set(op->ptr, "frames", 0);
 +              
 +              return OPERATOR_RUNNING_MODAL;
 +      }
 +      
 +      return OPERATOR_CANCELLED;
 +}
 +
 +/* note, init has to be called succesfully */
 +static void ed_marker_move_apply(bContext *C, wmOperator *op)
 +{
 +      MarkerMove *mm= op->customdata;
 +      TimeMarker *marker;
 +      int a, offs;
 +      
 +      offs= RNA_int_get(op->ptr, "frames");
 +      for (a=0, marker= mm->markers->first; marker; marker= marker->next) {
 +              if (marker->flag & SELECT) {
 +                      marker->frame= mm->oldframe[a] + offs;
 +                      a++;
 +              }
 +      }
 +}
 +
 +/* only for modal */
 +static void ed_marker_move_cancel(bContext *C, wmOperator *op)
 +{
 +      RNA_int_set(op->ptr, "frames", 0);
 +      ed_marker_move_apply(C, op);
 +      ed_marker_move_exit(C, op);     
 +      
 +      WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL);
 +}
 +
 +
 +
 +static int ed_marker_move_modal(bContext *C, wmOperator *op, wmEvent *evt)
 +{
 +      Scene *scene= CTX_data_scene(C);
 +      MarkerMove *mm= op->customdata;
 +      View2D *v2d= UI_view2d_fromcontext(C);
 +      TimeMarker *marker, *selmarker=NULL;
 +      float dx, fac;
 +      char str[256];
 +              
 +      switch(evt->type) {
 +              case ESCKEY:
 +                      ed_marker_move_cancel(C, op);
 +                      return OPERATOR_CANCELLED;
 +
 +              case LEFTMOUSE:
 +              case MIDDLEMOUSE:
 +              case RIGHTMOUSE:
 +                      if(WM_modal_tweak_exit(evt, mm->event_type)) {
 +                              ed_marker_move_exit(C, op);
 +                              WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL);
 +                              return OPERATOR_FINISHED;
 +                      }
 +                      
 +                      break;
 +              case MOUSEMOVE:
 +      
 +                      dx= v2d->mask.xmax-v2d->mask.xmin;
 +                      dx= (v2d->cur.xmax-v2d->cur.xmin)/dx;
 +                      
 +                      if (evt->x != mm->evtx) {       /* XXX maybe init for firsttime */
 +                              int a, offs, totmark=0;
 +                              
 +                              mm->evtx= evt->x;
 +                              
 +                              fac= ((float)(evt->x - mm->firstx)*dx);
 +                              
 +                              if (ELEM(mm->slink->spacetype, SPACE_TIME, SPACE_SOUND)) 
 +                                      apply_keyb_grid(evt->shift, evt->ctrl, &fac, 0.0, FPS, 0.1*FPS, 0);
 +                              else
 +                                      apply_keyb_grid(evt->shift, evt->ctrl, &fac, 0.0, 1.0, 0.1, U.flag & USER_AUTOGRABGRID);
 +                              
 +                              offs= (int)fac;
 +                              RNA_int_set(op->ptr, "frames", offs);
 +                              ed_marker_move_apply(C, op);
 +                              
 +                              /* cruft below is for header print */
 +                              for (a=0, marker= mm->markers->first; marker; marker= marker->next) {
 +                                      if (marker->flag & SELECT) {
 +                                              selmarker= marker;
 +                                              a++; totmark++;
 +                                      }
 +                              }
 +                              
 +                              if (totmark==1) {       
 +                                      /* we print current marker value */
 +                                      if (ELEM(mm->slink->spacetype, SPACE_TIME, SPACE_SOUND)) {
 +                                              SpaceTime *stime= (SpaceTime *)mm->slink;
 +                                              if (stime->flag & TIME_DRAWFRAMES) 
 +                                                      sprintf(str, "Marker %d offset %d", selmarker->frame, offs);
 +                                              else 
 +                                                      sprintf(str, "Marker %.2f offset %.2f", FRA2TIME(selmarker->frame), FRA2TIME(offs));
 +                                      }
 +                                      else if (mm->slink->spacetype == SPACE_ACTION) {
 +#if 0                                         
 +XXX                                           if (saction->flag & SACTION_DRAWTIME)
 +                                                      sprintf(str, "Marker %.2f offset %.2f", FRA2TIME(selmarker->frame), FRA2TIME(offs));
 +                                              else
 +                                                      sprintf(str, "Marker %.2f offset %.2f", (double)(selmarker->frame), (double)(offs));
 +#endif                                        
 +                                      }
 +                                      else {
 +                                              sprintf(str, "Marker %.2f offset %.2f", (double)(selmarker->frame), (double)(offs));
 +                                      }
 +                              }
 +                              else {
 +                                      /* we only print the offset */
 +                                      if (ELEM(mm->slink->spacetype, SPACE_TIME, SPACE_SOUND)) { 
 +                                              SpaceTime *stime= (SpaceTime *)mm->slink;
 +                                              if (stime->flag & TIME_DRAWFRAMES) 
 +                                                      sprintf(str, "Marker offset %d ", offs);
 +                                              else 
 +                                                      sprintf(str, "Marker offset %.2f ", FRA2TIME(offs));
 +                                      }
 +#if 0                                 
 +XXX                                   else if (mm->slink->spacetype == SPACE_ACTION) {
 +                                              if (saction->flag & SACTION_DRAWTIME)
 +                                                      sprintf(str, "Marker offset %.2f ", FRA2TIME(offs));
 +                                              else
 +                                                      sprintf(str, "Marker offset %.2f ", (double)(offs));
 +                                      }
 +#endif                                        
 +                                      else {
 +                                              sprintf(str, "Marker offset %.2f ", (double)(offs));
 +                                      }
 +                              }
 +                              
 +                              WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL);
 +                              // headerprint(str); XXX
 +                      }
 +      }
 +
 +      return OPERATOR_RUNNING_MODAL;
 +}
 +
 +static int ed_marker_move_exec(bContext *C, wmOperator *op)
 +{
 +      if(ed_marker_move_init(C, op)) {
 +              ed_marker_move_apply(C, op);
 +              ed_marker_move_exit(C, op);
 +              return OPERATOR_FINISHED;
 +      }
 +      return OPERATOR_PASS_THROUGH;
 +}
 +
 +static void MARKER_OT_move(wmOperatorType *ot)
 +{
 +      /* identifiers */
 +      ot->name= "Move Time Marker";
 +      ot->idname= "MARKER_OT_move";
 +      
 +      /* api callbacks */
 +      ot->exec= ed_marker_move_exec;
 +      ot->invoke= ed_marker_move_invoke;
 +      ot->modal= ed_marker_move_modal;
 +      ot->poll= ED_operator_areaactive;
 +      
 +      /* rna storage */
 +      RNA_def_int(ot->srna, "frames", 0, INT_MIN, INT_MAX, "Frames", "", INT_MIN, INT_MAX);
 +}
 +
 +/* ************************** duplicate markers *************************** */
 +
 +/* operator state vars used:  
 +      frs: delta movement
 +
 +functions:
 +
 +      apply()  do the actual duplicate
 +
 +callbacks:
 +
 +      exec()  calls apply, move_exec
 +
 +      invoke() calls apply, move_invoke
 +
 +      modal() uses move_modal
 +
 +*/
 +
 +
 +/* duplicate selected TimeMarkers */
 +static void ed_marker_duplicate_apply(bContext *C, wmOperator *op)
 +{
 +      ListBase *markers= context_get_markers(C);
 +      TimeMarker *marker, *newmarker;
 +      
++      if(markers == NULL) return;
++
 +      /* go through the list of markers, duplicate selected markers and add duplicated copies
 +      * to the begining of the list (unselect original markers) */
 +      for(marker= markers->first; marker; marker= marker->next) {
 +              if(marker->flag & SELECT){
 +                      /* unselect selected marker */
 +                      marker->flag &= ~SELECT;
 +                      /* create and set up new marker */
 +                      newmarker = MEM_callocN(sizeof(TimeMarker), "TimeMarker");
 +                      newmarker->flag= SELECT;
 +                      newmarker->frame= marker->frame;
 +                      BLI_strncpy(newmarker->name, marker->name, sizeof(marker->name));
 +                      /* new marker is added to the begining of list */
 +                      BLI_addhead(markers, newmarker);
 +              }
 +      }
 +}
 +
 +static int ed_marker_duplicate_exec(bContext *C, wmOperator *op)
 +{
 +      ed_marker_duplicate_apply(C, op);
 +      ed_marker_move_exec(C, op);     /* assumes frs delta set */
 +      
 +      return OPERATOR_FINISHED;
 +      
 +}
 +
 +static int ed_marker_duplicate_invoke(bContext *C, wmOperator *op, wmEvent *evt)
 +{
 +      ed_marker_duplicate_apply(C, op);
 +      return ed_marker_move_invoke(C, op, evt);
 +}
 +
 +static void MARKER_OT_duplicate(wmOperatorType *ot)
 +{
 +      /* identifiers */
 +      ot->name= "Duplicate Time Marker";
 +      ot->idname= "MARKER_OT_duplicate";
 +      
 +      /* api callbacks */
 +      ot->exec= ed_marker_duplicate_exec;
 +      ot->invoke= ed_marker_duplicate_invoke;
 +      ot->modal= ed_marker_move_modal;
 +      ot->poll= ED_operator_areaactive;
 +      
 +      /* rna storage */
 +      RNA_def_int(ot->srna, "frames", 0, INT_MIN, INT_MAX, "Frames", "", INT_MIN, INT_MAX);
 +}
 +
 +/* ************************** selection ************************************/
 +
 +/* select/deselect TimeMarker at current frame */
 +static void select_timeline_marker_frame(ListBase *markers, int frame, unsigned char shift)
 +{
 +      TimeMarker *marker;
 +      int select=0;
 +      
 +      for(marker= markers->first; marker; marker= marker->next) {
 +              /* if Shift is not set, then deselect Markers */
 +              if(!shift) marker->flag &= ~SELECT;
 +              /* this way a not-shift select will allways give 1 selected marker */
 +              if((marker->frame == frame) && (!select)) {
 +                      if(marker->flag & SELECT) 
 +                              marker->flag &= ~SELECT;
 +                      else
 +                              marker->flag |= SELECT;
 +                      select = 1;
 +              }
 +      }
 +}
 +
 +int find_nearest_marker_time(ListBase *markers, float dx)
 +{
 +      TimeMarker *marker, *nearest= NULL;
 +      float dist, min_dist= 1000000;
 +      
 +      for(marker= markers->first; marker; marker= marker->next) {
 +              dist = ABS((float)marker->frame - dx);
 +              if(dist < min_dist){
 +                      min_dist= dist;
 +                      nearest= marker;
 +              }
 +      }
 +      
 +      if(nearest) return nearest->frame;
 +      else return (int)floor(dx); /* hrmf? */
 +}
 +
 +
 +static int ed_marker_select(bContext *C, wmEvent *evt, int extend)
 +{
 +      ListBase *markers= context_get_markers(C);
 +      View2D *v2d= UI_view2d_fromcontext(C);
 +      float viewx;
 +      int x, y, cfra;
 +      
++      if(markers == NULL)
++              return OPERATOR_PASS_THROUGH;
++
 +      x= evt->x - CTX_wm_region(C)->winrct.xmin;
 +      y= evt->y - CTX_wm_region(C)->winrct.ymin;
 +      
 +      UI_view2d_region_to_view(v2d, x, y, &viewx, NULL);      
 +      
 +      cfra= find_nearest_marker_time(markers, viewx);
 +      
 +      if (extend)
 +              select_timeline_marker_frame(markers, cfra, 1);
 +      else
 +              select_timeline_marker_frame(markers, cfra, 0);
 +      
 +      WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL);
 +
 +      /* allowing tweaks */
 +      return OPERATOR_PASS_THROUGH;
 +}
 +
 +static int ed_marker_select_extend_invoke(bContext *C, wmOperator *op, wmEvent *evt)
 +{
 +      return ed_marker_select(C, evt, 1);
 +}
 +
 +static int ed_marker_select_invoke(bContext *C, wmOperator *op, wmEvent *evt)
 +{
 +      return ed_marker_select(C, evt, 0);
 +}
 +
 +static void MARKER_OT_mouseselect(wmOperatorType *ot)
 +{
 +      /* identifiers */
 +      ot->name= "Select Time Marker";
 +      ot->idname= "MARKER_OT_mouseselect";
 +      
 +      /* api callbacks */
 +      ot->invoke= ed_marker_select_invoke;
 +      ot->poll= ED_operator_areaactive;
 +}
 +
 +static void MARKER_OT_mouseselect_extend(wmOperatorType *ot)
 +{
 +      /* identifiers */
 +      ot->name= "Extend Select Time Marker";
 +      ot->idname= "MARKER_OT_mouseselect_extend";
 +      
 +      /* api callbacks */
 +      ot->invoke= ed_marker_select_extend_invoke;
 +      ot->poll= ED_operator_areaactive;
 +}
 +
 +/* *************************** border select markers **************** */
 +
 +/* operator state vars used: (added by default WM callbacks)   
 +      xmin, ymin     
 +      xmax, ymax     
 +
 +customdata: the wmGesture pointer, with subwindow
 +
 +callbacks:
 +
 +      exec()  has to be filled in by user
 +
 +      invoke() default WM function
 +                      adds modal handler
 +
 +      modal() default WM function 
 +                      accept modal events while doing it, calls exec(), handles ESC and border drawing
 +
 +      poll()  has to be filled in by user for context
 +*/
 +
 +static int ed_marker_border_select_exec(bContext *C, wmOperator *op)
 +{
 +      View2D *v2d= UI_view2d_fromcontext(C);
 +      ListBase *markers= context_get_markers(C);
 +      TimeMarker *marker;
 +      float xminf, xmaxf, yminf, ymaxf;
 +      int event_type= RNA_int_get(op->ptr, "event_type");
 +      int xmin= RNA_int_get(op->ptr, "xmin");
 +      int xmax= RNA_int_get(op->ptr, "xmax");
 +      int ymin= RNA_int_get(op->ptr, "ymin");
 +      int ymax= RNA_int_get(op->ptr, "ymax");
 +      
 +      UI_view2d_region_to_view(v2d, xmin, ymin, &xminf, &yminf);      
 +      UI_view2d_region_to_view(v2d, xmax, ymax, &xmaxf, &ymaxf);      
 +      
 +      /* XXX disputable */
 +      if(yminf > 30.0f || ymaxf < 0.0f)
 +              return 0;
 +      
++      if(markers == NULL)
++              return 0;
++      
 +      /* XXX marker context */
 +      for(marker= markers->first; marker; marker= marker->next) {
 +              if ((marker->frame > xminf) && (marker->frame <= xmaxf)) {
 +                      switch (event_type) {
 +                              case LEFTMOUSE:
 +                                      if ((marker->flag & SELECT) == 0) 
 +                                              marker->flag |= SELECT;
 +                                      break;
 +                              case RIGHTMOUSE:
 +                                      if (marker->flag & SELECT) 
 +                                              marker->flag &= ~SELECT;
 +                                      break;
 +                      }
 +              }
 +      }
 +      
 +      WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL);
 +
 +      return 1;
 +}
 +
 +static void MARKER_OT_border_select(wmOperatorType *ot)
 +{
 +      /* identifiers */
 +      ot->name= "Marker Border select";
 +      ot->idname= "MARKER_OT_border_select";
 +      
 +      /* api callbacks */
 +      ot->exec= ed_marker_border_select_exec;
 +      ot->invoke= WM_border_select_invoke;
 +      ot->modal= WM_border_select_modal;
 +      
 +      ot->poll= ED_operator_areaactive;
 +      
 +      /* rna */
 +      RNA_def_int(ot->srna, "event_type", 0, INT_MIN, INT_MAX, "Event Type", "", INT_MIN, INT_MAX);
 +      RNA_def_int(ot->srna, "xmin", 0, INT_MIN, INT_MAX, "X Min", "", INT_MIN, INT_MAX);
 +      RNA_def_int(ot->srna, "xmax", 0, INT_MIN, INT_MAX, "X Max", "", INT_MIN, INT_MAX);
 +      RNA_def_int(ot->srna, "ymin", 0, INT_MIN, INT_MAX, "Y Min", "", INT_MIN, INT_MAX);
 +      RNA_def_int(ot->srna, "ymax", 0, INT_MIN, INT_MAX, "Y Max", "", INT_MIN, INT_MAX);
 +}
 +
 +/* *********************** (de)select all ***************** */
 +
 +static int ed_marker_select_all_exec(bContext *C, wmOperator *op)
 +{
 +      ListBase *markers= context_get_markers(C);
 +      TimeMarker *marker;
 +      int select= RNA_int_get(op->ptr, "select_type");
++
++      if(markers == NULL)
++              return OPERATOR_CANCELLED;
 +      
 +      if(RNA_boolean_get(op->ptr, "select_swap")) {
 +              for(marker= markers->first; marker; marker= marker->next) {
 +                      if(marker->flag & SELECT)
 +                              break;
 +              }
 +              if(marker)
 +                      select= 0;
 +              else
 +                      select= 1;
 +      }
 +      
 +      for(marker= markers->first; marker; marker= marker->next) {
 +              if(select)
 +                      marker->flag |= SELECT;
 +              else
 +                      marker->flag &= ~SELECT;
 +      }
 +      
 +      WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL);
 +
 +      return OPERATOR_FINISHED;
 +}
 +
 +static int ed_marker_select_all_invoke(bContext *C, wmOperator *op, wmEvent *evt)
 +{
 +      RNA_boolean_set(op->ptr, "select_swap", 1);
 +      
 +      return ed_marker_select_all_exec(C, op);
 +}
 +
 +static void MARKER_OT_select_all(wmOperatorType *ot)
 +{
 +      /* identifiers */
 +      ot->name= "(De)select all markers";
 +      ot->idname= "MARKER_OT_select_all";
 +      
 +      /* api callbacks */
 +      ot->exec= ed_marker_select_all_exec;
 +      ot->invoke= ed_marker_select_all_invoke;
 +      ot->poll= ED_operator_areaactive;
 +      
 +      /* rna */
 +      RNA_def_boolean(ot->srna, "select_swap", 0, "Select Swap", "");
 +      RNA_def_int(ot->srna, "select_type", 0, INT_MIN, INT_MAX, "Select Type", "", INT_MIN, INT_MAX);
 +}
 +
 +/* ******************************* remove marker ***************** */
 +
 +/* remove selected TimeMarkers */
 +static int ed_marker_delete_exec(bContext *C, wmOperator *op)
 +{
 +      ListBase *markers= context_get_markers(C);
 +      TimeMarker *marker, *nmarker;
 +      short changed= 0;
 +      
++      if(markers == NULL)
++              return OPERATOR_CANCELLED;
++      
 +      for(marker= markers->first; marker; marker= nmarker) {
 +              nmarker= marker->next;
 +              if(marker->flag & SELECT) {
 +                      BLI_freelinkN(markers, marker);
 +                      changed= 1;
 +              }
 +      }
 +      
 +      if(changed) {
 +              WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL);
 +      }
 +      return OPERATOR_FINISHED;
 +}
 +
 +
 +static void MARKER_OT_delete(wmOperatorType *ot)
 +{
 +      /* identifiers */
 +      ot->name= "Delete Markers";
 +      ot->idname= "MARKER_OT_delete";
 +      
 +      /* api callbacks */
 +      ot->invoke= WM_operator_confirm;
 +      ot->exec= ed_marker_delete_exec;
 +      ot->poll= ED_operator_areaactive;
 +      
 +}
 +
 +/* ************************** registration **********************************/
 +
 +/* called in screen_ops.c:ED_operatortypes_screen() */
 +void ED_marker_operatortypes(void)
 +{
 +      WM_operatortype_append(MARKER_OT_add);
 +      WM_operatortype_append(MARKER_OT_move);
 +      WM_operatortype_append(MARKER_OT_duplicate);
 +      WM_operatortype_append(MARKER_OT_mouseselect);
 +      WM_operatortype_append(MARKER_OT_mouseselect_extend);
 +      WM_operatortype_append(MARKER_OT_border_select);
 +      WM_operatortype_append(MARKER_OT_select_all);
 +      WM_operatortype_append(MARKER_OT_delete);
 +}
 +
 +/* called in screen_ops.c:ED_keymap_screen() */
 +void ED_marker_keymap(wmWindowManager *wm)
 +{
 +      ListBase *keymap= WM_keymap_listbase(wm, "Markers", 0, 0);
 +      
 +      WM_keymap_verify_item(keymap, "MARKER_OT_add", MKEY, KM_PRESS, 0, 0);
 +      WM_keymap_verify_item(keymap, "MARKER_OT_move", EVT_TWEAK_R, KM_ANY, 0, 0);
 +      WM_keymap_verify_item(keymap, "MARKER_OT_duplicate", DKEY, KM_PRESS, KM_SHIFT, 0);
 +      WM_keymap_verify_item(keymap, "MARKER_OT_mouseselect", RIGHTMOUSE, KM_PRESS, 0, 0);
 +      WM_keymap_verify_item(keymap, "MARKER_OT_mouseselect_extend", RIGHTMOUSE, KM_PRESS, KM_SHIFT, 0);
 +      WM_keymap_verify_item(keymap, "MARKER_OT_border_select", BKEY, KM_PRESS, 0, 0);
 +      WM_keymap_verify_item(keymap, "MARKER_OT_select_all", AKEY, KM_PRESS, 0, 0);
 +      WM_keymap_verify_item(keymap, "MARKER_OT_delete", XKEY, KM_PRESS, 0, 0);
 +      
 +      WM_keymap_add_item(keymap, "MARKER_OT_move", GKEY, KM_PRESS, 0, 0);
 +      
 +      /* generates event, in end to make select work */
 +      WM_keymap_verify_item(keymap, "WM_OT_tweak_gesture", RIGHTMOUSE, KM_PRESS, 0, 0);
 +      
 +}
index dab3067,0000000..8302d6e
mode 100644,000000..100644
--- /dev/null
@@@ -1,11 -1,0 +1,16 @@@
- env.BlenderLib ( 'bf_editors_space_file', sources, Split(incs), [], libtype=['core'], priority=[115] )
 +#!/usr/bin/python
 +Import ('env')
 +
 +sources = env.Glob('*.c')
 +
 +incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
 +incs += ' ../../blenloader #intern/bmfont ../../makesrna'
 +incs += ' ../../render/extern/include '
 +incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
 +
++defs = []
++
++if env['WITH_BF_OPENJPEG']:
++    defs.append('WITH_OPENJPEG')
++
++env.BlenderLib ( 'bf_editors_space_file', sources, Split(incs), defs, libtype=['core'], priority=[115] )
index e355151,0000000..384fb21
mode 100644,000000..100644
--- /dev/null
@@@ -1,1201 -1,0 +1,1208 @@@
 +/**
 + * $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) 2007 Blender Foundation.
 + * All rights reserved.
 + *
 + * The Original Code is: all of this file.
 + *
 + * Contributor(s): none yet.
 + *
 + * ***** END GPL LICENSE BLOCK *****
 + */
 +
 +
 +/* global includes */
 +
 +#include <stdlib.h>
 +#include <math.h>
 +#include <string.h>
 +
 +#ifdef HAVE_CONFIG_H
 +#include <config.h>
 +#endif
 +
 +#ifndef WIN32
 +#include <unistd.h>
 +#else
 +#include <io.h>
 +#include <direct.h>
 +#endif   
 +#include "MEM_guardedalloc.h"
 +
 +#include "BLI_blenlib.h"
 +#include "BLI_linklist.h"
 +#include "BLI_storage_types.h"
 +#include "BLI_threads.h"
 +
 +#ifdef WIN32
 +#include "BLI_winstuff.h"
 +#endif
 +
 +#include "BKE_utildefines.h"
 +#include "BKE_global.h"
 +#include "BKE_library.h"
 +#include "BKE_global.h"
 +#include "BKE_main.h"
 +#include "BLO_readfile.h"
 +
 +#include "DNA_space_types.h"
 +#include "DNA_ipo_types.h"
 +#include "DNA_ID.h"
 +#include "DNA_object_types.h"
 +#include "DNA_listBase.h"
 +#include "DNA_lamp_types.h"
 +#include "DNA_material_types.h"
 +#include "DNA_texture_types.h"
 +#include "DNA_world_types.h"
 +#include "DNA_scene_types.h"
 +#include "DNA_userdef_types.h"
 +
 +#include "ED_datafiles.h"
 +
 +#include "IMB_imbuf.h"
 +#include "IMB_imbuf_types.h"
 +#include "IMB_thumbs.h"
 +
 +#include "PIL_time.h"
 +
 +
 +#include "filelist.h"
 +
 +/* Elubie: VERY, really very ugly and evil! Remove asap!!! */
 +/* for state of file */
 +#define ACTIVE                                2
 +
 +/* max length of library group name within filesel */
 +#define GROUP_MAX 32
 +
 +static void *exec_loadimages(void *list_v);
 +
 +struct FileList;
 +
 +typedef struct FileImage {
 +      struct FileImage *next, *prev;
 +      int index;
 +      short lock;
 +      short done;
 +      struct FileList* filelist;
 +} FileImage;
 +
 +typedef struct FileList
 +{
 +      struct direntry *filelist;
 +      int *fidx;
 +
 +      int numfiles;
 +      int numfiltered;
 +      char dir[FILE_MAX];
 +      short type;
 +      short ipotype;
 +      struct BlendHandle *libfiledata;
 +      int has_func;
 +      short prv_w;
 +      short prv_h;
 +      short hide_dot;
 +      unsigned int filter;
 +      short changed;
 +      ListBase loadimages;
 +      ListBase threads;
 +} FileList;
 +
 +int BIF_groupname_to_code(char *group)
 +{
 +      char buf[32];
 +      char *lslash;
 +      
 +      BLI_strncpy(buf, group, 31);
 +      lslash= BLI_last_slash(buf);
 +      if (lslash)
 +              lslash[0]= '\0';
 +
 +      return BLO_idcode_from_name(buf);
 +}
 +
 +
 +#define SPECIAL_IMG_SIZE 48
 +#define SPECIAL_IMG_ROWS 4
 +#define SPECIAL_IMG_COLS 4
 +
 +#define SPECIAL_IMG_FOLDER 0
 +#define SPECIAL_IMG_PARENT 1
 +#define SPECIAL_IMG_REFRESH 2
 +#define SPECIAL_IMG_BLENDFILE 3
 +#define SPECIAL_IMG_SOUNDFILE 4
 +#define SPECIAL_IMG_MOVIEFILE 5
 +#define SPECIAL_IMG_PYTHONFILE 6
 +#define SPECIAL_IMG_TEXTFILE 7
 +#define SPECIAL_IMG_FONTFILE 8
 +#define SPECIAL_IMG_UNKNOWNFILE 9
 +#define SPECIAL_IMG_MAX SPECIAL_IMG_UNKNOWNFILE + 1
 +
 +static ImBuf* gSpecialFileImages[SPECIAL_IMG_MAX];
 +
 +
 +/* ******************* SORT ******************* */
 +
 +static int compare_name(const void *a1, const void *a2)
 +{
 +      const struct direntry *entry1=a1, *entry2=a2;
 +
 +      /* type is is equal to stat.st_mode */
 +
 +      if (S_ISDIR(entry1->type)){
 +              if (S_ISDIR(entry2->type)==0) return (-1);
 +      } else{
 +              if (S_ISDIR(entry2->type)) return (1);
 +      }
 +      if (S_ISREG(entry1->type)){
 +              if (S_ISREG(entry2->type)==0) return (-1);
 +      } else{
 +              if (S_ISREG(entry2->type)) return (1);
 +      }
 +      if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1);
 +      if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1);
 +      
 +      /* make sure "." and ".." are always first */
 +      if( strcmp(entry1->relname, ".")==0 ) return (-1);
 +      if( strcmp(entry2->relname, ".")==0 ) return (1);
 +      if( strcmp(entry1->relname, "..")==0 ) return (-1);
 +      
 +      return (BLI_strcasecmp(entry1->relname,entry2->relname));
 +}
 +
 +static int compare_date(const void *a1, const void *a2)       
 +{
 +      const struct direntry *entry1=a1, *entry2=a2;
 +      
 +      /* type is equal to stat.st_mode */
 +
 +      if (S_ISDIR(entry1->type)){
 +              if (S_ISDIR(entry2->type)==0) return (-1);
 +      } else{
 +              if (S_ISDIR(entry2->type)) return (1);
 +      }
 +      if (S_ISREG(entry1->type)){
 +              if (S_ISREG(entry2->type)==0) return (-1);
 +      } else{
 +              if (S_ISREG(entry2->type)) return (1);
 +      }
 +      if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1);
 +      if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1);
 +
 +      /* make sure "." and ".." are always first */
 +      if( strcmp(entry1->relname, ".")==0 ) return (-1);
 +      if( strcmp(entry2->relname, ".")==0 ) return (1);
 +      if( strcmp(entry1->relname, "..")==0 ) return (-1);
 +      
 +      if ( entry1->s.st_mtime < entry2->s.st_mtime) return 1;
 +      if ( entry1->s.st_mtime > entry2->s.st_mtime) return -1;
 +      
 +      else return BLI_strcasecmp(entry1->relname,entry2->relname);
 +}
 +
 +static int compare_size(const void *a1, const void *a2)       
 +{
 +      const struct direntry *entry1=a1, *entry2=a2;
 +
 +      /* type is equal to stat.st_mode */
 +
 +      if (S_ISDIR(entry1->type)){
 +              if (S_ISDIR(entry2->type)==0) return (-1);
 +      } else{
 +              if (S_ISDIR(entry2->type)) return (1);
 +      }
 +      if (S_ISREG(entry1->type)){
 +              if (S_ISREG(entry2->type)==0) return (-1);
 +      } else{
 +              if (S_ISREG(entry2->type)) return (1);
 +      }
 +      if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1);
 +      if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1);
 +
 +      /* make sure "." and ".." are always first */
 +      if( strcmp(entry1->relname, ".")==0 ) return (-1);
 +      if( strcmp(entry2->relname, ".")==0 ) return (1);
 +      if( strcmp(entry1->relname, "..")==0 ) return (-1);
 +      
 +      if ( entry1->s.st_size < entry2->s.st_size) return 1;
 +      if ( entry1->s.st_size > entry2->s.st_size) return -1;
 +      else return BLI_strcasecmp(entry1->relname,entry2->relname);
 +}
 +
 +static int compare_extension(const void *a1, const void *a2) {
 +      const struct direntry *entry1=a1, *entry2=a2;
 +      char *sufix1, *sufix2;
 +      char *nil="";
 +
 +      if (!(sufix1= strstr (entry1->relname, ".blend.gz"))) 
 +              sufix1= strrchr (entry1->relname, '.');
 +      if (!(sufix2= strstr (entry2->relname, ".blend.gz")))
 +              sufix2= strrchr (entry2->relname, '.');
 +      if (!sufix1) sufix1= nil;
 +      if (!sufix2) sufix2= nil;
 +
 +      /* type is is equal to stat.st_mode */
 +
 +      if (S_ISDIR(entry1->type)){
 +              if (S_ISDIR(entry2->type)==0) return (-1);
 +      } else{
 +              if (S_ISDIR(entry2->type)) return (1);
 +      }
 +      if (S_ISREG(entry1->type)){
 +              if (S_ISREG(entry2->type)==0) return (-1);
 +      } else{
 +              if (S_ISREG(entry2->type)) return (1);
 +      }
 +      if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1);
 +      if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1);
 +      
 +      /* make sure "." and ".." are always first */
 +      if( strcmp(entry1->relname, ".")==0 ) return (-1);
 +      if( strcmp(entry2->relname, ".")==0 ) return (1);
 +      if( strcmp(entry1->relname, "..")==0 ) return (-1);
 +      if( strcmp(entry2->relname, "..")==0 ) return (-1);
 +      
 +      return (BLI_strcasecmp(sufix1, sufix2));
 +}
 +
 +void filelist_filter(FileList* filelist)
 +{
 +      char dir[FILE_MAX], group[GROUP_MAX];
 +      int num_filtered = 0;
 +      int i, j;
 +      
 +      if (!filelist->filelist)
 +              return;
 +      
 +      if ( ( (filelist->type == FILE_LOADLIB) &&  filelist_islibrary(filelist, dir, group)) 
 +              || (filelist->type == FILE_MAIN) ) {
 +              filelist->filter = 0;
 +      }
 +
 +      if (!filelist->filter) {
 +              if (filelist->fidx) {
 +                      MEM_freeN(filelist->fidx);
 +                      filelist->fidx = NULL;
 +              }
 +              filelist->fidx = (int *)MEM_callocN(filelist->numfiles*sizeof(int), "filteridx");
 +              for (i = 0; i < filelist->numfiles; ++i) {
 +                      filelist->fidx[i] = i;
 +              }
 +              filelist->numfiltered = filelist->numfiles;
 +              return;
 +      }
 +
 +      // How many files are left after filter ?
 +      for (i = 0; i < filelist->numfiles; ++i) {
 +              if (filelist->filelist[i].flags & filelist->filter) {
 +                      num_filtered++;
 +              } 
 +              else if (filelist->filelist[i].type & S_IFDIR) {
 +                      if (filelist->filter & FOLDERFILE) {
 +                              num_filtered++;
 +                      }
 +              }               
 +      }
 +      
 +      if (filelist->fidx) {
 +                      MEM_freeN(filelist->fidx);
 +                      filelist->fidx = NULL;
 +      }
 +      filelist->fidx = (int *)MEM_callocN(num_filtered*sizeof(int), "filteridx");
 +      filelist->numfiltered = num_filtered;
 +
 +      for (i = 0, j=0; i < filelist->numfiles; ++i) {
 +              if (filelist->filelist[i].flags & filelist->filter) {
 +                      filelist->fidx[j++] = i;
 +              }
 +              else if (filelist->filelist[i].type & S_IFDIR) {
 +                      if (filelist->filter & FOLDERFILE) {
 +                              filelist->fidx[j++] = i;
 +                      }
 +              }  
 +      }
 +}
 +
 +void filelist_init_icons()
 +{
 +      short x, y, k;
 +      ImBuf *bbuf;
 +      ImBuf *ibuf;
 +      bbuf = IMB_ibImageFromMemory((int *)datatoc_prvicons, datatoc_prvicons_size, IB_rect);
 +      if (bbuf) {
 +              for (y=0; y<SPECIAL_IMG_ROWS; y++) {
 +                      for (x=0; x<SPECIAL_IMG_COLS; x++) {
 +                              int tile = SPECIAL_IMG_COLS*y + x; 
 +                              if (tile < SPECIAL_IMG_MAX) {
 +                                      ibuf = IMB_allocImBuf(SPECIAL_IMG_SIZE, SPECIAL_IMG_SIZE, 32, IB_rect, 0);
 +                                      for (k=0; k<SPECIAL_IMG_SIZE; k++) {
 +                                              memcpy(&ibuf->rect[k*SPECIAL_IMG_SIZE], &bbuf->rect[(k+y*SPECIAL_IMG_SIZE)*SPECIAL_IMG_SIZE*SPECIAL_IMG_COLS+x*SPECIAL_IMG_SIZE], SPECIAL_IMG_SIZE*sizeof(int));
 +                                      }
 +                                      gSpecialFileImages[tile] = ibuf;
 +                              }
 +                      }
 +              }
 +              IMB_freeImBuf(bbuf);
 +      }
 +}
 +
 +void filelist_free_icons()
 +{
 +      int i;
 +      for (i=0; i < SPECIAL_IMG_MAX; ++i) {
 +              IMB_freeImBuf(gSpecialFileImages[i]);
 +              gSpecialFileImages[i] = NULL;
 +      }
 +}
 +
 +struct FileList*      filelist_new()
 +{
 +      FileList* p = MEM_callocN( sizeof(FileList), "filelist" );
 +      p->filelist = 0;
 +      p->numfiles = 0;
 +      p->dir[0] = '\0';
 +      p->libfiledata = 0;
 +      p->type = 0;
 +      p->has_func = 0;
 +      p->filter = 0;
 +      return p;
 +}
 +
 +struct FileList*      filelist_copy(struct FileList* filelist)
 +{
 +      FileList* p = filelist_new();
 +      BLI_strncpy(p->dir, filelist->dir, FILE_MAX);
 +      p->filelist = NULL;
 +      p->fidx = NULL;
 +      p->type = filelist->type;
 +      p->ipotype = filelist->ipotype;
 +      p->has_func = filelist->has_func;
 +
 +      return p;
 +}
 +
 +void filelist_free(struct FileList* filelist)
 +{
 +      int i;
 +
 +      if (!filelist) {
 +              printf("Attemtping to delete empty filelist.\n");
 +              return;
 +      }
 +
 +      BLI_end_threads(&filelist->threads);
 +      BLI_freelistN(&filelist->loadimages);
 +      
 +      if (filelist->fidx) {
 +              MEM_freeN(filelist->fidx);
 +              filelist->fidx = NULL;
 +      }
 +
 +      for (i = 0; i < filelist->numfiles; ++i) {
 +              if (filelist->filelist[i].image) {                      
 +                      IMB_freeImBuf(filelist->filelist[i].image);
 +              }
 +              filelist->filelist[i].image = 0;
 +              if (filelist->filelist[i].relname)
 +                      MEM_freeN(filelist->filelist[i].relname);
 +              filelist->filelist[i].relname = 0;
 +              if (filelist->filelist[i].string)
 +                      MEM_freeN(filelist->filelist[i].string);
 +              filelist->filelist[i].string = 0;
 +      }
 +      
 +      filelist->numfiles = 0;
 +      free(filelist->filelist);
 +      filelist->filelist = 0; 
 +      filelist->filter = 0;
 +      filelist->numfiltered =0;
 +}
 +
 +void filelist_freelib(struct FileList* filelist)
 +{
 +      if(filelist->libfiledata)       
 +              BLO_blendhandle_close(filelist->libfiledata);
 +      filelist->libfiledata= 0;
 +}
 +
 +struct BlendHandle *filelist_lib(struct FileList* filelist)
 +{
 +      return filelist->libfiledata;
 +}
 +
 +int   filelist_numfiles(struct FileList* filelist)
 +{
 +      return filelist->numfiltered;
 +}
 +
 +const char * filelist_dir(struct FileList* filelist)
 +{
 +      return filelist->dir;
 +}
 +
 +void filelist_setdir(struct FileList* filelist, const char *dir)
 +{
 +      BLI_strncpy(filelist->dir, dir, FILE_MAX);
 +}
 +
 +void filelist_imgsize(struct FileList* filelist, short w, short h)
 +{
 +      filelist->prv_w = w;
 +      filelist->prv_h = h;
 +}
 +
 +
 +static void *exec_loadimages(void *list_v)
 +{
 +      FileImage* img = (FileImage*)list_v;
 +      struct FileList *filelist = img->filelist;
 +
 +      ImBuf *imb = NULL;
 +      int fidx = img->index;
 +      
 +      if ( filelist->filelist[fidx].flags & IMAGEFILE ) {                             
 +              imb = IMB_thumb_manage(filelist->dir, filelist->filelist[fidx].relname, THB_NORMAL, THB_SOURCE_IMAGE);
 +      } else if ( filelist->filelist[fidx].flags & MOVIEFILE ) {                              
 +              imb = IMB_thumb_manage(filelist->dir, filelist->filelist[fidx].relname, THB_NORMAL, THB_SOURCE_MOVIE);
 +              if (!imb) {
 +                      /* remember that file can't be loaded via IMB_open_anim */
 +                      filelist->filelist[fidx].flags &= ~MOVIEFILE;
 +                      filelist->filelist[fidx].flags |= MOVIEFILE_ICON;
 +              }
 +      }
 +      if (imb) {
 +              IMB_freeImBuf(imb);
 +      }
 +      img->done=1;
 +      return 0;
 +}
 +
 +short filelist_changed(struct FileList* filelist)
 +{
 +      return filelist->changed;
 +}
 +
 +void filelist_loadimage_timer(struct FileList* filelist)
 +{
 +      FileImage *limg = filelist->loadimages.first;
 +      short refresh=0;
 +
 +      // as long as threads are available and there is work to do
 +      while (limg) {
 +              if (BLI_available_threads(&filelist->threads)>0) {
 +                      if (!limg->lock) {
 +                              limg->lock=1;
 +                              BLI_insert_thread(&filelist->threads, limg);
 +                      }
 +              }
 +              if (limg->done) {
 +                      FileImage *oimg = limg;
 +                      BLI_remlink(&filelist->loadimages, oimg);
 +                      BLI_remove_thread(&filelist->threads, oimg);
 +                      limg = oimg->next;
 +                      MEM_freeN(oimg);
 +                      refresh = 1;
 +              } else {
 +                      limg= limg->next;
 +              }
 +      }
 +      filelist->changed=refresh;
 +}
 +
 +void filelist_loadimage(struct FileList* filelist, int index)
 +{
 +      ImBuf *imb = NULL;
 +      int imgwidth = filelist->prv_w;
 +      int imgheight = filelist->prv_h;
 +      short ex, ey, dx, dy;
 +      float scaledx, scaledy;
 +      int fidx = 0;
 +      
 +      if ( (index < 0) || (index >= filelist->numfiltered) ) {
 +              return;
 +      }
 +      fidx = filelist->fidx[index];
 +
 +      if (!filelist->filelist[fidx].image)
 +      {
 +              if (filelist->type != FILE_MAIN)
 +              {
 +                      if ( (filelist->filelist[fidx].flags & IMAGEFILE) || (filelist->filelist[fidx].flags & MOVIEFILE) ) {                           
 +                              imb = IMB_thumb_read(filelist->dir, filelist->filelist[fidx].relname, THB_NORMAL);
 +                      } 
 +                      if (imb) {
 +                              if (imb->x > imb->y) {
 +                                      scaledx = (float)imgwidth;
 +                                      scaledy =  ( (float)imb->y/(float)imb->x )*imgwidth;
 +                              }
 +                              else {
 +                                      scaledy = (float)imgheight;
 +                                      scaledx =  ( (float)imb->x/(float)imb->y )*imgheight;
 +                              }
 +                              ex = (short)scaledx;
 +                              ey = (short)scaledy;
 +                              
 +                              dx = imgwidth - ex;
 +                              dy = imgheight - ey;
 +                              
 +                              IMB_scaleImBuf(imb, ex, ey);
 +                              filelist->filelist[fidx].image = imb;
 +                      } else {
 +                              /* prevent loading image twice */
 +                              FileImage* limg = filelist->loadimages.first;
 +                              short found= 0;
 +                              while(limg) {
 +                                      if (limg->index == fidx) {
 +                                              found= 1;
 +                                              break;
 +                                      }
 +                                      limg= limg->next;
 +                              }
 +                              if (!found) {
 +                                      FileImage* limg = MEM_callocN(sizeof(struct FileImage), "loadimage");
 +                                      limg->index= fidx;
 +                                      limg->lock= 0;
 +                                      limg->filelist= filelist;
 +                                      BLI_addtail(&filelist->loadimages, limg);
 +                              }
 +                      }               
 +              }
 +      }
 +}
 +
 +struct ImBuf * filelist_getimage(struct FileList* filelist, int index)
 +{
 +      ImBuf* ibuf = NULL;
 +      int fidx = 0;   
 +      if ( (index < 0) || (index >= filelist->numfiltered) ) {
 +              return NULL;
 +      }
 +      fidx = filelist->fidx[index];
 +      ibuf = filelist->filelist[fidx].image;
 +
 +      if (ibuf == NULL) {
 +              struct direntry *file = &filelist->filelist[fidx];
 +              if (file->type & S_IFDIR) {
 +                      if ( strcmp(filelist->filelist[fidx].relname, "..") == 0) {
 +                              ibuf = gSpecialFileImages[SPECIAL_IMG_PARENT];
 +                      } else if  ( strcmp(filelist->filelist[fidx].relname, ".") == 0) {
 +                              ibuf = gSpecialFileImages[SPECIAL_IMG_REFRESH];
 +                      } else {
 +                              ibuf = gSpecialFileImages[SPECIAL_IMG_FOLDER];
 +                      }
 +              } else {
 +                      ibuf = gSpecialFileImages[SPECIAL_IMG_UNKNOWNFILE];
 +              }
 +
 +              if (file->flags & BLENDERFILE) {
 +                      ibuf = gSpecialFileImages[SPECIAL_IMG_BLENDFILE];
 +              } else if ( (file->flags & MOVIEFILE) || (file->flags & MOVIEFILE_ICON) ) {
 +                      ibuf = gSpecialFileImages[SPECIAL_IMG_MOVIEFILE];
 +              } else if (file->flags & SOUNDFILE) {
 +                      ibuf = gSpecialFileImages[SPECIAL_IMG_SOUNDFILE];
 +              } else if (file->flags & PYSCRIPTFILE) {
 +                      ibuf = gSpecialFileImages[SPECIAL_IMG_PYTHONFILE];
 +              } else if (file->flags & FTFONTFILE) {
 +                      ibuf = gSpecialFileImages[SPECIAL_IMG_FONTFILE];
 +              } else if (file->flags & TEXTFILE) {
 +                      ibuf = gSpecialFileImages[SPECIAL_IMG_TEXTFILE];
 +              } 
 +      }
 +      return ibuf;
 +}
 +
 +struct direntry * filelist_file(struct FileList* filelist, int index)
 +{
 +      int fidx = 0;
 +      
 +      if ( (index < 0) || (index >= filelist->numfiltered) ) {
 +              return NULL;
 +      }
 +      fidx = filelist->fidx[index];
 +
 +      return &filelist->filelist[fidx];
 +}
 +
 +int filelist_find(struct FileList* filelist, char *file)
 +{
 +      int index = -1;
 +      int i;
 +      int fidx = -1;
 +      
 +      if (!filelist->fidx) 
 +              return fidx;
 +
 +      
 +      for (i = 0; i < filelist->numfiles; ++i) {
 +              if ( strcmp(filelist->filelist[i].relname, file) == 0) {
 +                      index = i;
 +                      break;
 +              }
 +      }
 +
 +      for (i = 0; i < filelist->numfiltered; ++i) {
 +              if (filelist->fidx[i] == index) {
 +                      fidx = i;
 +                      break;
 +              }
 +      }
 +      return fidx;
 +}
 +
 +void filelist_hidedot(struct FileList* filelist, short hide)
 +{
 +      filelist->hide_dot = hide;
 +}
 +
 +void filelist_setfilter(struct FileList* filelist, unsigned int filter)
 +{
 +      filelist->filter = filter;
 +}
 +
 +void filelist_readdir(struct FileList* filelist)
 +{
 +      char wdir[FILE_MAX];
 +      int finished = 0;
 +
 +      if (!filelist) return;
 +      filelist->fidx = 0;
 +      filelist->filelist = 0;
 +
 +      if(filelist->type==FILE_MAIN) {
 +              filelist_from_main(filelist);
 +              finished = 1;
 +      } else if(filelist->type==FILE_LOADLIB) {
 +              BLI_cleanup_dir(G.sce, filelist->dir);
 +              filelist_from_library(filelist);
 +              if(filelist->libfiledata) {
 +                      finished = 1;
 +              }
 +      }
 +
 +      if (!finished) {
 +              BLI_getwdN(wdir);        
 +              
 +              BLI_cleanup_dir(G.sce, filelist->dir);
 +              BLI_hide_dot_files(filelist->hide_dot);
 +              filelist->numfiles = BLI_getdir(filelist->dir, &(filelist->filelist));
 +
 +              chdir(wdir);
 +              filelist_setfiletypes(filelist, G.have_quicktime);
 +              filelist_filter(filelist);
 +              
 +              if (!filelist->threads.first) {
 +                      BLI_init_threads(&filelist->threads, exec_loadimages, 2);
 +              }
 +      }
 +}
 +
 +int filelist_empty(struct FileList* filelist)
 +{     
 +      return filelist->filelist == 0;
 +}
 +
 +void filelist_parent(struct FileList* filelist)
 +{
 +      BLI_parent_dir(filelist->dir);
 +      BLI_make_exist(filelist->dir);
 +      filelist_readdir(filelist);
 +}
 +
 +void filelist_setfiletypes(struct FileList* filelist, short has_quicktime)
 +{
 +      struct direntry *file;
 +      int num;
 +
 +      file= filelist->filelist;
 +
 +      for(num=0; num<filelist->numfiles; num++, file++) {
 +              file->flags= 0;
 +              file->type= file->s.st_mode;    /* restore the mess below */ 
 +
 +                      /* Don't check extensions for directories */ 
 +              if (file->type & S_IFDIR)
 +                      continue;
 +                              
 +              
 +              
 +              if(BLO_has_bfile_extension(file->relname)) {
 +                      file->flags |= BLENDERFILE;
 +                      if(filelist->type==FILE_LOADLIB) {              
 +                              char name[FILE_MAXDIR+FILE_MAXFILE];
 +                              BLI_strncpy(name, filelist->dir, sizeof(name));
 +                              strcat(name, file-