svn merge -r 12937:13095 https://svn.blender.org/svnroot/bf-blender/trunk/blender
authorDaniel Genrich <daniel.genrich@gmx.net>
Wed, 2 Jan 2008 14:36:46 +0000 (14:36 +0000)
committerDaniel Genrich <daniel.genrich@gmx.net>
Wed, 2 Jan 2008 14:36:46 +0000 (14:36 +0000)
178 files changed:
SConstruct
config/win32-mingw-config.py
extern/verse/Makefile
intern/guardedalloc/intern/mallocn.c
projectfiles_vc7/blender/blenkernel/BKE_blenkernel.vcproj
projectfiles_vc7/blender/blenlib/BLI_blenlib.vcproj
projectfiles_vc7/blender/src/BL_src.vcproj
release/datafiles/blenderbuttons
release/scripts/image_find_paths.py [deleted file]
release/scripts/import_obj.py
source/blender/avi/intern/avi.c
source/blender/blenkernel/BKE_bad_level_calls.h
source/blender/blenkernel/BKE_image.h
source/blender/blenkernel/BKE_ipo.h
source/blender/blenkernel/BKE_mesh.h
source/blender/blenkernel/BKE_multires.h [new file with mode: 0644]
source/blender/blenkernel/BKE_node.h
source/blender/blenkernel/BKE_particle.h
source/blender/blenkernel/BKE_scene.h
source/blender/blenkernel/BKE_sculpt.h [new file with mode: 0644]
source/blender/blenkernel/BKE_utildefines.h
source/blender/blenkernel/bad_level_call_stubs/stubs.c
source/blender/blenkernel/intern/DerivedMesh.c
source/blender/blenkernel/intern/action.c
source/blender/blenkernel/intern/anim.c
source/blender/blenkernel/intern/colortools.c
source/blender/blenkernel/intern/curve.c
source/blender/blenkernel/intern/image.c
source/blender/blenkernel/intern/ipo.c
source/blender/blenkernel/intern/mesh.c
source/blender/blenkernel/intern/multires-firstlevel.c [moved from source/blender/src/multires-firstlevel.c with 99% similarity]
source/blender/blenkernel/intern/multires.c [new file with mode: 0644]
source/blender/blenkernel/intern/node.c
source/blender/blenkernel/intern/object.c
source/blender/blenkernel/intern/particle.c
source/blender/blenkernel/intern/particle_system.c
source/blender/blenkernel/intern/scene.c
source/blender/blenkernel/intern/softbody.c
source/blender/blenlib/BLI_blenlib.h
source/blender/blenlib/BLI_boxpack2d.h
source/blender/blenlib/BLI_bpath.h [new file with mode: 0644]
source/blender/blenlib/intern/BLI_ghash.c
source/blender/blenlib/intern/bpath.c [new file with mode: 0644]
source/blender/blenlib/intern/util.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/imbuf/intern/anim.c
source/blender/imbuf/intern/dds/BlockDXT.cpp
source/blender/imbuf/intern/dds/BlockDXT.h
source/blender/imbuf/intern/dds/ColorBlock.cpp
source/blender/imbuf/intern/dds/ColorBlock.h
source/blender/imbuf/intern/dds/Common.h
source/blender/imbuf/intern/dds/DirectDrawSurface.cpp
source/blender/imbuf/intern/dds/DirectDrawSurface.h
source/blender/imbuf/intern/dds/Image.cpp
source/blender/imbuf/intern/dds/Image.h
source/blender/imbuf/intern/dds/PixelFormat.h [new file with mode: 0644]
source/blender/imbuf/intern/filter.c
source/blender/imbuf/intern/jpeg.c
source/blender/imbuf/intern/rotate.c
source/blender/imbuf/intern/thumbs.c
source/blender/imbuf/intern/tiff.c
source/blender/include/BDR_editobject.h
source/blender/include/BDR_sculptmode.h
source/blender/include/BIF_butspace.h
source/blender/include/BIF_drawtext.h
source/blender/include/BIF_editaction.h
source/blender/include/BIF_editparticle.h
source/blender/include/BIF_editseq.h
source/blender/include/BIF_poselib.h [new file with mode: 0644]
source/blender/include/BIF_resources.h
source/blender/include/BIF_space.h
source/blender/include/BSE_node.h
source/blender/include/BSE_seqeffects.h
source/blender/include/BSE_sequence.h
source/blender/include/BSE_time.h
source/blender/include/butspace.h
source/blender/include/multires.h
source/blender/include/transform.h
source/blender/makesdna/DNA_action_types.h
source/blender/makesdna/DNA_material_types.h
source/blender/makesdna/DNA_node_types.h
source/blender/makesdna/DNA_object_types.h
source/blender/makesdna/DNA_particle_types.h
source/blender/makesdna/DNA_scene_types.h
source/blender/makesdna/DNA_sequence_types.h
source/blender/makesdna/DNA_texture_types.h
source/blender/nodes/CMP_node.h
source/blender/nodes/intern/CMP_nodes/CMP_bilateralblur.c [new file with mode: 0644]
source/blender/nodes/intern/CMP_nodes/CMP_directionalblur.c [new file with mode: 0644]
source/blender/python/api2_2x/Blender.c
source/blender/python/api2_2x/Image.c
source/blender/python/api2_2x/Mesh.c
source/blender/python/api2_2x/Object.c
source/blender/python/api2_2x/Scene.c
source/blender/python/api2_2x/Texture.c
source/blender/python/api2_2x/bpy_data.c
source/blender/python/api2_2x/doc/Blender.py
source/blender/python/api2_2x/doc/Object.py
source/blender/render/extern/include/RE_pipeline.h
source/blender/render/intern/include/render_types.h
source/blender/render/intern/include/renderdatabase.h
source/blender/render/intern/include/strand.h
source/blender/render/intern/source/convertblender.c
source/blender/render/intern/source/imagetexture.c
source/blender/render/intern/source/pipeline.c
source/blender/render/intern/source/rendercore.c
source/blender/render/intern/source/renderdatabase.c
source/blender/render/intern/source/shadeoutput.c
source/blender/render/intern/source/strand.c
source/blender/render/intern/source/texture.c
source/blender/src/blenderbuttons.c
source/blender/src/butspace.c
source/blender/src/buttons_editing.c
source/blender/src/buttons_object.c
source/blender/src/buttons_scene.c
source/blender/src/buttons_shading.c
source/blender/src/drawaction.c
source/blender/src/drawimage.c
source/blender/src/drawipo.c
source/blender/src/drawmesh.c
source/blender/src/drawnla.c
source/blender/src/drawnode.c
source/blender/src/drawseq.c
source/blender/src/drawsound.c
source/blender/src/drawtext.c
source/blender/src/drawtime.c
source/blender/src/drawview.c
source/blender/src/editaction.c
source/blender/src/editarmature.c
source/blender/src/editface.c
source/blender/src/editfont.c
source/blender/src/editipo.c
source/blender/src/editmball.c
source/blender/src/editmesh.c
source/blender/src/editnla.c
source/blender/src/editnode.c
source/blender/src/editobject.c
source/blender/src/editparticle.c
source/blender/src/editscreen.c
source/blender/src/editseq.c
source/blender/src/editsima.c
source/blender/src/editsound.c
source/blender/src/edittime.c
source/blender/src/filesel.c
source/blender/src/header_action.c
source/blender/src/header_buttonswin.c
source/blender/src/header_info.c
source/blender/src/header_node.c
source/blender/src/header_seq.c
source/blender/src/header_text.c
source/blender/src/header_time.c
source/blender/src/header_view3d.c
source/blender/src/headerbuttons.c
source/blender/src/meshtools.c
source/blender/src/multires.c
source/blender/src/outliner.c
source/blender/src/playanim.c
source/blender/src/poselib.c [new file with mode: 0644]
source/blender/src/renderwin.c
source/blender/src/retopo.c
source/blender/src/sculptmode-stroke.c
source/blender/src/sculptmode.c
source/blender/src/seqaudio.c
source/blender/src/seqeffects.c
source/blender/src/sequence.c
source/blender/src/space.c
source/blender/src/toets.c
source/blender/src/toolbox.c
source/blender/src/transform.c
source/blender/src/transform_conversions.c
source/blender/src/transform_generics.c
source/blender/src/verse_object.c
source/blender/src/view.c
source/blender/src/vpaint.c
source/creator/creator.c
source/nan_compile.mk
tools/btools.py

index 7fad247ec07cde6300ac05a072ea224a2177d323..adecfcb5dcf15056e285a3c8ac6c448de519359c 100644 (file)
@@ -170,6 +170,9 @@ else:
 opts = btools.read_opts(optfiles, B.arguments)
 opts.Update(env)
 
+if not env['BF_FANCY']:
+    B.bc.disable()
+
 # disable elbeem (fluidsim) compilation?
 if env['BF_NO_ELBEEM'] == 1:
     env['CPPFLAGS'].append('-DDISABLE_ELBEEM')
index 54d8e0c6ffd1ec18c562aaf35f1f909d4d15c099..8c8c12db46fe3648997bacf40979475d4e9e9fc6 100644 (file)
@@ -18,7 +18,7 @@ BF_OPENAL_LIB = 'openal_static'
 BF_OPENAL_LIBPATH = '${BF_OPENAL}/lib'
 
 WITH_BF_FFMPEG = 'false'
-BF_FFMPEG_LIB = 'avformat avutil avcodec'
+BF_FFMPEG_LIB = 'avformat swscale avcodec avutil xvidcore x264'
 BF_FFMPEG_LIBPATH = LIBDIR + '/gcc/ffmpeg/lib'
 BF_FFMPEG_INC =  LIBDIR + '/gcc/ffmpeg/include'
 
index 2e88ee2223f55a1dc659a41b00fec9459e1cab26..bd8bba331956ab0fb77ac19c0f095f99c76102d4 100644 (file)
@@ -54,5 +54,5 @@ install: all debug
 ifeq ($(OS),darwin)
        ranlib $(NAN_VERSE)/lib/libverse.a
 endif
-       $(CCC) $(LDFLAGS) -o $(DIR)/verse$(EXT) $(DIR)/libverse.a $(LIBS) $(SLIBS) $(LLIBS) $(DADD) $(LOPTS)
+       $(CCC) $(CCFLAGS) $(LDFLAGS) -o $(DIR)/verse$(EXT) $(DIR)/libverse.a $(LIBS) $(SLIBS) $(LLIBS) $(DADD) $(LOPTS)
        @$(CP) $(DIR)/verse$(EXT) $(OCGDIR)/bin
index 51c2a2427b5f9f56f8c1cd8366eb467b319dfca2..44909bbea548470c768f0c5fd95c612af7cca843 100644 (file)
@@ -333,6 +333,7 @@ void *MEM_mapallocN(unsigned int len, const char *str)
 }
 
 
+/* Prints in python syntax for easy */
 void MEM_printmemlist()
 {
        MemHead *membl;
@@ -341,13 +342,33 @@ void MEM_printmemlist()
 
        membl = membase->first;
        if (membl) membl = MEMNEXT(membl);
+       
+       print_error("# membase_debug.py\n");
+       print_error("membase = [\\\n");
        while(membl) {
-               print_error("%s len: %d %p\n",membl->name,membl->len, membl+1);
+               fprintf(stderr, "{'len':%i, 'name':'''%s''', 'pointer':'%p'},\\\n", membl->len, membl->name, membl+1);
                if(membl->next)
                        membl= MEMNEXT(membl->next);
                else break;
        }
-
+       fprintf(stderr, "]\n\n");
+       fprintf(stderr,
+"mb_userinfo = {}\n"
+"totmem = 0\n"
+"for mb_item in membase:\n"
+"\tmb_item_user_size = mb_userinfo.setdefault(mb_item['name'], [0,0])\n"
+"\tmb_item_user_size[0] += 1 # Add a user\n"
+"\tmb_item_user_size[1] += mb_item['len'] # Increment the size\n"
+"\ttotmem += mb_item['len']\n"
+"print '(membase) items:', len(membase), '| unique-names:', len(mb_userinfo), '| total-mem:', totmem\n"
+"mb_userinfo_sort = mb_userinfo.items()\n"
+"for sort_name, sort_func in (('size', lambda a: -a[1][1]), ('users', lambda a: -a[1][0]), ('name', lambda a: a[0])):\n"
+"\tprint '\\nSorting by:', sort_name\n"
+"\tmb_userinfo_sort.sort(key = sort_func)\n"
+"\tfor item in mb_userinfo_sort:\n"
+"\t\tprint 'name:%%s, users:%%i, len:%%i' %% (item[0], item[1][0], item[1][1])\n"
+       );
+       
        mem_unlock_thread();
 }
 
index 15614f52fdf951910af3e852065cddedb3419708..7b7d1ac06084cfd3cb74975eed91be365710a767 100644 (file)
                        <File
                                RelativePath="..\..\..\source\blender\blenkernel\intern\modifier.c">
                        </File>
+                       <File
+                               RelativePath="..\..\..\source\blender\blenkernel\intern\multires-firstlevel.c">
+                       </File>
+                       <File
+                               RelativePath="..\..\..\source\blender\blenkernel\intern\multires.c">
+                       </File>
                        <File
                                RelativePath="..\..\..\source\blender\blenkernel\intern\nla.c">
                        </File>
                        <File
                                RelativePath="..\..\..\source\blender\blenkernel\BKE_modifier.h">
                        </File>
+                       <File
+                               RelativePath="..\..\..\source\blender\blenkernel\BKE_multires.h">
+                       </File>
                        <File
                                RelativePath="..\..\..\source\blender\blenkernel\BKE_nla.h">
                        </File>
index b42642c774f938cdb89d70e7663021b059033a48..8a2b8b95e385e4b4fafa2d3a9d63ec0bf7fee01f 100644 (file)
                        <File
                                RelativePath="..\..\..\source\blender\blenlib\intern\boxpack2d.c">
                        </File>
+                       <File
+                               RelativePath="..\..\..\source\blender\blenlib\intern\bpath.c">
+                       </File>
                        <File
                                RelativePath="..\..\..\source\blender\blenlib\intern\dynlib.c">
                        </File>
                        <File
                                RelativePath="..\..\..\source\blender\blenlib\BLI_boxpack2d.h">
                        </File>
+                       <File
+                               RelativePath="..\..\..\source\blender\blenlib\BLI_bpath.h">
+                       </File>
                        <File
                                RelativePath="..\..\..\source\blender\blenlib\intern\BLI_callbacks.h">
                        </File>
index 9c03b21f1a82c689a6fbd595368fe9621f1ee821..9d5e40b96b7ef2f138ed37fd210032f28b45e7d1 100644 (file)
                        <File
                                RelativePath="..\..\..\source\blender\src\meshtools.c">
                        </File>
-                       <File
-                               RelativePath="..\..\..\source\blender\src\multires-firstlevel.c">
-                       </File>
                        <File
                                RelativePath="..\..\..\source\blender\src\multires.c">
                        </File>
                        <File
                                RelativePath="..\..\..\source\blender\blenpluginapi\intern\pluginapi.c">
                        </File>
+                       <File
+                               RelativePath="..\..\..\source\blender\src\poselib.c">
+                       </File>
                        <File
                                RelativePath="..\..\..\source\blender\src\poseobject.c">
                        </File>
index d447b3b4f2c61f712cee19c4447627b8f29c1054..3f897f7d1c46a3b8c880188f87fa5e01967d9a23 100644 (file)
Binary files a/release/datafiles/blenderbuttons and b/release/datafiles/blenderbuttons differ
diff --git a/release/scripts/image_find_paths.py b/release/scripts/image_find_paths.py
deleted file mode 100644 (file)
index 266ecee..0000000
+++ /dev/null
@@ -1,167 +0,0 @@
-#!BPY
-
-"""
-Name: 'Fix Broken Paths'
-Blender: 242
-Group: 'Image'
-Tooltip: 'Search for new image paths to make relative links to'
-"""
-
-__author__ = "Campbell Barton AKA Ideasman"
-__url__ = ["blenderartist.org"]
-
-__bpydoc__ = """\
-Find image target paths
-
-This script searches for images whos
-file paths do not point to an existing image file,
-all image paths are made relative where possible.
-usefull when moving projects between computers, when absolute paths links are broken.
-"""
-
-# ***** BEGIN GPL LICENSE BLOCK *****
-#
-# Script copyright (C) Campbell J Barton
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-#
-# ***** END GPL LICENCE BLOCK *****
-# --------------------------------------------------------------------------
-
-
-from Blender import *
-
-try:
-       import os
-except:
-       Draw.PupMenu('You need a full python install to use this script')
-       os= None
-
-
-#==============================================#
-# Strips the slashes from the back of a string #
-#==============================================#
-def stripPath(path):
-       return path.split('/')[-1].split('\\')[-1]
-
-# finds the file starting at the root.
-def findImage(findRoot, imagePath):
-       newImageFile = None
-       
-       imageFile = imagePath.split('/')[-1].split('\\')[-1]
-       
-       # ROOT, DIRS, FILES
-       pathWalk = os.walk(findRoot)
-       pathList = [True]
-       
-       matchList = [] # Store a list of (match, size), choose the biggest.
-       while True:
-               try:
-                       pathList  = pathWalk.next()
-               except:
-                       break
-               
-               for file in pathList[2]:
-                       # FOUND A MATCH
-                       if file.lower() == imageFile.lower():
-                               name = pathList[0] + sys.sep + file
-                               try:
-                                       size = os.path.getsize(name)
-                               except:
-                                       size = 0
-                                       
-                               if size:
-                                       print '   found:', name 
-                                       matchList.append( (name, size) )
-               
-       if matchList == []:
-               print 'no match for:', imageFile
-               return None
-       else:
-               # Sort by file size
-               matchList.sort(lambda A, B: cmp(B[1], A[1]) )
-               
-               print 'using:', matchList[0][0]
-               # First item is the largest
-               return matchList[0][0] # 0 - first, 0 - pathname
-               
-
-# Makes the pathe relative to the blend file path.
-def makeRelative(path, blendBasePath):
-       if path.startswith(blendBasePath):
-               path = path.replace(blendBasePath, '//')
-               path = path.replace('//\\', '//')
-       return path
-
-def find_images(findRoot):
-       print findRoot
-       
-       # findRoot = Draw.PupStrInput ('find in: ', '', 100)
-       
-       if findRoot == '':
-               Draw.PupMenu('No Directory Selected')
-               return
-       
-       # Account for //
-       findRoot = sys.expandpath(findRoot)
-       
-       # Strip filename
-       while findRoot[-1] != '/' and findRoot[-1] != '\\':
-               findRoot = findRoot[:-1]
-       
-       
-       if not findRoot.endswith(sys.sep):
-               findRoot += sys.sep
-       
-       
-       if findRoot != '/' and not sys.exists(findRoot[:-1]):
-               Draw.PupMenu('Directory Dosent Exist')
-       
-       blendBasePath = sys.expandpath('//')
-       
-       
-       Window.WaitCursor(1)
-       # ============ DIR DONE\
-       images = Image.Get()
-       len_images = float(len(images))
-       for idx, i in enumerate(images):
-
-               progress = idx / len_images
-               Window.DrawProgressBar(progress, 'searching for images')
-               
-               # If files not there?
-               if not sys.exists(sys.expandpath(i.filename )): 
-                       newImageFile = findImage(findRoot, i.filename)
-                       if newImageFile != None:
-                               newImageFile= makeRelative(newImageFile, blendBasePath)
-                               print 'newpath relink:', newImageFile
-                               i.filename = newImageFile
-                               i.reload()
-               else:
-                       # Exists
-                       newImageFile= makeRelative(i.filename, blendBasePath)
-                       if newImageFile!=i.filename:
-                               print 'newpath relative:', newImageFile
-                               i.filename = newImageFile
-                       
-       
-       Window.RedrawAll()
-       Window.DrawProgressBar(1.0, '')
-       Window.WaitCursor(0)
-
-if __name__ == '__main__' and os:
-       Window.FileSelector(find_images, 'SEARCH ROOT DIR', sys.expandpath('//'))
-
-
index 30c4c410434c746d723bd1757b33b23367a43b21..e5bdc796e16b6efb7654c6d949e27cbcd1995e0c 100644 (file)
@@ -542,6 +542,9 @@ def get_float_func(filepath):
                                return lambda f: float(f.replace(',', '.'))
                        elif '.' in line:
                                return float
+       
+       # incase all vert values were ints 
+       return float
 
 def load_obj(filepath, CLAMP_SIZE= 0.0, CREATE_FGONS= True, CREATE_SMOOTH_GROUPS= True, CREATE_EDGES= True, SPLIT_OBJECTS= True, SPLIT_GROUPS= True, SPLIT_MATERIALS= True, IMAGE_SEARCH=True):
        '''
index 3ad844bfdc1811498961bd5b727112e000654ab6..7e3d7ac61330cfcd293ef96ee64d8f865cac1984 100644 (file)
@@ -190,6 +190,7 @@ void AVI_set_debug (int mode) {
        AVI_DEBUG= mode;
 }
 
+/*
 int AVI_is_avi (char *name) {
        FILE *fp;
        int ret;
@@ -209,6 +210,195 @@ int AVI_is_avi (char *name) {
        fclose(fp);
        return ret;
 }
+*/
+
+int AVI_is_avi (char *name) {
+       int temp, fcca, j;
+       AviMovie movie;
+       AviMainHeader header;
+       AviBitmapInfoHeader bheader;
+       
+       DEBUG("opening movie\n");
+
+       memset(&movie, 0, sizeof(AviMovie));
+
+       movie.type = AVI_MOVIE_READ;
+       movie.fp = fopen (name, "rb");
+       movie.offset_table = NULL;
+
+       if (movie.fp == NULL)
+               return 0;
+
+       if (GET_FCC (movie.fp) != FCC("RIFF") ||
+           !(movie.size = GET_FCC (movie.fp))) {
+           fclose(movie.fp);
+               return 0;
+       }
+
+       movie.header = &header;
+
+       if (GET_FCC (movie.fp) != FCC("AVI ") ||
+           GET_FCC (movie.fp) != FCC("LIST") ||
+           !GET_FCC (movie.fp) ||
+           GET_FCC (movie.fp) != FCC("hdrl") ||
+           (movie.header->fcc = GET_FCC (movie.fp)) != FCC("avih") ||
+           !(movie.header->size = GET_FCC (movie.fp))) {
+               DEBUG("bad initial header info\n");
+               fclose(movie.fp);
+               return 0;
+       }
+       
+       movie.header->MicroSecPerFrame = GET_FCC(movie.fp);
+       movie.header->MaxBytesPerSec = GET_FCC(movie.fp);
+       movie.header->PaddingGranularity = GET_FCC(movie.fp);
+       movie.header->Flags = GET_FCC(movie.fp);
+       movie.header->TotalFrames = GET_FCC(movie.fp);
+       movie.header->InitialFrames = GET_FCC(movie.fp);
+       movie.header->Streams = GET_FCC(movie.fp);
+       movie.header->SuggestedBufferSize = GET_FCC(movie.fp);
+       movie.header->Width = GET_FCC(movie.fp);
+       movie.header->Height = GET_FCC(movie.fp);
+       movie.header->Reserved[0] = GET_FCC(movie.fp);
+       movie.header->Reserved[1] = GET_FCC(movie.fp);
+       movie.header->Reserved[2] = GET_FCC(movie.fp);
+       movie.header->Reserved[3] = GET_FCC(movie.fp);
+
+       fseek (movie.fp, movie.header->size-14*4, SEEK_CUR);
+
+       if (movie.header->Streams < 1) {
+               DEBUG("streams less than 1\n");
+               fclose(movie.fp);
+               return 0;
+       }
+       
+       movie.streams = (AviStreamRec *) MEM_callocN (sizeof(AviStreamRec) * movie.header->Streams, "moviestreams");
+
+       for (temp=0; temp < movie.header->Streams; temp++) {
+
+               if (GET_FCC(movie.fp) != FCC("LIST") ||
+                   !GET_FCC (movie.fp) ||
+                   GET_FCC (movie.fp) != FCC ("strl") ||
+                   (movie.streams[temp].sh.fcc = GET_FCC (movie.fp)) != FCC ("strh") ||
+                   !(movie.streams[temp].sh.size = GET_FCC (movie.fp))) {
+                       DEBUG("bad stream header information\n");
+                       
+                       MEM_freeN(movie.streams);
+                       fclose(movie.fp);
+                       return 0;                               
+               }
+
+               movie.streams[temp].sh.Type = GET_FCC (movie.fp);
+               movie.streams[temp].sh.Handler = GET_FCC (movie.fp);
+
+               fcca = movie.streams[temp].sh.Handler;
+               
+               if (movie.streams[temp].sh.Type == FCC("vids")) {
+                       if (fcca == FCC ("DIB ") ||
+                               fcca == FCC ("RGB ") ||
+                               fcca == FCC ("rgb ") ||
+                               fcca == FCC ("RAW ") ||
+                               fcca == 0) {
+                               movie.streams[temp].format = AVI_FORMAT_AVI_RGB;
+                       } else if (fcca == FCC ("mjpg")||fcca == FCC ("MJPG")) {
+                               movie.streams[temp].format = AVI_FORMAT_MJPEG;
+                       } else {
+                               MEM_freeN(movie.streams);
+                               fclose(movie.fp);
+                               return 0;
+                       }
+               }
+               
+               movie.streams[temp].sh.Flags = GET_FCC (movie.fp);
+               movie.streams[temp].sh.Priority = GET_TCC (movie.fp);
+               movie.streams[temp].sh.Language = GET_TCC (movie.fp);
+               movie.streams[temp].sh.InitialFrames = GET_FCC (movie.fp);
+               movie.streams[temp].sh.Scale = GET_FCC (movie.fp);
+               movie.streams[temp].sh.Rate = GET_FCC (movie.fp);
+               movie.streams[temp].sh.Start = GET_FCC (movie.fp);
+               movie.streams[temp].sh.Length = GET_FCC (movie.fp);
+               movie.streams[temp].sh.SuggestedBufferSize = GET_FCC (movie.fp);
+               movie.streams[temp].sh.Quality = GET_FCC (movie.fp);
+               movie.streams[temp].sh.SampleSize = GET_FCC (movie.fp);
+               movie.streams[temp].sh.left = GET_TCC (movie.fp);
+               movie.streams[temp].sh.top = GET_TCC (movie.fp);
+               movie.streams[temp].sh.right = GET_TCC (movie.fp);
+               movie.streams[temp].sh.bottom = GET_TCC (movie.fp);
+
+               fseek (movie.fp, movie.streams[temp].sh.size-14*4, SEEK_CUR);
+
+               if (GET_FCC (movie.fp) != FCC("strf")) {
+                       DEBUG("no stream format information\n");
+                       MEM_freeN(movie.streams);
+                       fclose(movie.fp);
+                       return 0;
+               }
+
+               movie.streams[temp].sf_size= GET_FCC(movie.fp);
+               if (movie.streams[temp].sh.Type == FCC("vids")) {
+                       j = movie.streams[temp].sf_size - (sizeof(AviBitmapInfoHeader) - 8);
+                       if (j >= 0) {
+                               AviBitmapInfoHeader *bi;
+                               
+                               movie.streams[temp].sf= &bheader;
+                               bi= (AviBitmapInfoHeader *) movie.streams[temp].sf;
+                               
+                               bi->fcc= FCC("strf");
+                               bi->size= movie.streams[temp].sf_size;
+                               bi->Size= GET_FCC(movie.fp);
+                               bi->Width= GET_FCC(movie.fp);
+                               bi->Height= GET_FCC(movie.fp);
+                               bi->Planes= GET_TCC(movie.fp);
+                               bi->BitCount= GET_TCC(movie.fp);
+                               bi->Compression= GET_FCC(movie.fp);
+                               bi->SizeImage= GET_FCC(movie.fp);
+                               bi->XPelsPerMeter= GET_FCC(movie.fp);
+                               bi->YPelsPerMeter= GET_FCC(movie.fp);
+                               bi->ClrUsed= GET_FCC(movie.fp);
+                               bi->ClrImportant= GET_FCC(movie.fp);
+                               
+                               fcca = bi->Compression;
+
+                if ( movie.streams[temp].format ==
+                                        AVI_FORMAT_AVI_RGB) {
+                                       if (fcca == FCC ("DIB ") ||
+                                               fcca == FCC ("RGB ") ||
+                                               fcca == FCC ("rgb ") ||
+                                               fcca == FCC ("RAW ") ||
+                                               fcca == 0 ) {
+                                       } else if ( fcca == FCC ("mjpg") || 
+                                               fcca == FCC ("MJPG")) {
+                                                       movie.streams[temp].format = AVI_FORMAT_MJPEG;
+                                       } else {
+                                               MEM_freeN(movie.streams);
+                                               fclose(movie.fp);
+                                               return 0;
+                                       }
+                               }
+
+                       } 
+                       if (j > 0) fseek (movie.fp, j, SEEK_CUR);
+               } else fseek (movie.fp, movie.streams[temp].sf_size, SEEK_CUR);
+
+               /* Walk to the next LIST */             
+               while (GET_FCC (movie.fp) != FCC("LIST")) {
+                       temp= GET_FCC (movie.fp);
+                       if (temp<0 || ftell(movie.fp) > movie.size) {
+                               DEBUG("incorrect size in header or error in AVI\n");
+                               
+                               MEM_freeN(movie.streams);
+                               fclose(movie.fp);
+                           return 0;                           
+                       }
+                       fseek(movie.fp, temp, SEEK_CUR);                        
+               }
+
+               fseek(movie.fp, -4L, SEEK_CUR);
+       }
+       
+       MEM_freeN(movie.streams);
+       fclose(movie.fp);
+       return 1;
+}
 
 AviError AVI_open_movie (char *name, AviMovie *movie) {
        int temp, fcca, size, j;
index 8b9454f1a9d9e54deaa44b2b8ba0bb0e34c0b28a..94eafbf9f713e0344a2e5338be982be96ff07e18 100644 (file)
@@ -207,19 +207,6 @@ void post_layer_create(struct VLayer *vlayer);
 void post_layer_destroy(struct VLayer *vlayer);
 void post_server_add(void);
 
-/* multires.c */
-struct Multires;
-struct MultiresLevel;
-struct MultiresLevel *multires_level_n(struct Multires *mr, int n);
-void multires_free(struct Multires *mr);
-void multires_set_level(struct Object *ob, struct Mesh *me, const int render);
-void multires_update_levels(struct Mesh *me, const int render);
-void multires_calc_level_maps(struct MultiresLevel *lvl);
-struct Multires *multires_copy(struct Multires *orig);
-/* sculptmode.c */
-void sculptmode_free_all(struct Scene *sce);
-void sculptmode_init(struct Scene *sce);
-
 /* zbuf.c */
 void antialias_tagbuf(int xsize, int ysize, char *rectmove);
 
index b308342ac1e492e7647c22f2dc9039185e5d5250..47716e660779cfc3f694e72a3acda1acc7517cd2 100644 (file)
@@ -114,7 +114,7 @@ struct ImBuf *BKE_image_get_ibuf(struct Image *ima, struct ImageUser *iuser);
 struct Image *BKE_add_image_file(const char *name);
 
 /* adds image, adds ibuf, generates color or pattern */
-struct Image *BKE_add_image_size(int width, int height, char *name, short uvtestgrid, float color[4]);
+struct Image *BKE_add_image_size(int width, int height, char *name, int floatbuf, short uvtestgrid, float color[4]);
 
 /* for reload, refresh, pack */
 void BKE_image_signal(struct Image *ima, struct ImageUser *iuser, int signal);
index 2a6065eb4f169a70551656491874133dd78a25ed..01fe0903775a997cdc42f6a01ac5ee1616a42c5c 100644 (file)
@@ -95,7 +95,7 @@ void do_ipo_nocalc(struct Ipo *ipo);
 void do_ipo(struct Ipo *ipo);
 void do_mat_ipo(struct Material *ma);
 void do_ob_ipo(struct Object *ob);
-void do_seq_ipo(struct Sequence *seq);
+void do_seq_ipo(struct Sequence *seq, int cfra);
 void do_ob_ipodrivers(struct Object *ob, struct Ipo *ipo, float ctime);
 
 int has_ipo_code(struct Ipo *ipo, int code);
index be0a04ba563363b8f325c82a49e8812c42f55b5e..b60fd0ce954935273f9fe0354300643f8b95dc22 100644 (file)
@@ -111,6 +111,11 @@ UvVertMap *make_uv_vert_map(struct MFace *mface, struct MTFace *tface, unsigned
 UvMapVert *get_uv_map_vert(UvVertMap *vmap, unsigned int v);
 void free_uv_vert_map(UvVertMap *vmap);
 
+/* Partial Mesh Visibility */
+struct PartialVisibility *mesh_pmv_copy(struct PartialVisibility *);
+void mesh_pmv_free(struct PartialVisibility *);
+void mesh_pmv_revert(struct Object *ob, struct Mesh *me);
+void mesh_pmv_off(struct Object *ob, struct Mesh *me);
 
 /* functions for making menu's from customdata layers */
 int mesh_layers_menu_charlen(struct CustomData *data, int type); /* use this to work out how many chars to allocate */
diff --git a/source/blender/blenkernel/BKE_multires.h b/source/blender/blenkernel/BKE_multires.h
new file mode 100644 (file)
index 0000000..61eb796
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * $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 by Nicholas Bishop
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */ 
+
+struct CustomData;
+struct EditMesh;
+struct Multires;
+struct MultiresLevel;
+struct Mesh;
+struct Object;
+
+/* Level access */
+struct MultiresLevel *current_level(struct Multires *mr);
+struct MultiresLevel *multires_level_n(struct Multires *mr, int n);
+
+/* Level control */
+void multires_add_level(struct Object *ob, struct Mesh *me, const char subdiv_type);
+void multires_set_level(struct Object *ob, struct Mesh *me, const int render);
+void multires_free_level(struct MultiresLevel *lvl);
+
+void multires_edge_level_update(struct Object *ob, struct Mesh *me);
+
+void multires_free(struct Multires *mr);
+struct Multires *multires_copy(struct Multires *orig);
+void multires_create(struct Object *ob, struct Mesh *me);
+
+/* CustomData */
+void multires_delete_layer(struct Mesh *me, struct CustomData *cd, const int type, int n);
+void multires_add_layer(struct Mesh *me, struct CustomData *cd, const int type, const int n);
+void multires_del_lower_customdata(struct Multires *mr, struct MultiresLevel *cr_lvl);
+void multires_to_mcol(struct MultiresColFace *f, MCol mcol[4]);
+/* After adding or removing vcolor layers, run this */
+void multires_load_cols(struct Mesh *me);
+
+/* Private (used in multires-firstlevel.c) */
+void multires_level_to_mesh(struct Object *ob, struct Mesh *me, const int render);
+void multires_update_levels(struct Mesh *me, const int render);
+void multires_update_first_level(struct Mesh *me, struct EditMesh *em);
+void multires_update_customdata(struct MultiresLevel *lvl1, struct CustomData *src,
+                               struct CustomData *dst, const int type);
+void multires_customdata_to_mesh(struct Mesh *me, struct EditMesh *em,
+                                struct MultiresLevel *lvl, struct CustomData *src,
+                                 struct CustomData *dst, const int type);
index 2ffa1d205da935551fb3430d454dc0bad1695dfb..2008b18b5ed00703d7479eed3b114b1841adc0d4 100644 (file)
@@ -143,6 +143,7 @@ void                        nodeVerifyType(struct bNodeTree *ntree, struct bNode *node);
 
 void                   nodeAddToPreview(struct bNode *, float *, int, int);
 
+void                   nodeUnlinkNode(struct bNodeTree *ntree, struct bNode *node);
 struct bNode   *nodeAddNodeType(struct bNodeTree *ntree, int type, struct bNodeTree *ngroup);
 void                   nodeFreeNode(struct bNodeTree *ntree, struct bNode *node);
 struct bNode   *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node);
@@ -150,6 +151,8 @@ struct bNode        *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node);
 struct bNodeLink *nodeAddLink(struct bNodeTree *ntree, struct bNode *fromnode, struct bNodeSocket *fromsock, struct bNode *tonode, struct bNodeSocket *tosock);
 void                   nodeRemLink(struct bNodeTree *ntree, struct bNodeLink *link);
 
+int                    nodeFindNode(struct bNodeTree *ntree, struct bNodeSocket *sock, struct bNode **nodep, int *sockindex);
+
 struct bNodeLink *nodeFindLink(struct bNodeTree *ntree, struct bNodeSocket *from, struct bNodeSocket *to);
 int                            nodeCountSocketLinks(struct bNodeTree *ntree, struct bNodeSocket *sock);
 
@@ -303,6 +306,8 @@ void                        set_node_shader_lamp_loop(void (*lamp_loop_func)(struct ShadeInput *, str
 #define CMP_NODE_INVERT                251
 #define CMP_NODE_NORMALIZE      252
 #define CMP_NODE_CROP          253
+#define CMP_NODE_DBLUR         254
+#define CMP_NODE_BILATERALBLUR  255
 
 #define CMP_NODE_GLARE         301
 #define CMP_NODE_TONEMAP       302
index 1c69fe613c77676155cbc2306d64b94ae7065c6e..a1ac97406e161659ea54d6976375e9c8f56fca38 100644 (file)
@@ -112,8 +112,8 @@ typedef struct ParticleSeam{
 typedef struct ParticleCacheKey{
        float co[3];
        float vel[3];
-       float rot[4];
        float col[3];
+       float rot[4];
        int steps;
 } ParticleCacheKey;
 
@@ -165,7 +165,7 @@ typedef struct ParticleThreadContext {
 
        float *jit, *jitoff, *weight;
        float maxweight;
-       int *index, jitlevel;
+       int *index, *skip, jitlevel;
 
        int from, cfrom, distr;
 
@@ -214,8 +214,10 @@ void free_hair(struct ParticleSystem *psys);
 void free_keyed_keys(struct ParticleSystem *psys);
 void psys_free(struct Object * ob, struct ParticleSystem * psys);
 
-void psys_particles_to_render_backup(struct Object *ob, struct ParticleSystem *psys);
-void psys_render_backup_to_particles(struct Object *ob, struct ParticleSystem *psys);
+void psys_render_set(struct Object *ob, struct ParticleSystem *psys, float viewmat[][4], float winmat[][4], int winx, int winy);
+void psys_render_restore(struct Object *ob, struct ParticleSystem *psys);
+int psys_render_simplify_distribution(struct ParticleThreadContext *ctx, int tot);
+int psys_render_simplify_params(struct ParticleSystem *psys, struct ChildParticle *cpa, float *params);
 
 void clear_particles_from_cache(struct Object *ob, struct ParticleSystem *psys, int cfra);
 //void psys_remove_from_particle_list(struct Object *ob, short nbr, struct ParticleSystem *psys);
index 69ff6876acd00114b24254092240d9456dc7426c..3095383540652a08b2f5b139eaba38510f2af47e 100644 (file)
 #ifndef BKE_SCENE_H
 #define BKE_SCENE_H
 
+struct bglMats;
 struct Scene;
 struct Object;
 struct Base;
 struct AviCodecData;
 struct QuicktimeCodecData;
+struct SculptData;
 
 /* sequence related defines */
 #define WHILE_SEQ(base)        {                                                                                       \
diff --git a/source/blender/blenkernel/BKE_sculpt.h b/source/blender/blenkernel/BKE_sculpt.h
new file mode 100644 (file)
index 0000000..d539bcf
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * $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 by Nicholas Bishop
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef BKE_SCULPT_H
+#define BKE_SCULPT_H
+
+struct NumInput;
+struct Scene;
+struct SculptData;
+struct SculptSession;
+
+typedef enum PropsetMode {
+       PropsetNone = 0,
+       PropsetSize,
+       PropsetStrength,
+       PropsetTexRot
+} PropsetMode;
+
+typedef struct PropsetData {
+       PropsetMode mode;
+       unsigned int tex;
+       short origloc[2];
+       float *texdata;
+       
+       short origsize;
+       char origstrength;
+       float origtexrot;
+       
+       struct NumInput *num;
+} PropsetData;
+
+typedef struct SculptSession {
+       struct ProjVert *projverts;
+
+       struct bglMats *mats;
+       
+       /* An array of lists; array is sized as
+          large as the number of verts in the mesh,
+          the list for each vert contains the index
+          for all the faces that use that vertex */
+       struct ListBase *vertex_users;
+       struct IndexNode *vertex_users_mem;
+       int vertex_users_size;
+
+       /* Used temporarily per-stroke */
+       float *vertexcosnos;
+       ListBase damaged_rects;
+       ListBase damaged_verts;
+       
+       /* Used to cache the render of the active texture */
+       unsigned int texcache_w, texcache_h, *texcache;
+       
+       struct PropsetData *propset;
+       
+       /* For rotating around a pivot point */
+       vec3f pivot;
+
+       struct SculptStroke *stroke;
+} SculptSession;
+
+void sculptdata_init(struct Scene *sce);
+void sculptdata_free(struct Scene *sce);
+void sculptsession_free(struct Scene *sce);
+void sculpt_vertexusers_free(struct SculptSession *ss);
+void sculpt_reset_curve(struct SculptData *sd);
+
+#endif
index f3f66190c31b98f020bf2feb86d5cb006b390d08..d08f42375ac785f6456cdbf6e6487a924f4dd392 100644 (file)
 
 #define ABS(a)                                 ( (a)<0 ? (-(a)) : (a) )
 
+#define AVG2(x, y)             ( 0.5 * ((x) + (y)) )
+
 #define VECCOPY(v1,v2)          {*(v1)= *(v2); *(v1+1)= *(v2+1); *(v1+2)= *(v2+2);}
 #define VECCOPY2D(v1,v2)          {*(v1)= *(v2); *(v1+1)= *(v2+1);}
 #define QUATCOPY(v1,v2)         {*(v1)= *(v2); *(v1+1)= *(v2+1); *(v1+2)= *(v2+2); *(v1+3)= *(v2+3);}
index 55931b50462ae97a51aebb0e089edd1f3da80cc8..1bcbed1efb165d1afd82ca5344f3903564f22a0b 100644 (file)
@@ -310,15 +310,6 @@ void post_geometry_free_constraint(struct VNode *vnode) {}
 void post_layer_create(struct VLayer *vlayer) {}
 void post_layer_destroy(struct VLayer *vlayer) {}
 void post_server_add(void) {}
- /* Multires/sculpt stubs */
-struct MultiresLevel *multires_level_n(struct Multires *mr, int n) {return NULL;}
-void multires_free(struct Multires *mr) {}
-void multires_set_level(struct Object *ob, struct Mesh *me, const int render) {}
-void multires_update_levels(struct Mesh *me, const int render) {}
-void multires_calc_level_maps(struct MultiresLevel *lvl) {}
-struct Multires *multires_copy(struct Multires *orig) {return NULL;}
-void sculptmode_init(struct Scene *sce) {}
-void sculptmode_free_all(struct Scene *sce) {}
 
 /* zbuf.c stub */
 void antialias_tagbuf(int xsize, int ysize, char *rectmove) {}
index dd56fe2df6123b1176afc09e7440b1766eb6102a..aada60be21b3bd90ec00b0b078af5155d8e6a73d 100644 (file)
@@ -74,6 +74,7 @@
 #include "BKE_material.h"
 #include "BKE_modifier.h"
 #include "BKE_mesh.h"
+#include "BKE_multires.h"
 #include "BKE_object.h"
 #include "BKE_subsurf.h"
 #include "BKE_texture.h"
@@ -87,8 +88,6 @@
 #include "BIF_gl.h"
 #include "BIF_glutil.h"
 
-#include "multires.h"
-
 // headers for fluidsim bobj meshes
 #include <stdlib.h>
 #include "LBM_fluidsim.h"
@@ -2598,7 +2597,8 @@ float *multires_render_pin(Object *ob, Mesh *me, int *orig_lvl)
 }
 
 /* Propagate the changes to render level - fails if mesh topology changed */
-void multires_render_final(Object *ob, Mesh *me, DerivedMesh **dm, float *vert_copy, const int orig_lvl)
+void multires_render_final(Object *ob, Mesh *me, DerivedMesh **dm, float *vert_copy,
+                          const int orig_lvl, CustomDataMask dataMask)
 {
        if(me->mr) {
                if((*dm)->getNumVerts(*dm) == me->totvert &&
@@ -2619,6 +2619,9 @@ void multires_render_final(Object *ob, Mesh *me, DerivedMesh **dm, float *vert_c
                        (*dm)= CDDM_copy(old);
                        old->release(old);
 
+                       if(dataMask & CD_MASK_ORCO)
+                               add_orco_dm(ob, *dm, NULL);
+
                        /* Restore the original verts */
                        me->mr->newlvl= BLI_countlist(&me->mr->levels);
                        multires_set_level(ob, me, 1);
@@ -2646,7 +2649,7 @@ DerivedMesh *mesh_create_derived_render(Object *ob, CustomDataMask dataMask)
        
        vert_copy= multires_render_pin(ob, me, &orig_lvl);
        mesh_calc_modifiers(ob, NULL, NULL, &final, 1, 1, 0, dataMask);
-       multires_render_final(ob, me, &final, vert_copy, orig_lvl);
+       multires_render_final(ob, me, &final, vert_copy, orig_lvl, dataMask);
 
        return final;
 }
@@ -2681,7 +2684,7 @@ DerivedMesh *mesh_create_derived_no_deform_render(Object *ob,
 
        vert_copy= multires_render_pin(ob, me, &orig_lvl);
        mesh_calc_modifiers(ob, vertCos, NULL, &final, 1, 0, 0, dataMask);
-       multires_render_final(ob, me, &final, vert_copy, orig_lvl);
+       multires_render_final(ob, me, &final, vert_copy, orig_lvl, dataMask);
 
        return final;
 }
index 162ee582d744843590c70f9f62b2de55058c59d8..4dab625d2c96fd603150abfc557a79f8a937a4bc 100644 (file)
@@ -177,6 +177,10 @@ void free_action (bAction *act)
        
        if (act->chanbase.first)
                BLI_freelistN(&act->chanbase);
+               
+       /* Free pose-references */
+       if (act->markers.first)
+               BLI_freelistN(&act->markers);
 }
 
 bAction *copy_action (bAction *src)
@@ -188,6 +192,7 @@ bAction *copy_action (bAction *src)
        
        dst= copy_libblock(src);
        duplicatelist(&(dst->chanbase), &(src->chanbase));
+       duplicatelist(&(dst->markers), &(src->markers));
        
        for (dchan=dst->chanbase.first, schan=src->chanbase.first; dchan; dchan=dchan->next, schan=schan->next){
                dchan->ipo = copy_ipo(dchan->ipo);
index 1eb7e232382c08da9298cfc1b03742ae1dcc622b..0b733f9c0685331d4aade2ec73dfa3673a64967a 100644 (file)
 #include <config.h>
 #endif
 
+#define MAX_DUPLI_RECUR 4
+
+static void object_duplilist_recursive(ID *id, Object *ob, ListBase *duplilist, float (*par_space_mat)[][4], int level);
+
 void free_path(Path *path)
 {
        if(path->data) MEM_freeN(path->data);
@@ -306,7 +310,7 @@ static void group_duplilist(ListBase *lb, Object *ob, int level)
        group= ob->dup_group;
        
        /* simple preventing of too deep nested groups */
-       if(level>4) return;
+       if(level>MAX_DUPLI_RECUR) return;
        
        /* handles animated groups, and */
        /* we need to check update for objects that are not in scene... */
@@ -315,25 +319,29 @@ static void group_duplilist(ListBase *lb, Object *ob, int level)
        for(go= group->gobject.first; go; go= go->next) {
                /* note, if you check on layer here, render goes wrong... it still deforms verts and uses parent imat */
                if(go->ob!=ob) {
+                       
                        Mat4MulMat4(mat, go->ob->obmat, ob->obmat);
                        dob= new_dupli_object(lb, go->ob, mat, ob->lay, 0);
                        dob->no_draw= (dob->origlay & group->layer)==0;
                        
-                       if(go->ob->dup_group && (go->ob->transflag & OB_DUPLIGROUP)) {
+                       if(go->ob->transflag & OB_DUPLI) {
                                Mat4CpyMat4(dob->ob->obmat, dob->mat);
-                               group_duplilist(lb, go->ob, level+1);
+                               object_duplilist_recursive((ID *)group, go->ob, lb, &ob->obmat, level+1);
                                Mat4CpyMat4(dob->ob->obmat, dob->omat);
                        }
                }
        }
 }
 
-static void frames_duplilist(ListBase *lb, Object *ob)
+static void frames_duplilist(ListBase *lb, Object *ob, int level)
 {
        extern int enable_cu_speed;     /* object.c */
        Object copyob;
        int cfrao, ok;
        
+       /* simple preventing of too deep nested groups */
+       if(level>MAX_DUPLI_RECUR) return;
+       
        cfrao= G.scene->r.cfra;
        if(ob->parent==NULL && ob->track==NULL && ob->ipo==NULL && ob->constraints.first==NULL) return;
 
@@ -362,8 +370,11 @@ static void frames_duplilist(ListBase *lb, Object *ob)
 }
 
 struct vertexDupliData {
+       ID *id; /* scene or group, for recursive loops */
+       int level;
        ListBase *lb;
        float pmat[4][4];
+       float obmat[4][4]; /* Only used for dupliverts inside dupligroups, where the ob->obmat is modified */
        Object *ob, *par;
 };
 
@@ -375,9 +386,9 @@ static void vertex_dupli__mapFunc(void *userData, int index, float *co, float *n
        VECCOPY(vec, co);
        Mat4MulVecfl(vdd->pmat, vec);
        VecSubf(vec, vec, vdd->pmat[3]);
-       VecAddf(vec, vec, vdd->ob->obmat[3]);
+       VecAddf(vec, vec, vdd->obmat[3]);
        
-       Mat4CpyMat4(obmat, vdd->ob->obmat);
+       Mat4CpyMat4(obmat, vdd->obmat);
        VECCOPY(obmat[3], vec);
        
        if(vdd->par->transflag & OB_DUPLIROT) {
@@ -395,19 +406,32 @@ static void vertex_dupli__mapFunc(void *userData, int index, float *co, float *n
                Mat4MulMat43(obmat, tmat, mat);
        }
        new_dupli_object(vdd->lb, vdd->ob, obmat, vdd->par->lay, index);
+       
+       if(vdd->ob->transflag & OB_DUPLI) {
+               float tmpmat[4][4];
+               Mat4CpyMat4(tmpmat, vdd->ob->obmat);
+               Mat4CpyMat4(vdd->ob->obmat, obmat); /* pretend we are really this mat */
+               object_duplilist_recursive((ID *)vdd->id, vdd->ob, vdd->lb, &obmat, vdd->level+1);
+               Mat4CpyMat4(vdd->ob->obmat, tmpmat);
+       }
 }
 
-static void vertex_duplilist(ListBase *lb, Scene *sce, Object *par)
+static void vertex_duplilist(ListBase *lb, ID *id, Object *par, float (*par_space_mat)[][4], int level)
 {
-       Object *ob;
-       Base *base;
+       Object *ob, *ob_iter;
+       Base *base = NULL;
        float vec[3], no[3], pmat[4][4];
-       int lay, totvert, a;
+       int lay, totvert, a, oblay;
        DerivedMesh *dm;
+       struct vertexDupliData vdd;
+       Scene *sce = NULL;
+       Group *group = NULL;
+       GroupObject * go = NULL;
        
        Mat4CpyMat4(pmat, par->obmat);
        
-       lay= G.scene->lay;
+       /* simple preventing of too deep nested groups */
+       if(level>MAX_DUPLI_RECUR) return;
        
        if(par==G.obedit)
                dm= editmesh_get_derived_cage(CD_MASK_BAREMESH);
@@ -416,16 +440,45 @@ static void vertex_duplilist(ListBase *lb, Scene *sce, Object *par)
        
        totvert = dm->getNumVerts(dm);
 
-       base= sce->base.first;
-       while(base) {
-
-               if(base->object->type>0 && (lay & base->lay) && G.obedit!=base->object) {
-                       ob= base->object->parent;
+       /* having to loop on scene OR group objects is NOT FUN */
+       if (GS(id->name) == ID_SCE) {
+               sce = (Scene *)id;
+               lay= sce->lay;
+               base= sce->base.first;
+       } else {
+               group = (Group *)id;
+               lay= group->layer;
+               go = group->gobject.first;
+       }
+       
+       /* Start looping on Scene OR Group objects */
+       while (base || go) { 
+               if (sce) {
+                       ob_iter= base->object;
+                       oblay = base->lay;
+               } else {
+                       ob_iter= go->ob;
+                       oblay = ob_iter->lay;
+               }
+               
+               if (lay & oblay && G.obedit!=ob_iter) {
+                       ob=ob_iter->parent;
                        while(ob) {
                                if(ob==par) {
-                                       struct vertexDupliData vdd;
+                                       ob = ob_iter;
+       /* End Scene/Group object loop, below is generic */
                                        
-                                       ob= base->object;
+                                       
+                                       /* par_space_mat - only used for groups so we can modify the space dupli's are in
+                                          when par_space_mat is NULL ob->obmat can be used instead of ob__obmat
+                                       */
+                                       if (par_space_mat) {
+                                               Mat4MulMat4(vdd.obmat, ob->obmat, *par_space_mat);
+                                       } else {
+                                               Mat4CpyMat4(vdd.obmat, ob->obmat);
+                                       }
+                                       vdd.id= id;
+                                       vdd.level= level;
                                        vdd.lb= lb;
                                        vdd.ob= ob;
                                        vdd.par= par;
@@ -451,25 +504,32 @@ static void vertex_duplilist(ListBase *lb, Scene *sce, Object *par)
                                ob= ob->parent;
                        }
                }
-               base= base->next;
+               if (sce)        base= base->next;       /* scene loop */
+               else            go= go->next;           /* group loop */
        }
 
        dm->release(dm);
 }
 
-static void face_duplilist(ListBase *lb, Scene *sce, Object *par)
+static void face_duplilist(ListBase *lb, ID *id, Object *par, float (*par_space_mat)[][4], int level)
 {
-       Object *ob;
-       Base *base;
+       Object *ob, *ob_iter;
+       Base *base = NULL;
        DerivedMesh *dm;
        MFace *mface;
        MVert *mvert;
        float pmat[4][4], imat[3][3];
-       int lay, totface, a;
+       int lay, oblay, totface, a;
+       Scene *sce = NULL;
+       Group *group = NULL;
+       GroupObject *go = NULL;
        
-       Mat4CpyMat4(pmat, par->obmat);
+       float ob__obmat[4][4]; /* needed for groups where the object matrix needs to be modified */
        
-       lay= G.scene->lay;
+       /* simple preventing of too deep nested groups */
+       if(level>MAX_DUPLI_RECUR) return;
+       
+       Mat4CpyMat4(pmat, par->obmat);
        
        if(par==G.obedit) {
                int totvert;
@@ -491,16 +551,45 @@ static void face_duplilist(ListBase *lb, Scene *sce, Object *par)
        }
        
        
-       for(base= sce->base.first; base; base= base->next) {
+       /* having to loop on scene OR group objects is NOT FUN */
+       if (GS(id->name) == ID_SCE) {
+               sce = (Scene *)id;
+               lay= sce->lay;
+               base= sce->base.first;
+       } else {
+               group = (Group *)id;
+               lay= group->layer;
+               go = group->gobject.first;
+       }
+       
+       /* Start looping on Scene OR Group objects */
+       while (base || go) { 
+               if (sce) {
+                       ob_iter= base->object;
+                       oblay = base->lay;
+               } else {
+                       ob_iter= go->ob;
+                       oblay = ob_iter->lay;
+               }
                
-               if(base->object->type>0 && (lay & base->lay) && G.obedit!=base->object) {
-                       ob= base->object->parent;
+               if (lay & oblay && G.obedit!=ob_iter) {
+                       ob=ob_iter->parent;
                        while(ob) {
                                if(ob==par) {
+                                       ob = ob_iter;
+       /* End Scene/Group object loop, below is generic */
                                        
-                                       ob= base->object;
-                                       Mat3CpyMat4(imat, ob->parentinv);
+                                       /* par_space_mat - only used for groups so we can modify the space dupli's are in
+                                          when par_space_mat is NULL ob->obmat can be used instead of ob__obmat
+                                       */
+                                       if (par_space_mat) {
+                                               Mat4MulMat4(ob__obmat, ob->obmat, *par_space_mat);
+                                       } else {
+                                               Mat4CpyMat4(ob__obmat, ob->obmat);
+                                       }
                                        
+                                       Mat3CpyMat4(imat, ob->parentinv);
+                                               
                                        /* mballs have a different dupli handling */
                                        if(ob->type!=OB_MBALL) ob->flag |= OB_DONE;     /* doesnt render */
 
@@ -519,9 +608,10 @@ static void face_duplilist(ListBase *lb, Scene *sce, Object *par)
                                                Mat4MulVecfl(pmat, cent);
                                                
                                                VecSubf(cent, cent, pmat[3]);
-                                               VecAddf(cent, cent, ob->obmat[3]);
+                                               VecAddf(cent, cent, ob__obmat[3]);
+                                               
+                                               Mat4CpyMat4(obmat, ob__obmat);
                                                
-                                               Mat4CpyMat4(obmat, ob->obmat);
                                                VECCOPY(obmat[3], cent);
                                                
                                                /* rotation */
@@ -542,7 +632,14 @@ static void face_duplilist(ListBase *lb, Scene *sce, Object *par)
                                                Mat4MulMat43(obmat, tmat, mat);
                                                
                                                new_dupli_object(lb, ob, obmat, lay, a);
-
+                                               
+                                               if(ob->transflag & OB_DUPLI) {
+                                                       float tmpmat[4][4];
+                                                       Mat4CpyMat4(tmpmat, ob->obmat);
+                                                       Mat4CpyMat4(ob->obmat, obmat); /* pretend we are really this mat */
+                                                       object_duplilist_recursive((ID *)id, ob, lb, &ob->obmat, level+1);
+                                                       Mat4CpyMat4(ob->obmat, tmpmat);
+                                               }
                                        }
                                        
                                        break;
@@ -550,6 +647,8 @@ static void face_duplilist(ListBase *lb, Scene *sce, Object *par)
                                ob= ob->parent;
                        }
                }
+               if (sce)        base= base->next;       /* scene loop */
+               else            go= go->next;           /* group loop */
        }
        
        if(par==G.obedit) {
@@ -560,7 +659,7 @@ static void face_duplilist(ListBase *lb, Scene *sce, Object *par)
        dm->release(dm);
 }
 
-static void new_particle_duplilist(ListBase *lb, Scene *sce, Object *par, ParticleSystem *psys)
+static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, ParticleSystem *psys, int level)
 {
        GroupObject *go;
        Object *ob, **oblist=0;
@@ -575,6 +674,11 @@ static void new_particle_duplilist(ListBase *lb, Scene *sce, Object *par, Partic
 
        if(psys==0) return;
        
+       /* simple preventing of too deep nested groups */
+       if(level>MAX_DUPLI_RECUR) return;
+       
+       if (GS(id->name)!=ID_SCE) return; /* No support for groups YET! TODO */
+       
        part=psys->part;
 
        if(part==0) return;
@@ -722,7 +826,7 @@ static Object *find_family_object(Object **obar, char *family, char ch)
 }
 
 
-static void font_duplilist(ListBase *lb, Object *par)
+static void font_duplilist(ListBase *lb, Object *par, int level)
 {
        Object *ob, *obar[256];
        Curve *cu;
@@ -730,6 +834,9 @@ static void font_duplilist(ListBase *lb, Object *par)
        float vec[3], obmat[4][4], pmat[4][4], fsize, xof, yof;
        int slen, a;
        
+       /* simple preventing of too deep nested groups */
+       if(level>MAX_DUPLI_RECUR) return;
+       
        Mat4CpyMat4(pmat, par->obmat);
        
        /* in par the family name is stored, use this to find the other objects */
@@ -769,45 +876,63 @@ static void font_duplilist(ListBase *lb, Object *par)
 }
 
 /* ***************************** */
+static void object_duplilist_recursive(ID *id, Object *ob, ListBase *duplilist, float (*par_space_mat)[][4], int level)
+{      
+       if((ob->transflag & OB_DUPLI)==0)
+               return;
+       
+       /* Should the dupli's be greated for this object? - Respect restrict flags */
+       if (G.rendering) {
+               if (ob->restrictflag & OB_RESTRICT_RENDER) {
+                       return;
+               }
+       } else {
+               if (ob->restrictflag & OB_RESTRICT_VIEW) {
+                       return;
+               }
+       }
 
-/* note; group dupli's already set transform matrix. see note in group_duplilist() */
-ListBase *object_duplilist(Scene *sce, Object *ob)
-{
-       ListBase *duplilist= MEM_mallocN(sizeof(ListBase), "duplilist");
-       duplilist->first= duplilist->last= NULL;
-
-       if(ob->transflag & OB_DUPLI) {
-               if(ob->transflag & OB_DUPLIPARTS) {
-                       ParticleSystem *psys = ob->particlesystem.first;
-                       for(; psys; psys=psys->next)
-                               new_particle_duplilist(duplilist, sce, ob, psys);
+       if(ob->transflag & OB_DUPLIPARTS) {
+               ParticleSystem *psys = ob->particlesystem.first;
+               for(; psys; psys=psys->next)
+                       new_particle_duplilist(duplilist, id, ob, psys, level+1);
+       }
+       else if(ob->transflag & OB_DUPLIVERTS) {
+               if(ob->type==OB_MESH) {
+                       vertex_duplilist(duplilist, id, ob, par_space_mat, level+1);
                }
-               else if(ob->transflag & OB_DUPLIVERTS) {
-                       if(ob->type==OB_MESH) {
-                               vertex_duplilist(duplilist, sce, ob);
-                       }
-                       else if(ob->type==OB_FONT) {
-                               font_duplilist(duplilist, ob);
+               else if(ob->type==OB_FONT) {
+                       if (GS(id->name)==ID_SCE) { /* TODO - support dupligroups */
+                               font_duplilist(duplilist, ob, level+1);
                        }
                }
-               else if(ob->transflag & OB_DUPLIFACES) {
-                       if(ob->type==OB_MESH)
-                               face_duplilist(duplilist, sce, ob);
+       }
+       else if(ob->transflag & OB_DUPLIFACES) {
+               if(ob->type==OB_MESH)
+                       face_duplilist(duplilist, id, ob, par_space_mat, level+1);
+       }
+       else if(ob->transflag & OB_DUPLIFRAMES) {
+               if (GS(id->name)==ID_SCE) { /* TODO - support dupligroups */
+                       frames_duplilist(duplilist, ob, level+1);
                }
-               else if(ob->transflag & OB_DUPLIFRAMES) 
-                       frames_duplilist(duplilist, ob);
-               else if(ob->transflag & OB_DUPLIGROUP) {
-                       DupliObject *dob;
-                       
-                       group_duplilist(duplilist, ob, 0); /* now recursive */
+       } else if(ob->transflag & OB_DUPLIGROUP) {
+               DupliObject *dob;
+               
+               group_duplilist(duplilist, ob, level+1); /* now recursive */
 
-                       /* make copy already, because in group dupli's deform displists can be made, requiring parent matrices */
+               if (level==0) {
                        for(dob= duplilist->first; dob; dob= dob->next)
                                Mat4CpyMat4(dob->ob->obmat, dob->mat);
                }
-               
        }
-       
+}
+
+/* note; group dupli's already set transform matrix. see note in group_duplilist() */
+ListBase *object_duplilist(Scene *sce, Object *ob)
+{
+       ListBase *duplilist= MEM_mallocN(sizeof(ListBase), "duplilist");
+       duplilist->first= duplilist->last= NULL;
+       object_duplilist_recursive((ID *)sce, ob, duplilist, NULL, 0);
        return duplilist;
 }
 
index 83b014cdd63cddef3d9f1e4a7fa5e13bee3097a2..e4336576e2a82ef020eccd5b3c0d9fd888184cb5 100644 (file)
@@ -167,18 +167,30 @@ void curvemap_remove(CurveMap *cuma, int flag)
 void curvemap_insert(CurveMap *cuma, float x, float y)
 {
        CurveMapPoint *cmp= MEM_callocN((cuma->totpoint+1)*sizeof(CurveMapPoint), "curve points");
-       int a;
-       
-       memcpy(cmp, cuma->curve, (cuma->totpoint)*sizeof(CurveMapPoint));
+       int a, b, foundloc= 0;
+               
+       /* insert fragments of the old one and the new point to the new curve */
+       cuma->totpoint++;
+       for(a=0, b=0; a<cuma->totpoint; a++) {
+               if((x < cuma->curve[a].x) && !foundloc) {
+                       cmp[a].x= x;
+                       cmp[a].y= y;
+                       cmp[a].flag= CUMA_SELECT;
+                       foundloc= 1;
+               }
+               else {
+                       cmp[a].x= cuma->curve[b].x;
+                       cmp[a].y= cuma->curve[b].y;
+                       cmp[a].flag= cuma->curve[b].flag;
+                       cmp[a].flag &= ~CUMA_SELECT; /* make sure old points don't remain selected */
+                       cmp[a].shorty= cuma->curve[b].shorty;
+                       b++;
+               }
+       }
+
+       /* free old curve and replace it with new one */
        MEM_freeN(cuma->curve);
        cuma->curve= cmp;
-       
-       cuma->curve[cuma->totpoint].x= x;
-       cuma->curve[cuma->totpoint].y= y;
-       cuma->curve[cuma->totpoint].flag = CUMA_SELECT;
-       for(a=0; a<cuma->totpoint; a++, cmp++)
-               cmp->flag= 0;
-       cuma->totpoint++;
 }
 
 void curvemap_reset(CurveMap *cuma, rctf *clipr)
index de4f4555823a3df5d402bfd179354efa0e19d136..fd22579ea67111897b68a03ba57c5303b1ac04ec 100644 (file)
@@ -1467,7 +1467,7 @@ void makeBevelList(Object *ob)
        BevPoint *bevp, *bevp2, *bevp1 = NULL, *bevp0;
        float  *data, *data_a, *v1, *v2, min, inp, x1, x2, y1, y2, vec[3];
        struct bevelsort *sortdata, *sd, *sd1;
-       int a, b, len, nr, poly, resolu;
+       int a, b, nr, poly, resolu, len=0;
 
        /* this function needs an object, because of tflag and upflag */
        cu= ob->data;
index ed944a3a4ea8dbb249f3d13040d2f24bae2d02a5..3b40907244ae418454e9213f7e0d640cd83189bc 100644 (file)
 /* used by sequencer and image premul option - IMA_DO_PREMUL */
 void converttopremul(struct ImBuf *ibuf)
 {
-       int x, y, val;
-       char *cp;
+       int x, y;
        
        if(ibuf==0) return;
-       if(ibuf->depth==24) {   /* put alpha at 255 */
-               
-               cp= (char *)(ibuf->rect);
-               for(y=0; y<ibuf->y; y++) {
-                       for(x=0; x<ibuf->x; x++, cp+=4) {
-                               cp[3]= 255;
+       if (ibuf->rect) {
+               int val;
+               char *cp;
+               if(ibuf->depth==24) {   /* put alpha at 255 */
+                       cp= (char *)(ibuf->rect);
+                       for(y=0; y<ibuf->y; y++) {
+                               for(x=0; x<ibuf->x; x++, cp+=4) {
+                                       cp[3]= 255;
+                               }
+                       }
+               } else {
+                       cp= (char *)(ibuf->rect);
+                       for(y=0; y<ibuf->y; y++) {
+                               for(x=0; x<ibuf->x; x++, cp+=4) {
+                                       val= cp[3];
+                                       cp[0]= (cp[0]*val)>>8;
+                                       cp[1]= (cp[1]*val)>>8;
+                                       cp[2]= (cp[2]*val)>>8;
+                               }
                        }
                }
-               return;
        }
-
-       cp= (char *)(ibuf->rect);
-       for(y=0; y<ibuf->y; y++) {
-               for(x=0; x<ibuf->x; x++, cp+=4) {
-                       if(cp[3]==0) {
-                               cp[0]= cp[1]= cp[2]= 0;
+       if (ibuf->rect_float) {
+               float val;
+               float *cp;
+               if(ibuf->depth==24) {   /* put alpha at 1.0 */
+                       cp= ibuf->rect_float;;
+                       for(y=0; y<ibuf->y; y++) {
+                               for(x=0; x<ibuf->x; x++, cp+=4) {
+                                       cp[3]= 1.0;
+                               }
                        }
-                       else if(cp[3]!=255) {
-                               val= cp[3];
-                               cp[0]= (cp[0]*val)>>8;
-                               cp[1]= (cp[1]*val)>>8;
-                               cp[2]= (cp[2]*val)>>8;
+               } else {
+                       cp= ibuf->rect_float;
+                       for(y=0; y<ibuf->y; y++) {
+                               for(x=0; x<ibuf->x; x++, cp+=4) {
+                                       val= cp[3];
+                                       cp[0]= cp[0]*val;
+                                       cp[1]= cp[1]*val;
+                                       cp[2]= cp[2]*val;
+                               }
                        }
                }
        }
@@ -378,20 +396,27 @@ Image *BKE_add_image_file(const char *name)
        return ima;
 }
 
-static ImBuf *add_ibuf_size(int width, int height, char *name, short uvtestgrid, float color[4])
+static ImBuf *add_ibuf_size(int width, int height, char *name, int floatbuf, short uvtestgrid, float color[4])
 {
        ImBuf *ibuf;
        float h=0.0, hoffs=0.0, hue=0.0, s=0.9, v=0.9, r, g, b;
        unsigned char *rect;
+       float *rect_float;
        int x, y;
        int checkerwidth=21, dark=1;
        
-       ibuf= IMB_allocImBuf(width, height, 24, IB_rect, 0);
+       if (floatbuf) {
+               ibuf= IMB_allocImBuf(width, height, 24, IB_rectfloat, 0);
+               rect_float= (float*)ibuf->rect_float;
+       }
+       else {
+               ibuf= IMB_allocImBuf(width, height, 24, IB_rect, 0);
+               rect= (unsigned char*)ibuf->rect;
+       }
+       
        strcpy(ibuf->name, "Untitled");
        ibuf->userflags |= IB_BITMAPDIRTY;
        
-       rect= (unsigned char*)ibuf->rect;
-       
        if (uvtestgrid) {
                /* these two passes could be combined into one, but it's more readable and 
                * easy to tweak like this, speed isn't really that much of an issue in this situation... */
@@ -400,26 +425,40 @@ static ImBuf *add_ibuf_size(int width, int height, char *name, short uvtestgrid,
                for(y=0; y<ibuf->y; y++) {
                        dark = pow(-1, floor(y / checkerwidth));
                        
-                       for(x=0; x<ibuf->x; x++, rect+=4) {
+                       for(x=0; x<ibuf->x; x++) {
                                if (x % checkerwidth == 0) dark *= -1;
                                
-                               if (dark > 0) {
-                                       rect[0] = rect[1] = rect[2] = 64;
-                                       rect[3] = 255;
-                               } else {
-                                       rect[0] = rect[1] = rect[2] = 150;
-                                       rect[3] = 255;
+                               if (floatbuf) {
+                                       if (dark > 0) {
+                                               rect_float[0] = rect_float[1] = rect_float[2] = 0.25;
+                                               rect_float[3] = 1.0;
+                                       } else {
+                                               rect_float[0] = rect_float[1] = rect_float[2] = 0.58;
+                                               rect_float[3] = 1.0;
+                                       }
+                                       rect_float+=4;
+                               }
+                               else {
+                                       if (dark > 0) {
+                                               rect[0] = rect[1] = rect[2] = 64;
+                                               rect[3] = 255;
+                                       } else {
+                                               rect[0] = rect[1] = rect[2] = 150;
+                                               rect[3] = 255;
+                                       }
+                                       rect += 4;
                                }
                        }
                }
                
                /* 2nd pass, colored + */
-               rect= (unsigned char*)ibuf->rect;
+               if (floatbuf) rect_float= (float*)ibuf->rect_float;
+               else rect= (unsigned char*)ibuf->rect;
                
                for(y=0; y<ibuf->y; y++) {
                        hoffs = 0.125 * floor(y / checkerwidth);
                        
-                       for(x=0; x<ibuf->x; x++, rect+=4) {
+                       for(x=0; x<ibuf->x; x++) {
                                h = 0.125 * floor(x / checkerwidth);
                                
                                if ((fabs((x % checkerwidth) - (checkerwidth / 2)) < 4) &&
@@ -431,10 +470,20 @@ static ImBuf *add_ibuf_size(int width, int height, char *name, short uvtestgrid,
                                                hue = fmod(fabs(h-hoffs), 1.0);
                                                hsv_to_rgb(hue, s, v, &r, &g, &b);
                                                
-                                               rect[0]= (char)(r * 255.0);
-                                               rect[1]= (char)(g * 255.0);
-                                               rect[2]= (char)(b * 255.0);
-                                               rect[3]= 255;
+                                               if (floatbuf) {
+                                                       rect_float[0]= r;
+                                                       rect_float[1]= g;
+                                                       rect_float[2]= b;
+                                                       rect_float[3]= 1.0;
+                                                       rect_float+=4;
+                                               }
+                                               else {
+                                                       rect[0]= (char)(r * 255.0);
+                                                       rect[1]= (char)(g * 255.0);
+                                                       rect[2]= (char)(b * 255.0);
+                                                       rect[3]= 255;
+                                                       rect+=4;
+                                               }
                                        }
                                }
                                
@@ -442,11 +491,21 @@ static ImBuf *add_ibuf_size(int width, int height, char *name, short uvtestgrid,
                }
        } else {        /* blank image */
                for(y=0; y<ibuf->y; y++) {
-                       for(x=0; x<ibuf->x; x++, rect+=4) {
-                               rect[0]= (char)(color[0] * 255.0);
-                               rect[1]= (char)(color[1] * 255.0);
-                               rect[2]= (char)(color[2] * 255.0);
-                               rect[3]= (char)(color[3] * 255.0);
+                       for(x=0; x<ibuf->x; x++) {
+                               if (floatbuf) {
+                                       rect_float[0]= color[0];
+                                       rect_float[1]= color[1];
+                                       rect_float[2]= color[2];
+                                       rect_float[3]= color[3];
+                                       rect_float+=4;
+                               }
+                               else {
+                                       rect[0]= (char)(color[0] * 255.0);
+                                       rect[1]= (char)(color[1] * 255.0);
+                                       rect[2]= (char)(color[2] * 255.0);
+                                       rect[3]= (char)(color[3] * 255.0);
+                                       rect+=4;
+                               }
                        }
                }
        }
@@ -454,7 +513,7 @@ static ImBuf *add_ibuf_size(int width, int height, char *name, short uvtestgrid,
 }
 
 /* adds new image block, creates ImBuf and initializes color */
-Image *BKE_add_image_size(int width, int height, char *name, short uvtestgrid, float color[4])
+Image *BKE_add_image_size(int width, int height, char *name, int floatbuf, short uvtestgrid, float color[4])
 {
        Image *ima;
        
@@ -469,7 +528,7 @@ Image *BKE_add_image_size(int width, int height, char *name, short uvtestgrid, f
                ima->gen_y= height;
                ima->gen_type= uvtestgrid;
                
-               ibuf= add_ibuf_size(width, height, name, uvtestgrid, color);
+               ibuf= add_ibuf_size(width, height, name, floatbuf, uvtestgrid, color);
                image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0);
                
                ima->ok= IMA_OK_LOADED;
@@ -812,8 +871,8 @@ static void stampdata(StampData *stamp_data, int do_prefix)
        }
        
        if (G.scene->r.stamp & R_STAMP_NOTE) {
-               if (do_prefix)          sprintf(stamp_data->note, "Note %s", G.scene->r.stamp_udata);
-               else                            sprintf(stamp_data->note, "%s", G.scene->r.stamp_udata);
+               /* Never do prefix for Note */
+               sprintf(stamp_data->note, "%s", G.scene->r.stamp_udata);
        } else {
                stamp_data->note[0] = '\0';
        }
@@ -1678,6 +1737,7 @@ ImBuf *BKE_image_get_ibuf(Image *ima, ImageUser *iuser)
 {
        ImBuf *ibuf= NULL;
        float color[] = {0, 0, 0, 1};
+       int floatbuf;
 
        /* quick reject tests */
        if(ima==NULL) 
@@ -1755,7 +1815,7 @@ ImBuf *BKE_image_get_ibuf(Image *ima, ImageUser *iuser)
                                /* UV testgrid or black or solid etc */
                                if(ima->gen_x==0) ima->gen_x= 256;
                                if(ima->gen_y==0) ima->gen_y= 256;
-                               ibuf= add_ibuf_size(ima->gen_x, ima->gen_y, ima->name, ima->gen_type, color);
+                               ibuf= add_ibuf_size(ima->gen_x, ima->gen_y, ima->name, floatbuf, ima->gen_type, color);
                                image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0);
                                ima->ok= IMA_OK_LOADED;
                        }
index 876f1c50a93a5ba11713d5092105cde8d5f059e8..4af310913d65b97d4677a8b5a6daad4f6be54546 100644 (file)
@@ -2161,7 +2161,7 @@ void do_ob_ipodrivers(Object *ob, Ipo *ipo, float ctime)
        }
 }
 
-void do_seq_ipo(Sequence *seq)
+void do_seq_ipo(Sequence *seq, int cfra)
 {
        float ctime, div;
        
@@ -2169,11 +2169,10 @@ void do_seq_ipo(Sequence *seq)
        
        if(seq->ipo) {
                if((seq->flag & SEQ_IPO_FRAME_LOCKED) != 0) {
-                       ctime = frame_to_float(G.scene->r.cfra);
+                       ctime = frame_to_float(cfra);
                        div = 1.0;
                } else {
-                       ctime= frame_to_float(G.scene->r.cfra 
-                                             - seq->startdisp);
+                       ctime= frame_to_float(cfra - seq->startdisp);
                        div= (seq->enddisp - seq->startdisp)/100.0f;
                        if(div==0.0) return;
                }
@@ -2291,7 +2290,7 @@ void do_all_data_ipos()
                             || seq->type == SEQ_HD_SOUND) && (seq->ipo) && 
                                (seq->startdisp<=G.scene->r.cfra+2) && 
                            (seq->enddisp>G.scene->r.cfra)) 
-                                       do_seq_ipo(seq);
+                                       do_seq_ipo(seq, G.scene->r.cfra);
                        seq= seq->next;
                }
        }
index 79a8afedf3f4855eea5c6bcc7d0f3070ab65b980..25a391be5669501f34c46ddf4b3c05744fd8b022 100644 (file)
 #include "DNA_meshdata_types.h"
 #include "DNA_ipo_types.h"
 
-#include "BDR_sculptmode.h"
-
 #include "BKE_customdata.h"
 #include "BKE_depsgraph.h"
 #include "BKE_main.h"
 #include "BKE_DerivedMesh.h"
 #include "BKE_global.h"
 #include "BKE_mesh.h"
+#include "BKE_multires.h"
 #include "BKE_subsurf.h"
 #include "BKE_displist.h"
 #include "BKE_library.h"
@@ -83,8 +82,6 @@
 #include "BLI_editVert.h"
 #include "BLI_arithb.h"
 
-#include "multires.h"
-
 int update_realtime_texture(MTFace *tface, double time)
 {
        Image *ima;
@@ -489,21 +486,12 @@ float *get_mesh_orco_verts(Object *ob)
                vcos= mesh_getRefKeyCos(me, &totvert);
        }
        else {
-               MultiresLevel *lvl = NULL;
-               MVert *mvert = NULL;
-               
-               if(me->mr) {
-                       lvl = multires_level_n(me->mr, me->mr->pinlvl);
-                       vcos = MEM_callocN(sizeof(*vcos)*lvl->totvert, "orco mr mesh");
-                       mvert = me->mr->verts;
-                       totvert = lvl->totvert;
-               }
-               else {
-                       Mesh *tme = me->texcomesh?me->texcomesh:me;
-                       vcos = MEM_callocN(sizeof(*vcos)*me->totvert, "orco mesh");
-                       mvert = tme->mvert;
-                       totvert = MIN2(tme->totvert, me->totvert);
-               }
+               MVert *mvert = NULL;            
+               Mesh *tme = me->texcomesh?me->texcomesh:me;
+
+               vcos = MEM_callocN(sizeof(*vcos)*me->totvert, "orco mesh");
+               mvert = tme->mvert;
+               totvert = MIN2(tme->totvert, me->totvert);
 
                for(a=0; a<totvert; a++, mvert++) {
                        vcos[a][0]= mvert->co[0];
@@ -1240,3 +1228,70 @@ void free_uv_vert_map(UvVertMap *vmap)
        }
 }
 
+/* Partial Mesh Visibility */
+PartialVisibility *mesh_pmv_copy(PartialVisibility *pmv)
+{
+       PartialVisibility *n= MEM_dupallocN(pmv);
+       n->vert_map= MEM_dupallocN(pmv->vert_map);
+       n->edge_map= MEM_dupallocN(pmv->edge_map);
+       n->old_edges= MEM_dupallocN(pmv->old_edges);
+       n->old_faces= MEM_dupallocN(pmv->old_faces);
+       return n;
+}
+
+void mesh_pmv_free(PartialVisibility *pv)
+{
+       MEM_freeN(pv->vert_map);
+       MEM_freeN(pv->edge_map);
+       MEM_freeN(pv->old_faces);
+       MEM_freeN(pv->old_edges);
+       MEM_freeN(pv);
+}
+
+void mesh_pmv_revert(Object *ob, Mesh *me)
+{
+       if(me->pv) {
+               unsigned i;
+               MVert *nve, *old_verts;
+               
+               /* Reorder vertices */
+               nve= me->mvert;
+               old_verts = MEM_mallocN(sizeof(MVert)*me->pv->totvert,"PMV revert verts");
+               for(i=0; i<me->pv->totvert; ++i)
+                       old_verts[i]= nve[me->pv->vert_map[i]];
+
+               /* Restore verts, edges and faces */
+               CustomData_free_layer_active(&me->vdata, CD_MVERT, me->totvert);
+               CustomData_free_layer_active(&me->edata, CD_MEDGE, me->totedge);
+               CustomData_free_layer_active(&me->fdata, CD_MFACE, me->totface);
+
+               CustomData_add_layer(&me->vdata, CD_MVERT, CD_ASSIGN, old_verts, me->pv->totvert);
+               CustomData_add_layer(&me->edata, CD_MEDGE, CD_ASSIGN, me->pv->old_edges, me->pv->totedge);
+               CustomData_add_layer(&me->fdata, CD_MFACE, CD_ASSIGN, me->pv->old_faces, me->pv->totface);
+               mesh_update_customdata_pointers(me);
+
+               me->totvert= me->pv->totvert;
+               me->totedge= me->pv->totedge;
+               me->totface= me->pv->totface;
+
+               me->pv->old_edges= NULL;
+               me->pv->old_faces= NULL;
+
+               /* Free maps */
+               MEM_freeN(me->pv->edge_map);
+               me->pv->edge_map= NULL;
+               MEM_freeN(me->pv->vert_map);
+               me->pv->vert_map= NULL;
+
+               DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
+       }
+}
+
+void mesh_pmv_off(Object *ob, Mesh *me)
+{
+       if(ob && me->pv) {
+               mesh_pmv_revert(ob, me);
+               MEM_freeN(me->pv);
+               me->pv= NULL;
+       }
+}
similarity index 99%
rename from source/blender/src/multires-firstlevel.c
rename to source/blender/blenkernel/intern/multires-firstlevel.c
index 2be867b5db017e79815b17e92d7b4a673ea8a620..778dd6f9c7796eadf2ab536bba2b8d83342115ed 100644 (file)
 #include "BKE_customdata.h"
 #include "BKE_global.h"
 #include "BKE_mesh.h"
+#include "BKE_multires.h"
 
 #include "BLI_editVert.h"
 
 #include "MEM_guardedalloc.h"
 
 #include "blendef.h"
-#include "multires.h"
 
 #include <string.h>
 
@@ -392,7 +392,6 @@ void multires_delete_layer(Mesh *me, CustomData *cd, const int type, int n)
        }
 }
 
-MultiresLevel *current_level(Multires *mr);
 void multires_add_layer(Mesh *me, CustomData *cd, const int type, const int n)
 {
        if(me && me->mr && cd) {
diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c
new file mode 100644 (file)
index 0000000..0874890
--- /dev/null
@@ -0,0 +1,1305 @@
+/*
+ * $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 by Nicholas Bishop
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_key_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_vec_types.h"
+
+#include "BIF_editmesh.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+#include "BLI_editVert.h"
+
+#include "BKE_customdata.h"
+#include "BKE_depsgraph.h"
+#include "BKE_global.h"
+#include "BKE_multires.h"
+
+#include "blendef.h"
+#include "editmesh.h"
+
+#include <math.h>
+
+/* Returns the active multires level (currently applied to the mesh) */
+MultiresLevel *current_level(Multires *mr)
+{
+       return BLI_findlink(&mr->levels, mr->current - 1);
+}
+
+/* Returns the nth multires level, starting at 1 */
+MultiresLevel *multires_level_n(Multires *mr, int n)
+{
+       if(mr)
+               return BLI_findlink(&mr->levels, n - 1);
+       else
+               return NULL;
+}
+
+/* Free and clear the temporary connectivity data */
+static void multires_free_temp_data(MultiresLevel *lvl)
+{
+       if(lvl) {
+               if(lvl->edge_boundary_states) MEM_freeN(lvl->edge_boundary_states);
+               if(lvl->vert_edge_map) MEM_freeN(lvl->vert_edge_map);
+               if(lvl->vert_face_map) MEM_freeN(lvl->vert_face_map);
+               if(lvl->map_mem) MEM_freeN(lvl->map_mem);
+
+               lvl->edge_boundary_states = NULL;
+               lvl->vert_edge_map = lvl->vert_face_map = NULL;
+               lvl->map_mem = NULL;
+       }
+}
+
+/* Does not actually free lvl itself */
+void multires_free_level(MultiresLevel *lvl)
+{
+       if(lvl) {
+               if(lvl->faces) MEM_freeN(lvl->faces);
+               if(lvl->edges) MEM_freeN(lvl->edges);
+               if(lvl->colfaces) MEM_freeN(lvl->colfaces);
+               
+               multires_free_temp_data(lvl);
+       }
+}
+
+void multires_free(Multires *mr)
+{
+       if(mr) {
+               MultiresLevel* lvl= mr->levels.first;
+
+               /* Free the first-level data */
+               if(lvl) {
+                       CustomData_free(&mr->vdata, lvl->totvert);
+                       CustomData_free(&mr->fdata, lvl->totface);
+                       MEM_freeN(mr->edge_flags);
+                       MEM_freeN(mr->edge_creases);
+               }
+
+               while(lvl) {
+                       multires_free_level(lvl);                       
+                       lvl= lvl->next;
+               }
+
+               MEM_freeN(mr->verts);
+
+               BLI_freelistN(&mr->levels);
+
+               MEM_freeN(mr);
+       }
+}
+
+static MultiresLevel *multires_level_copy(MultiresLevel *orig)
+{
+       if(orig) {
+               MultiresLevel *lvl= MEM_dupallocN(orig);
+               
+               lvl->next= lvl->prev= NULL;
+               lvl->faces= MEM_dupallocN(orig->faces);
+               lvl->colfaces= MEM_dupallocN(orig->colfaces);
+               lvl->edges= MEM_dupallocN(orig->edges);
+               lvl->edge_boundary_states = NULL;
+               lvl->vert_edge_map= lvl->vert_face_map= NULL;
+               lvl->map_mem= NULL;
+               
+               return lvl;
+       }
+       return NULL;
+}
+
+Multires *multires_copy(Multires *orig)
+{
+       const CustomDataMask vdata_mask= CD_MASK_MDEFORMVERT;
+
+       if(orig) {
+               Multires *mr= MEM_dupallocN(orig);
+               MultiresLevel *lvl;
+               
+               mr->levels.first= mr->levels.last= NULL;
+               
+               for(lvl= orig->levels.first; lvl; lvl= lvl->next)
+                       BLI_addtail(&mr->levels, multires_level_copy(lvl));
+
+               mr->verts= MEM_dupallocN(orig->verts);
+               
+               lvl= mr->levels.first;
+               if(lvl) {
+                       CustomData_copy(&orig->vdata, &mr->vdata, vdata_mask, CD_DUPLICATE, lvl->totvert);
+                       CustomData_copy(&orig->fdata, &mr->fdata, CD_MASK_MTFACE, CD_DUPLICATE, lvl->totface);
+                       mr->edge_flags= MEM_dupallocN(orig->edge_flags);
+                       mr->edge_creases= MEM_dupallocN(orig->edge_creases);
+               }
+               
+               return mr;
+       }
+       return NULL;
+}
+
+static void multires_get_vert(MVert *out, EditVert *eve, MVert *m, int i)
+{
+       if(eve) {
+               VecCopyf(out->co, eve->co);
+               out->flag= 0;
+               if(eve->f & SELECT) out->flag |= 1;
+               if(eve->h) out->flag |= ME_HIDE;
+               eve->tmp.l= i;
+       }
+       else
+               *out= *m;
+}
+
+void eed_to_medge_flag(EditEdge *eed, short *flag, char *crease)
+{
+       if(!eed || !flag) return;
+
+       /* Would be nice if EditMesh edge flags could be unified with Mesh flags! */
+       *flag= (eed->f & SELECT) | ME_EDGERENDER;
+       if(eed->f2<2) *flag |= ME_EDGEDRAW;
+       if(eed->f2==0) *flag |= ME_LOOSEEDGE;
+       if(eed->sharp) *flag |= ME_SHARP;
+       if(eed->seam) *flag |= ME_SEAM;
+       if(eed->h & EM_FGON) *flag |= ME_FGON;
+       if(eed->h & 1) *flag |= ME_HIDE;
+       
+       *crease= (char)(255.0*eed->crease);
+}
+
+static void multires_get_edge(MultiresEdge *e, EditEdge *eed, MEdge *m, short *flag, char *crease)
+{
+       if(eed) {
+               e->v[0]= eed->v1->tmp.l;
+               e->v[1]= eed->v2->tmp.l;
+               eed_to_medge_flag(eed, flag, crease);
+       } else {                
+               e->v[0]= m->v1;
+               e->v[1]= m->v2;
+               *flag= m->flag;
+               *crease= m->crease;
+       }
+}
+
+static void multires_get_face(MultiresFace *f, EditFace *efa, MFace *m)
+{
+       if(efa) {
+               MFace tmp;
+               int j;
+               tmp.v1= efa->v1->tmp.l;
+               tmp.v2= efa->v2->tmp.l;
+               tmp.v3= efa->v3->tmp.l;
+               tmp.v4= 0;
+               if(efa->v4) tmp.v4= efa->v4->tmp.l;
+               test_index_face(&tmp, NULL, 0, efa->v4?4:3);
+               for(j=0; j<4; ++j) f->v[j]= (&tmp.v1)[j];
+
+               /* Flags */
+               f->flag= efa->flag;
+               if(efa->f & 1) f->flag |= ME_FACE_SEL;
+               else f->flag &= ~ME_FACE_SEL;
+               if(efa->h) f->flag |= ME_HIDE;
+               f->mat_nr= efa->mat_nr;
+       } else {                
+               f->v[0]= m->v1;
+               f->v[1]= m->v2;
+               f->v[2]= m->v3;
+               f->v[3]= m->v4;
+               f->flag= m->flag;
+               f->mat_nr= m->mat_nr;
+       }
+}
+
+/* For manipulating vertex colors / uvs */
+static void mcol_to_multires(MultiresColFace *mrf, MCol *mcol)
+{
+       char i;
+       for(i=0; i<4; ++i) {
+               mrf->col[i].a= mcol[i].a;
+               mrf->col[i].r= mcol[i].r;
+               mrf->col[i].g= mcol[i].g;
+               mrf->col[i].b= mcol[i].b;
+       }
+}
+
+/* 1 <= count <= 4 */
+static void multires_col_avg(MultiresCol *avg, MultiresCol cols[4], char count)
+{
+       unsigned i;
+       avg->a= avg->r= avg->g= avg->b= 0;
+       for(i=0; i<count; ++i) {
+               avg->a+= cols[i].a;
+               avg->r+= cols[i].r;
+               avg->g+= cols[i].g;
+               avg->b+= cols[i].b;
+       }
+       avg->a/= count;
+       avg->r/= count;
+       avg->g/= count;
+       avg->b/= count;
+}
+
+static void multires_col_avg2(MultiresCol *avg, MultiresCol *c1, MultiresCol *c2)
+{
+       MultiresCol in[2];
+       in[0]= *c1;
+       in[1]= *c2;
+       multires_col_avg(avg,in,2);
+}
+
+void multires_load_cols(Mesh *me)
+{
+       MultiresLevel *lvl= BLI_findlink(&me->mr->levels,me->mr->current-1), *cur;
+       EditMesh *em= G.obedit ? G.editMesh : NULL;
+       CustomData *src= em ? &em->fdata : &me->fdata;
+       EditFace *efa= NULL;
+       unsigned i,j;
+
+       if(!CustomData_has_layer(src, CD_MCOL) && !CustomData_has_layer(src, CD_MTFACE)) return;
+
+       /* Add texcol data */
+       for(cur= me->mr->levels.first; cur; cur= cur->next)
+               if(!cur->colfaces)
+                       cur->colfaces= MEM_callocN(sizeof(MultiresColFace)*cur->totface,"ColFaces");
+
+       me->mr->use_col= CustomData_has_layer(src, CD_MCOL);
+
+       if(em) efa= em->faces.first;
+       for(i=0; i<lvl->totface; ++i) {
+               MultiresColFace *f= &lvl->colfaces[i];
+
+               if(me->mr->use_col)
+                       mcol_to_multires(f, em ? CustomData_em_get(src, efa->data, CD_MCOL) : &me->mcol[i*4]);
+               
+               if(em) efa= efa->next;
+       }
+
+       /* Update higher levels */
+       lvl= lvl->next;
+       while(lvl) {
+               MultiresColFace *cf= lvl->colfaces;
+               for(i=0; i<lvl->prev->totface; ++i) {
+                       const char sides= lvl->prev->faces[i].v[3]?4:3;
+                       MultiresCol cntr;
+                       
+                       /* Find average color of 4 (or 3 for triangle) verts */
+                       multires_col_avg(&cntr,lvl->prev->colfaces[i].col,sides);
+                       
+                       for(j=0; j<sides; ++j) {
+                               MultiresColFace *pf= &lvl->prev->colfaces[i];
+
+                               multires_col_avg2(&cf->col[0],
+                                                 &pf->col[j],
+                                                 &pf->col[j==0?sides-1:j-1]);
+                               cf->col[1]= pf->col[j];
+                               multires_col_avg2(&cf->col[2],
+                                                 &pf->col[j],
+                                                 &pf->col[j==sides-1?0:j+1]);
+                               cf->col[3]= cntr;
+                               
+                               ++cf;
+                       }
+               }
+               lvl= lvl->next;
+       }
+
+       /* Update lower levels */
+       lvl= me->mr->levels.last;
+       lvl= lvl->prev;
+       while(lvl) {
+               unsigned curf= 0;
+               for(i=0; i<lvl->totface; ++i) {
+                       MultiresFace *f= &lvl->faces[i];
+                       for(j=0; j<(f->v[3]?4:3); ++j) {
+                               lvl->colfaces[i].col[j]= lvl->next->colfaces[curf].col[1];
+                               ++curf;
+                       }
+               }
+               lvl= lvl->prev;
+       }
+}
+
+void multires_create(Object *ob, Mesh *me)
+{
+       MultiresLevel *lvl;
+       EditMesh *em= G.obedit ? G.editMesh : NULL;
+       EditVert *eve= NULL;
+       EditFace *efa= NULL;
+       EditEdge *eed= NULL;
+       int i;
+       
+       lvl= MEM_callocN(sizeof(MultiresLevel), "multires level");
+
+       if(me->pv) mesh_pmv_off(ob, me);
+
+       me->mr= MEM_callocN(sizeof(Multires), "multires data");
+       
+       BLI_addtail(&me->mr->levels,lvl);
+       me->mr->current= 1;
+       me->mr->level_count= 1;
+       me->mr->edgelvl= 1;
+       me->mr->pinlvl= 1;
+       me->mr->renderlvl= 1;
+       
+       /* Load mesh (or editmesh) into multires data */
+
+       /* Load vertices and vdata (MDeformVerts) */
+       lvl->totvert= em ? BLI_countlist(&em->verts) : me->totvert;
+       me->mr->verts= MEM_callocN(sizeof(MVert)*lvl->totvert,"multires verts");
+       multires_update_customdata(me->mr->levels.first, em ? &em->vdata : &me->vdata,
+                                  &me->mr->vdata, CD_MDEFORMVERT);
+       if(em) eve= em->verts.first;
+       for(i=0; i<lvl->totvert; ++i) {
+               multires_get_vert(&me->mr->verts[i], eve, &me->mvert[i], i);
+               if(em) eve= eve->next;
+       }
+
+       /* Load faces and fdata (MTFaces) */
+       lvl->totface= em ? BLI_countlist(&em->faces) : me->totface;
+       lvl->faces= MEM_callocN(sizeof(MultiresFace)*lvl->totface,"multires faces");
+       multires_update_customdata(me->mr->levels.first, em ? &em->fdata : &me->fdata,
+                                  &me->mr->fdata, CD_MTFACE);
+       if(em) efa= em->faces.first;
+       for(i=0; i<lvl->totface; ++i) {
+               multires_get_face(&lvl->faces[i], efa, &me->mface[i]);
+               if(em) efa= efa->next;
+       }
+
+       /* Load edges and edge_flags */
+       lvl->totedge= em ? BLI_countlist(&em->edges) : me->totedge;
+       lvl->edges= MEM_callocN(sizeof(MultiresEdge)*lvl->totedge,"multires edges");
+       me->mr->edge_flags= MEM_callocN(sizeof(short)*lvl->totedge, "multires edge flags");
+       me->mr->edge_creases= MEM_callocN(sizeof(short)*lvl->totedge, "multires edge creases");
+       if(em) eed= em->edges.first;
+       for(i=0; i<lvl->totedge; ++i) {
+               multires_get_edge(&lvl->edges[i], eed, &me->medge[i], &me->mr->edge_flags[i], &me->mr->edge_creases[i]);
+               if(em) eed= eed->next;
+       }
+
+       multires_load_cols(me);
+}
+
+typedef struct MultiresMapNode {
+       struct MultiresMapNode *next, *prev;
+       unsigned Index;
+} MultiresMapNode;
+
+/* Produces temporary connectivity data for the multires lvl */
+static void multires_calc_temp_data(MultiresLevel *lvl)
+{
+       unsigned i, j, emax;
+       MultiresMapNode *indexnode= NULL;
+
+       lvl->map_mem= MEM_mallocN(sizeof(MultiresMapNode)*(lvl->totedge*2 + lvl->totface*4), "map_mem");
+       indexnode= lvl->map_mem;
+       
+       /* edge map */
+       lvl->vert_edge_map= MEM_callocN(sizeof(ListBase)*lvl->totvert,"vert_edge_map");
+       for(i=0; i<lvl->totedge; ++i) {
+               for(j=0; j<2; ++j, ++indexnode) {
+                       indexnode->Index= i;
+                       BLI_addtail(&lvl->vert_edge_map[lvl->edges[i].v[j]], indexnode);
+               }
+       }
+
+       /* face map */
+               lvl->vert_face_map= MEM_callocN(sizeof(ListBase)*lvl->totvert,"vert_face_map");
+       for(i=0; i<lvl->totface; ++i){
+               for(j=0; j<(lvl->faces[i].v[3]?4:3); ++j, ++indexnode) {
+                       indexnode->Index= i;
+                       BLI_addtail(&lvl->vert_face_map[lvl->faces[i].v[j]], indexnode);
+               }
+       }
+
+       /* edge boundaries */
+       emax = (lvl->prev ? (lvl->prev->totedge * 2) : lvl->totedge);
+       lvl->edge_boundary_states= MEM_callocN(sizeof(char)*lvl->totedge, "edge_boundary_states");
+       for(i=0; i<emax; ++i) {
+               MultiresMapNode *n1= lvl->vert_face_map[lvl->edges[i].v[0]].first;
+               unsigned total= 0;
+               
+               lvl->edge_boundary_states[i] = 1;
+               while(n1 && lvl->edge_boundary_states[i] == 1) {
+                       MultiresMapNode *n2= lvl->vert_face_map[lvl->edges[i].v[1]].first;
+                       while(n2) {
+                               if(n1->Index == n2->Index) {
+                                       ++total;
+                                       
+                                       if(total > 1) {
+                                               lvl->edge_boundary_states[i] = 0;
+                                               break;
+                                       }
+                               }
+                               
+                               n2= n2->next;
+                       }
+                       n1= n1->next;
+               }
+       }
+}
+
+/* CATMULL-CLARK
+   ============= */
+
+typedef struct MultiApplyData {
+       /* Smooth faces */
+       float *corner1, *corner2, *corner3, *corner4;
+       char quad;
+
+       /* Smooth edges */
+       char boundary;
+       float edge_face_neighbor_midpoints_accum[3];
+       unsigned edge_face_neighbor_midpoints_total;
+       float *endpoint1, *endpoint2;
+
+       /* Smooth verts */
+       /* uses 'char boundary' */
+       float *original;
+       int edge_count;
+       float vert_face_neighbor_midpoints_average[3];
+       float vert_edge_neighbor_midpoints_average[3];
+       float boundary_edges_average[3];
+} MultiApplyData;
+
+/* Simply averages the four corners of a polygon. */
+static float catmullclark_smooth_face(MultiApplyData *data, const unsigned i)
+{
+       const float total= data->corner1[i]+data->corner2[i]+data->corner3[i];
+       return data->quad ? (total+data->corner4[i])/4 : total/3;
+}
+
+static float catmullclark_smooth_edge(MultiApplyData *data, const unsigned i)
+{
+       float accum= 0;
+       unsigned count= 2;
+
+       accum+= data->endpoint1[i] + data->endpoint2[i];
+
+       if(!data->boundary) {
+               accum+= data->edge_face_neighbor_midpoints_accum[i];
+               count+= data->edge_face_neighbor_midpoints_total;
+       }
+
+       return accum / count;
+}
+
+static float catmullclark_smooth_vert(MultiApplyData *data, const unsigned i)
+{
+       if(data->boundary) {
+               return data->original[i]*0.75 + data->boundary_edges_average[i]*0.25;
+       } else {
+               return (data->vert_face_neighbor_midpoints_average[i] +
+                       2*data->vert_edge_neighbor_midpoints_average[i] +
+                       data->original[i]*(data->edge_count-3))/data->edge_count;
+       }
+}
+
+
+
+/* Call func count times, passing in[i] as the input and storing the output in out[i] */
+static void multi_apply(float *out, MultiApplyData *data,
+                const unsigned count, float (*func)(MultiApplyData *, const unsigned))
+{
+       unsigned i;
+       for(i=0; i<count; ++i)
+               out[i]= func(data,i);
+}
+
+static short multires_vert_is_boundary(MultiresLevel *lvl, unsigned v)
+{
+       MultiresMapNode *node= lvl->vert_edge_map[v].first;
+       while(node) {
+               if(lvl->edge_boundary_states[node->Index])
+                       return 1;
+               node= node->next;
+       }
+       return 0;
+}
+
+#define GET_FLOAT(array, i, j, stride) (((float*)((char*)(array)+((i)*(stride))))[(j)])
+
+static void edge_face_neighbor_midpoints_accum(MultiApplyData *data, MultiresLevel *lvl,
+                                             void *array, const char stride, const MultiresEdge *e)
+{
+       ListBase *neighbors1= &lvl->vert_face_map[e->v[0]];
+       ListBase *neighbors2= &lvl->vert_face_map[e->v[1]];
+       MultiresMapNode *n1, *n2;
+       unsigned j,count= 0;
+       float *out= data->edge_face_neighbor_midpoints_accum;
+       
+       out[0]=out[1]=out[2]= 0;
+
+       for(n1= neighbors1->first; n1; n1= n1->next) {
+               for(n2= neighbors2->first; n2; n2= n2->next) {
+                       if(n1->Index == n2->Index) {
+                               for(j=0; j<3; ++j)
+                                       out[j]+= GET_FLOAT(array,lvl->faces[n1->Index].mid,j,stride);
+                               ++count;
+                       }
+               }
+       }
+
+       data->edge_face_neighbor_midpoints_total= count;
+}
+
+static void vert_face_neighbor_midpoints_average(MultiApplyData *data, MultiresLevel *lvl,
+                                                void *array, const char stride, const unsigned i)
+{
+       ListBase *neighbors= &lvl->vert_face_map[i];
+       MultiresMapNode *n1;
+       unsigned j,count= 0;
+       float *out= data->vert_face_neighbor_midpoints_average;
+
+       out[0]=out[1]=out[2]= 0;
+
+       for(n1= neighbors->first; n1; n1= n1->next) {
+               for(j=0; j<3; ++j)
+                       out[j]+= GET_FLOAT(array,lvl->faces[n1->Index].mid,j,stride);
+               ++count;
+       }
+       for(j=0; j<3; ++j) out[j]/= count;
+}
+
+static void vert_edge_neighbor_midpoints_average(MultiApplyData *data, MultiresLevel *lvl,
+                                                void *array, const char stride, const unsigned i)
+{
+       ListBase *neighbors= &lvl->vert_edge_map[i];
+       MultiresMapNode *n1;
+       unsigned j,count= 0;
+       float *out= data->vert_edge_neighbor_midpoints_average;
+
+       out[0]=out[1]=out[2]= 0;
+
+       for(n1= neighbors->first; n1; n1= n1->next) {
+               for(j=0; j<3; ++j)
+                       out[j]+= (GET_FLOAT(array,lvl->edges[n1->Index].v[0],j,stride) +
+                                 GET_FLOAT(array,lvl->edges[n1->Index].v[1],j,stride)) / 2;
+               ++count;
+       }
+       for(j=0; j<3; ++j) out[j]/= count;
+}
+
+static void boundary_edges_average(MultiApplyData *data, MultiresLevel *lvl,
+                                  void *array, const char stride, const unsigned i)
+{
+       ListBase *neighbors= &lvl->vert_edge_map[i];
+       MultiresMapNode *n1;
+       unsigned j,count= 0;
+       float *out= data->boundary_edges_average;
+
+       out[0]=out[1]=out[2]= 0;
+       
+       for(n1= neighbors->first; n1; n1= n1->next) {
+               const MultiresEdge *e= &lvl->edges[n1->Index];
+               const unsigned end= e->v[0]==i ? e->v[1] : e->v[0];
+               
+               if(lvl->edge_boundary_states[n1->Index]) {
+                       for(j=0; j<3; ++j)
+                               out[j]+= GET_FLOAT(array,end,j,stride);
+                       ++count;
+               }
+       }
+       for(j=0; j<3; ++j) out[j]/= count;
+}
+
+/* END CATMULL-CLARK
+   ================= */
+
+/* Update vertex locations and vertex flags */
+static void multires_update_vertices(Mesh *me, EditMesh *em)
+{
+       MultiresLevel *cr_lvl= current_level(me->mr), *pr_lvl= NULL,
+                     *last_lvl= me->mr->levels.last;
+       vec3f *pr_deltas= NULL, *cr_deltas= NULL, *swap_deltas= NULL;
+       EditVert *eve= NULL;
+       MultiApplyData data;
+       int i, j;
+
+       /* Prepare deltas */
+       pr_deltas= MEM_callocN(sizeof(vec3f)*last_lvl->totvert, "multires deltas 1");
+       cr_deltas= MEM_callocN(sizeof(vec3f)*last_lvl->totvert, "multires deltas 2");
+
+       /* Calculate initial deltas -- current mesh subtracted from current level*/
+       if(em) eve= em->verts.first;
+       for(i=0; i<cr_lvl->totvert; ++i) {
+               if(em) {
+                       VecSubf(&cr_deltas[i].x, eve->co, me->mr->verts[i].co);
+                       eve= eve->next;
+               } else
+                       VecSubf(&cr_deltas[i].x, me->mvert[i].co, me->mr->verts[i].co);
+       }
+
+
+       /* Copy current level's vertex flags and clear the rest */
+       if(em) eve= em->verts.first;    
+       for(i=0; i < last_lvl->totvert; ++i) {
+               if(i < cr_lvl->totvert) {
+                       MVert mvflag;
+                       multires_get_vert(&mvflag, eve, &me->mvert[i], i);
+                       if(em) eve= eve->next;
+                       me->mr->verts[i].flag= mvflag.flag;
+               }
+               else
+                       me->mr->verts[i].flag= 0;
+       }
+
+       /* If already on the highest level, copy current verts (including flags) into current level */
+       if(cr_lvl == last_lvl) {
+               if(em)
+                       eve= em->verts.first;
+               for(i=0; i<cr_lvl->totvert; ++i) {
+                       multires_get_vert(&me->mr->verts[i], eve, &me->mvert[i], i);
+                       if(em) eve= eve->next;
+               }
+       }
+
+       /* Update higher levels */
+       pr_lvl= BLI_findlink(&me->mr->levels,me->mr->current-1);
+       cr_lvl= pr_lvl->next;
+       while(cr_lvl) {
+               multires_calc_temp_data(pr_lvl);                
+
+               /* Swap the old/new deltas */
+               swap_deltas= pr_deltas;
+               pr_deltas= cr_deltas;
+               cr_deltas= swap_deltas;
+
+               /* Calculate and add new deltas
+                  ============================ */
+               for(i=0; i<pr_lvl->totface; ++i) {
+                       const MultiresFace *f= &pr_lvl->faces[i];
+                       data.corner1= &pr_deltas[f->v[0]].x;
+                       data.corner2= &pr_deltas[f->v[1]].x;
+                       data.corner3= &pr_deltas[f->v[2]].x;
+                       data.corner4= &pr_deltas[f->v[3]].x;
+                       data.quad= f->v[3] ? 1 : 0;
+                       multi_apply(&cr_deltas[f->mid].x, &data, 3, catmullclark_smooth_face);
+                       
+                       for(j=0; j<(data.quad?4:3); ++j)
+                               me->mr->verts[f->mid].flag |= me->mr->verts[f->v[j]].flag;
+               }
+
+               for(i=0; i<pr_lvl->totedge; ++i) {
+                       const MultiresEdge *e= &pr_lvl->edges[i];
+                       data.boundary= pr_lvl->edge_boundary_states[i];
+                       edge_face_neighbor_midpoints_accum(&data,pr_lvl,cr_deltas,sizeof(vec3f),e);
+                       data.endpoint1= &pr_deltas[e->v[0]].x;
+                       data.endpoint2= &pr_deltas[e->v[1]].x;
+                       multi_apply(&cr_deltas[e->mid].x, &data, 3, catmullclark_smooth_edge);
+                               
+                       for(j=0; j<2; ++j)
+                               me->mr->verts[e->mid].flag |= me->mr->verts[e->v[j]].flag;
+               }
+
+               for(i=0; i<pr_lvl->totvert; ++i) {
+                       data.boundary= multires_vert_is_boundary(pr_lvl,i);
+                       data.original= &pr_deltas[i].x;
+                       data.edge_count= BLI_countlist(&pr_lvl->vert_edge_map[i]);
+                       if(data.boundary)
+                               boundary_edges_average(&data,pr_lvl,pr_deltas,sizeof(vec3f),i);
+                       else {
+                               vert_face_neighbor_midpoints_average(&data,pr_lvl,cr_deltas,sizeof(vec3f),i);
+                               vert_edge_neighbor_midpoints_average(&data,pr_lvl,pr_deltas,sizeof(vec3f),i);
+                       }
+                       multi_apply(&cr_deltas[i].x, &data, 3, catmullclark_smooth_vert);
+               }
+
+               /* Apply deltas to vertex locations */
+               for(i=0; (cr_lvl == last_lvl) && (i < cr_lvl->totvert); ++i) {
+                       VecAddf(me->mr->verts[i].co,
+                               me->mr->verts[i].co,
+                               &cr_deltas[i].x);                       
+               }
+
+               multires_free_temp_data(pr_lvl);
+
+               pr_lvl= pr_lvl->next;
+               cr_lvl= cr_lvl->next;
+       }
+       if(pr_deltas) MEM_freeN(pr_deltas);
+       if(cr_deltas) MEM_freeN(cr_deltas);
+
+}
+
+static void multires_update_faces(Mesh *me, EditMesh *em)
+{
+       MultiresLevel *cr_lvl= current_level(me->mr), *pr_lvl= NULL,
+                     *last_lvl= me->mr->levels.last;
+       char *pr_flag_damaged= NULL, *cr_flag_damaged= NULL, *or_flag_damaged= NULL,
+            *pr_mat_damaged= NULL, *cr_mat_damaged= NULL, *or_mat_damaged= NULL, *swap= NULL;
+       EditFace *efa= NULL;
+       unsigned i,j,curf;
+
+       /* Find for each face whether flag/mat has changed */
+       pr_flag_damaged= MEM_callocN(sizeof(char) * last_lvl->totface, "flag_damaged 1");
+       cr_flag_damaged= MEM_callocN(sizeof(char) * last_lvl->totface, "flag_damaged 1");
+       pr_mat_damaged= MEM_callocN(sizeof(char) * last_lvl->totface, "mat_damaged 1");
+       cr_mat_damaged= MEM_callocN(sizeof(char) * last_lvl->totface, "mat_damaged 1");
+       if(em) efa= em->faces.first;
+       for(i=0; i<cr_lvl->totface; ++i) {
+               MultiresFace mftmp;
+               multires_get_face(&mftmp, efa, &me->mface[i]);
+               if(cr_lvl->faces[i].flag != mftmp.flag)
+                       cr_flag_damaged[i]= 1;
+               if(cr_lvl->faces[i].mat_nr != mftmp.mat_nr)
+                       cr_mat_damaged[i]= 1;
+
+               /* Update current level */
+               cr_lvl->faces[i].flag= mftmp.flag;
+               cr_lvl->faces[i].mat_nr= mftmp.mat_nr;
+
+               if(em) efa= efa->next;
+       }
+       or_flag_damaged= MEM_dupallocN(cr_flag_damaged);
+       or_mat_damaged= MEM_dupallocN(cr_mat_damaged);
+
+       /* Update lower levels */
+       cr_lvl= cr_lvl->prev;
+       while(cr_lvl) {
+               swap= pr_flag_damaged;
+               pr_flag_damaged= cr_flag_damaged;
+               cr_flag_damaged= swap;
+
+               swap= pr_mat_damaged;
+               pr_mat_damaged= cr_mat_damaged;
+               cr_mat_damaged= swap;
+
+               curf= 0;
+               for(i=0; i<cr_lvl->totface; ++i) {
+                       const int sides= cr_lvl->faces[i].v[3] ? 4 : 3;
+                       
+                       /* Check damages */
+                       for(j=0; j<sides; ++j, ++curf) {
+                               if(pr_flag_damaged[curf]) {
+                                       cr_lvl->faces[i].flag= cr_lvl->next->faces[curf].flag;
+                                       cr_flag_damaged[i]= 1;
+                               }
+                               if(pr_mat_damaged[curf]) {
+                                       cr_lvl->faces[i].mat_nr= cr_lvl->next->faces[curf].mat_nr;
+                                       cr_mat_damaged[i]= 1;
+                               }
+                       }
+               }
+
+               cr_lvl= cr_lvl->prev;
+       }
+       
+       /* Clear to original damages */
+       if(cr_flag_damaged) MEM_freeN(cr_flag_damaged);
+       if(cr_mat_damaged) MEM_freeN(cr_mat_damaged);
+       cr_flag_damaged= or_flag_damaged;
+       cr_mat_damaged= or_mat_damaged;
+       
+       /* Update higher levels */
+       pr_lvl= current_level(me->mr);
+       cr_lvl= pr_lvl->next;
+       while(cr_lvl) {
+               swap= pr_flag_damaged;
+               pr_flag_damaged= cr_flag_damaged;
+               cr_flag_damaged= swap;
+
+               swap= pr_mat_damaged;
+               pr_mat_damaged= cr_mat_damaged;
+               cr_mat_damaged= swap;
+
+               /* Update faces */
+               for(i=0, curf= 0; i<pr_lvl->totface; ++i) {
+                       const int sides= cr_lvl->prev->faces[i].v[3] ? 4 : 3;
+                       for(j=0; j<sides; ++j, ++curf) {
+                               if(pr_flag_damaged[i]) {
+                                       cr_lvl->faces[curf].flag= pr_lvl->faces[i].flag;
+                                       cr_flag_damaged[curf]= 1;
+                               }
+                               if(pr_mat_damaged[i]) {
+                                       cr_lvl->faces[curf].mat_nr= pr_lvl->faces[i].mat_nr;
+                                       cr_mat_damaged[curf]= 1;
+                               }
+                       }
+               }
+
+               pr_lvl= pr_lvl->next;
+               cr_lvl= cr_lvl->next;
+       }
+
+       if(pr_flag_damaged) MEM_freeN(pr_flag_damaged);
+       if(cr_flag_damaged) MEM_freeN(cr_flag_damaged);
+       if(pr_mat_damaged) MEM_freeN(pr_mat_damaged);
+       if(cr_mat_damaged) MEM_freeN(cr_mat_damaged);
+}
+
+static void multires_update_colors(Mesh *me, EditMesh *em)
+{
+       MultiresLevel *lvl= BLI_findlink(&me->mr->levels,me->mr->current-1);
+       MultiresCol *pr_deltas= NULL, *cr_deltas= NULL;
+       CustomData *src= em ? &em->fdata : &me->fdata;
+       EditFace *efa= NULL;
+       unsigned i,j,curf= 0;
+       
+       if(me->mr->use_col) {
+               /* Calc initial deltas */
+               cr_deltas= MEM_callocN(sizeof(MultiresCol)*lvl->totface*4,"initial color/uv deltas");
+
+               if(em) efa= em->faces.first;
+               for(i=0; i<lvl->totface; ++i) {
+                       MCol *col= em ? CustomData_em_get(src, efa->data, CD_MCOL) : &me->mcol[i*4];
+                       for(j=0; j<4; ++j) {
+                               if(me->mr->use_col) {
+                                       cr_deltas[i*4+j].a= col[j].a - lvl->colfaces[i].col[j].a;
+                                       cr_deltas[i*4+j].r= col[j].r - lvl->colfaces[i].col[j].r;
+                                       cr_deltas[i*4+j].g= col[j].g - lvl->colfaces[i].col[j].g;
+                                       cr_deltas[i*4+j].b= col[j].b - lvl->colfaces[i].col[j].b;
+                               }
+                       }
+                       if(em) efa= efa->next;
+               }
+               
+               /* Update current level */
+               if(em) efa= em->faces.first;
+               for(i=0; i<lvl->totface; ++i) {
+                       MultiresColFace *f= &lvl->colfaces[i];
+
+                       if(me->mr->use_col)
+                               mcol_to_multires(f, em ? CustomData_em_get(src, efa->data, CD_MCOL) : &me->mcol[i*4]);
+                       
+                       if(em) efa= efa->next;
+               }
+               
+               /* Update higher levels */
+               lvl= lvl->next;
+               while(lvl) {
+                       /* Set up new deltas, but keep the ones from the previous level */
+                       if(pr_deltas) MEM_freeN(pr_deltas);
+                       pr_deltas= cr_deltas;
+                       cr_deltas= MEM_callocN(sizeof(MultiresCol)*lvl->totface*4,"color deltas");
+
+                       curf= 0;
+                       for(i=0; i<lvl->prev->totface; ++i) {
+                               const char sides= lvl->prev->faces[i].v[3]?4:3;
+                               MultiresCol cntr;
+                               
+                               /* Find average color of 4 (or 3 for triangle) verts */
+                               multires_col_avg(&cntr,&pr_deltas[i*4],sides);
+                               
+                               for(j=0; j<sides; ++j) {
+                                       multires_col_avg2(&cr_deltas[curf*4],
+                                                         &pr_deltas[i*4+j],
+                                                         &pr_deltas[i*4+(j==0?sides-1:j-1)]);
+                                       cr_deltas[curf*4+1]= pr_deltas[i*4+j];
+                                       multires_col_avg2(&cr_deltas[curf*4+2],
+                                                         &pr_deltas[i*4+j],
+                                                         &pr_deltas[i*4+(j==sides-1?0:j+1)]);
+                                       cr_deltas[curf*4+3]= cntr;
+                                       ++curf;
+                               }
+                       }
+
+                       for(i=0; i<lvl->totface; ++i) {
+                               for(j=0; j<4; ++j) {
+                                       lvl->colfaces[i].col[j].a+= cr_deltas[i*4+j].a;
+                                       lvl->colfaces[i].col[j].r+= cr_deltas[i*4+j].r;
+                                       lvl->colfaces[i].col[j].g+= cr_deltas[i*4+j].g;
+                                       lvl->colfaces[i].col[j].b+= cr_deltas[i*4+j].b;
+                               }
+                       }
+
+                       lvl= lvl->next;
+               }
+               if(pr_deltas) MEM_freeN(pr_deltas);
+               if(cr_deltas) MEM_freeN(cr_deltas);
+               
+               /* Update lower levels */
+               lvl= me->mr->levels.last;
+               lvl= lvl->prev;
+               while(lvl) {
+                       MultiresColFace *nf= lvl->next->colfaces;
+                       for(i=0; i<lvl->totface; ++i) {
+                               MultiresFace *f= &lvl->faces[i];
+                               for(j=0; j<(f->v[3]?4:3); ++j) {
+                                       lvl->colfaces[i].col[j]= nf->col[1];
+                                       ++nf;
+                               }
+                       }
+                       lvl= lvl->prev;
+               }
+       }
+}
+
+void multires_update_levels(Mesh *me, const int render)
+{
+       EditMesh *em= (!render && G.obedit) ? G.editMesh : NULL;
+
+       multires_update_first_level(me, em);
+       multires_update_vertices(me, em);
+       multires_update_faces(me, em);
+       multires_update_colors(me, em);
+}
+
+static void check_colors(Mesh *me)
+{
+       CustomData *src= G.obedit ? &G.editMesh->fdata : &me->fdata;
+       const char col= CustomData_has_layer(src, CD_MCOL);
+
+       /* Check if vertex colors have been deleted or added */
+       if(me->mr->use_col && !col)
+               me->mr->use_col= 0;
+       else if(!me->mr->use_col && col) {
+               me->mr->use_col= 1;
+               multires_load_cols(me);
+       }
+}
+
+static unsigned int find_mid_edge(ListBase *vert_edge_map,
+                                 MultiresLevel *lvl,
+                                 const unsigned int v1,
+                                 const unsigned int v2 )
+{
+       MultiresMapNode *n= vert_edge_map[v1].first;
+       while(n) {
+               if(lvl->edges[n->Index].v[0]==v2 ||
+                  lvl->edges[n->Index].v[1]==v2)
+                       return lvl->edges[n->Index].mid;
+
+               n= n->next;
+       }
+       return -1;
+}
+
+static float clamp_component(const float c)
+{
+       if(c<0) return 0;
+       else if(c>255) return 255;
+       else return c;
+}
+
+void multires_to_mcol(MultiresColFace *f, MCol mcol[4])
+{
+       unsigned char j;
+       for(j=0; j<4; ++j) {
+               mcol->a= clamp_component(f->col[j].a);
+               mcol->r= clamp_component(f->col[j].r);
+               mcol->g= clamp_component(f->col[j].g);
+               mcol->b= clamp_component(f->col[j].b);
+               ++mcol;
+       }
+}
+
+void multires_level_to_mesh(Object *ob, Mesh *me, const int render)
+{
+       MultiresLevel *lvl= BLI_findlink(&me->mr->levels,me->mr->current-1);
+       int i;
+       EditMesh *em= (!render && G.obedit) ? G.editMesh : NULL;
+       
+       if(em)
+               return;
+
+       CustomData_free_layer_active(&me->vdata, CD_MVERT, me->totvert);
+       CustomData_free_layer_active(&me->edata, CD_MEDGE, me->totedge);
+       CustomData_free_layer_active(&me->fdata, CD_MFACE, me->totface);
+       CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert);
+       CustomData_free_layers(&me->fdata, CD_MTFACE, me->totface);
+       CustomData_free_layers(&me->fdata, CD_MCOL, me->totface);
+               
+       me->totvert= lvl->totvert;
+       me->totface= lvl->totface;
+       me->totedge= lvl->totedge;
+
+       CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, me->totvert);
+       CustomData_add_layer(&me->edata, CD_MEDGE, CD_CALLOC, NULL, me->totedge);
+       CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, NULL, me->totface);
+       mesh_update_customdata_pointers(me);
+
+       /* Vertices/Edges/Faces */
+       
+       for(i=0; i<lvl->totvert; ++i) {
+               me->mvert[i]= me->mr->verts[i];
+       }
+       for(i=0; i<lvl->totedge; ++i) {
+               me->medge[i].v1= lvl->edges[i].v[0];
+               me->medge[i].v2= lvl->edges[i].v[1];
+               me->medge[i].flag &= ~ME_HIDE;
+       }
+       for(i=0; i<lvl->totface; ++i) {
+               me->mface[i].v1= lvl->faces[i].v[0];
+               me->mface[i].v2= lvl->faces[i].v[1];
+               me->mface[i].v3= lvl->faces[i].v[2];
+               me->mface[i].v4= lvl->faces[i].v[3];
+               me->mface[i].flag= lvl->faces[i].flag;
+               me->mface[i].flag &= ~ME_HIDE;
+               me->mface[i].mat_nr= lvl->faces[i].mat_nr;
+       }
+       
+       /* Edge flags */
+       if(lvl==me->mr->levels.first) {
+               for(i=0; i<lvl->totedge; ++i) {
+                       me->medge[i].flag= me->mr->edge_flags[i];
+                       me->medge[i].crease= me->mr->edge_creases[i];
+               }
+       } else {
+               MultiresLevel *lvl1= me->mr->levels.first;
+               const int last= lvl1->totedge * pow(2, me->mr->current-1);
+               for(i=0; i<last; ++i) {
+                       const int ndx= i / pow(2, me->mr->current-1);
+                       
+                       me->medge[i].flag= me->mr->edge_flags[ndx];
+                       me->medge[i].crease= me->mr->edge_creases[ndx];
+               }
+       }
+
+       multires_customdata_to_mesh(me, em, lvl, &me->mr->vdata, em ? &em->vdata : &me->vdata, CD_MDEFORMVERT);
+       multires_customdata_to_mesh(me, em, lvl, &me->mr->fdata, em ? &em->fdata : &me->fdata, CD_MTFACE);
+
+       /* Colors */
+       if(me->mr->use_col) {
+               CustomData *src= &me->fdata;
+               
+               if(me->mr->use_col) me->mcol= CustomData_add_layer(src, CD_MCOL, CD_CALLOC, NULL, me->totface);
+               
+               for(i=0; i<lvl->totface; ++i) {
+                       if(me->mr->use_col)
+                               multires_to_mcol(&lvl->colfaces[i], &me->mcol[i*4]);
+               }
+                       
+       }
+       
+       mesh_update_customdata_pointers(me);
+       
+       multires_edge_level_update(ob,me);
+       DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
+       mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL);
+}
+
+void multires_add_level(Object *ob, Mesh *me, const char subdiv_type)
+{
+       int i,j, curf, cure;
+       MultiresLevel *lvl= NULL;
+       MultiApplyData data;
+       MVert *oldverts= NULL;
+       
+       lvl= MEM_callocN(sizeof(MultiresLevel), "multireslevel");
+       if(me->pv) mesh_pmv_off(ob, me);
+
+       check_colors(me);
+       multires_update_levels(me, 0);
+
+       ++me->mr->level_count;
+       BLI_addtail(&me->mr->levels,lvl);
+
+       /* Create vertices
+          =============== */
+       lvl->totvert= lvl->prev->totvert + lvl->prev->totedge + lvl->prev->totface;
+       oldverts= me->mr->verts;
+       me->mr->verts= MEM_callocN(sizeof(MVert)*lvl->totvert, "multitres verts");
+       /* Copy old verts */
+       for(i=0; i<lvl->prev->totvert; ++i)
+               me->mr->verts[i]= oldverts[i];
+       /* Create new edge verts */
+       for(i=0; i<lvl->prev->totedge; ++i) {
+               VecMidf(me->mr->verts[lvl->prev->totvert + i].co,
+                       oldverts[lvl->prev->edges[i].v[0]].co,
+                       oldverts[lvl->prev->edges[i].v[1]].co);
+               lvl->prev->edges[i].mid= lvl->prev->totvert + i;
+       }
+       /* Create new face verts */
+       for(i=0; i<lvl->prev->totface; ++i) {
+               lvl->prev->faces[i].mid= lvl->prev->totvert + lvl->prev->totedge + i;
+       }
+
+       multires_calc_temp_data(lvl->prev);
+
+       /* Create faces
+          ============ */
+       /* Allocate all the new faces (each triangle creates three, and
+          each quad creates four */
+       lvl->totface= 0;
+       for(i=0; i<lvl->prev->totface; ++i)
+               lvl->totface+= lvl->prev->faces[i].v[3] ? 4 : 3;
+       lvl->faces= MEM_callocN(sizeof(MultiresFace)*lvl->totface,"multires faces");
+
+       curf= 0;
+       for(i=0; i<lvl->prev->totface; ++i) {
+               const int max= lvl->prev->faces[i].v[3] ? 3 : 2;
+               
+               for(j=0; j<max+1; ++j) {
+                       lvl->faces[curf].v[0]= find_mid_edge(lvl->prev->vert_edge_map,lvl->prev,
+                                                            lvl->prev->faces[i].v[j],
+                                                            lvl->prev->faces[i].v[j==0?max:j-1]);
+                       lvl->faces[curf].v[1]= lvl->prev->faces[i].v[j];
+                       lvl->faces[curf].v[2]= find_mid_edge(lvl->prev->vert_edge_map,lvl->prev,
+                                                            lvl->prev->faces[i].v[j],
+                                                            lvl->prev->faces[i].v[j==max?0:j+1]);
+                       lvl->faces[curf].v[3]= lvl->prev->totvert + lvl->prev->totedge + i;
+                       lvl->faces[curf].flag= lvl->prev->faces[i].flag;
+                       lvl->faces[curf].mat_nr= lvl->prev->faces[i].mat_nr;
+
+                       ++curf;
+               }
+       }
+
+       /* Create edges
+          ============ */
+       /* Figure out how many edges to allocate */
+       lvl->totedge= lvl->prev->totedge*2;
+       for(i=0; i<lvl->prev->totface; ++i)
+               lvl->totedge+= lvl->prev->faces[i].v[3]?4:3;
+       lvl->edges= MEM_callocN(sizeof(MultiresEdge)*lvl->totedge,"multires edges");
+
+       for(i=0; i<lvl->prev->totedge; ++i) {
+               lvl->edges[i*2].v[0]= lvl->prev->edges[i].v[0];
+               lvl->edges[i*2].v[1]= lvl->prev->edges[i].mid;
+               lvl->edges[i*2+1].v[0]= lvl->prev->edges[i].mid;
+               lvl->edges[i*2+1].v[1]= lvl->prev->edges[i].v[1];
+       }
+       /* Add edges inside of old polygons */
+       curf= 0;
+       cure= lvl->prev->totedge*2;
+       for(i=0; i<lvl->prev->totface; ++i) {
+               for(j=0; j<(lvl->prev->faces[i].v[3]?4:3); ++j) {
+                       lvl->edges[cure].v[0]= lvl->faces[curf].v[2];
+                       lvl->edges[cure].v[1]= lvl->faces[curf].v[3];
+                       ++cure;
+                       ++curf;
+               }
+       }
+
+       /* Smooth vertices
+          =============== */
+       for(i=0; i<lvl->prev->totface; ++i) {
+               const MultiresFace *f= &lvl->prev->faces[i];
+               data.corner1= oldverts[f->v[0]].co;
+               data.corner2= oldverts[f->v[1]].co;
+               data.corner3= oldverts[f->v[2]].co;
+               data.corner4= oldverts[f->v[3]].co;
+               data.quad= f->v[3] ? 1 : 0;
+               multi_apply(me->mr->verts[f->mid].co, &data, 3, catmullclark_smooth_face);
+       }
+
+       if(subdiv_type == 0) {
+               for(i=0; i<lvl->prev->totedge; ++i) {
+                       const MultiresEdge *e= &lvl->prev->edges[i];
+                       data.boundary= lvl->prev->edge_boundary_states[i];
+                       edge_face_neighbor_midpoints_accum(&data,lvl->prev, me->mr->verts, sizeof(MVert),e);
+                       data.endpoint1= oldverts[e->v[0]].co;
+                       data.endpoint2= oldverts[e->v[1]].co;
+                       multi_apply(me->mr->verts[e->mid].co, &data, 3, catmullclark_smooth_edge);
+               }
+               
+               for(i=0; i<lvl->prev->totvert; ++i) {
+                       data.boundary= multires_vert_is_boundary(lvl->prev,i);
+                       data.original= oldverts[i].co;
+                       data.edge_count= BLI_countlist(&lvl->prev->vert_edge_map[i]);
+                       if(data.boundary)
+                               boundary_edges_average(&data,lvl->prev, oldverts, sizeof(MVert),i);
+                       else {
+                               vert_face_neighbor_midpoints_average(&data,lvl->prev, me->mr->verts,
+                                                                    sizeof(MVert),i);
+                               vert_edge_neighbor_midpoints_average(&data,lvl->prev, oldverts,
+                                                                    sizeof(MVert),i);
+                       }
+                       multi_apply(me->mr->verts[i].co, &data, 3, catmullclark_smooth_vert);
+               }
+       }
+
+       multires_free_temp_data(lvl->prev);
+       MEM_freeN(oldverts);
+
+       /* Vertex Colors
+          ============= */
+       curf= 0;
+       if(me->mr->use_col) {
+               MultiresColFace *cf= MEM_callocN(sizeof(MultiresColFace)*lvl->totface,"Multirescolfaces");
+               lvl->colfaces= cf;
+               for(i=0; i<lvl->prev->totface; ++i) {
+                       const char sides= lvl->prev->faces[i].v[3]?4:3;
+                       MultiresCol cntr;
+
+                       /* Find average color of 4 (or 3 for triangle) verts */
+                       multires_col_avg(&cntr,lvl->prev->colfaces[i].col,sides);
+
+                       for(j=0; j<sides; ++j) {
+                               multires_col_avg2(&cf->col[0],
+                                                 &lvl->prev->colfaces[i].col[j],
+                                                 &lvl->prev->colfaces[i].col[j==0?sides-1:j-1]);
+                               cf->col[1]= lvl->prev->colfaces[i].col[j];
+                               multires_col_avg2(&cf->col[2],
+                                                 &lvl->prev->colfaces[i].col[j],
+                                                 &lvl->prev->colfaces[i].col[j==sides-1?0:j+1]);
+                               cf->col[3]= cntr;
+
+                               ++cf;
+                       }
+               }
+       }
+
+       me->mr->newlvl= me->mr->level_count;
+       me->mr->current= me->mr->newlvl;
+       /* Unless the render level has been set to something other than the
+          highest level (by the user), increment the render level to match
+          the highest available level */
+       if(me->mr->renderlvl == me->mr->level_count - 1) me->mr->renderlvl= me->mr->level_count;
+
+       multires_level_to_mesh(ob, me, 0);
+}
+
+void multires_set_level(Object *ob, Mesh *me, const int render)
+{
+       if(me->pv) mesh_pmv_off(ob, me);
+
+       check_colors(me);
+       multires_update_levels(me, render);
+
+       me->mr->current= me->mr->newlvl;
+       if(me->mr->current<1) me->mr->current= 1;
+       else if(me->mr->current>me->mr->level_count) me->mr->current= me->mr->level_count;
+
+       multires_level_to_mesh(ob, me, render);
+}
+
+/* Update the edge visibility flags to only show edges on or below the edgelvl */
+void multires_edge_level_update(Object *ob, Mesh *me)
+{
+       if(!G.obedit) {
+               MultiresLevel *cr_lvl= BLI_findlink(&me->mr->levels,me->mr->current-1);
+               MultiresLevel *edge_lvl= BLI_findlink(&me->mr->levels,me->mr->edgelvl-1);
+               const int threshold= edge_lvl->totedge * powf(2, me->mr->current - me->mr->edgelvl);
+               unsigned i;
+
+               for(i=0; i<cr_lvl->totedge; ++i) {
+                       const int ndx= me->pv ? me->pv->edge_map[i] : i;
+                       if(ndx != -1) { /* -1= hidden edge */
+                               if(me->mr->edgelvl >= me->mr->current || i<threshold)
+                                       me->medge[ndx].flag |= ME_EDGEDRAW | ME_EDGERENDER;
+                               else
+                                       me->medge[ndx].flag &= ~ME_EDGEDRAW & ~ME_EDGERENDER;
+                       }
+               }
+               
+               DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
+       }
+}
index 651115b7180bda22f078b7a70a411f04b452ef83..ce14165a499199f409627c9716138ec2e3398f18 100644 (file)
@@ -483,6 +483,20 @@ bNode *nodeMakeGroupFromSelected(bNodeTree *ntree)
                        BLI_addtail(&ngroup->nodes, node);
                        node->locx-= 0.5f*(min[0]+max[0]);
                        node->locy-= 0.5f*(min[1]+max[1]);
+
+                       /* set selin and selout of the nodetree */
+                       for(sock= node->inputs.first; sock; sock= sock->next) {
+                               if(sock->flag & SOCK_SEL) {
+                                       ngroup->selin= sock;
+                                       break;
+                               }
+                       }
+                       for(sock= node->outputs.first; sock; sock= sock->next) {
+                               if(sock->flag & SOCK_SEL) {
+                                       ngroup->selout= sock;
+                                       break;
+                               }
+                       }
                }
        }
 
@@ -653,7 +667,8 @@ void nodeGroupSocketUseFlags(bNodeTree *ngroup)
        }
 }
 
-static void find_node_with_socket(bNodeTree *ntree, bNodeSocket *sock, bNode **nodep, int *sockindex)
+/* finds a node based on given socket */
+int nodeFindNode(bNodeTree *ntree, bNodeSocket *sock, bNode **nodep, int *sockindex)
 {
        bNode *node;
        bNodeSocket *tsock;
@@ -671,13 +686,15 @@ static void find_node_with_socket(bNodeTree *ntree, bNodeSocket *sock, bNode **n
                if(tsock)
                        break;
        }
+
        if(node) {
                *nodep= node;
-               *sockindex= index;
-       }
-       else {
-               *nodep= NULL;
+               if(sockindex) *sockindex= index;
+               return 1;
        }
+       
+       *nodep= NULL;
+       return 0;
 }
 
 /* returns 1 if its OK */
@@ -717,7 +734,7 @@ int nodeGroupUnGroup(bNodeTree *ntree, bNode *gnode)
        for(link= ntree->links.first; link; link= link->next) {
                if(link->tonode==gnode) {
                        /* link->tosock->tosock is on the node we look for */
-                       find_node_with_socket(ngroup, link->tosock->tosock, &nextn, &index);
+                       nodeFindNode(ngroup, link->tosock->tosock, &nextn, &index);
                        if(nextn==NULL) printf("wrong stuff!\n");
                        else if(nextn->new_node==NULL) printf("wrong stuff too!\n");
                        else {
@@ -727,7 +744,7 @@ int nodeGroupUnGroup(bNodeTree *ntree, bNode *gnode)
                }
                else if(link->fromnode==gnode) {
                        /* link->fromsock->tosock is on the node we look for */
-                       find_node_with_socket(ngroup, link->fromsock->tosock, &nextn, &index);
+                       nodeFindNode(ngroup, link->fromsock->tosock, &nextn, &index);
                        if(nextn==NULL) printf("1 wrong stuff!\n");
                        else if(nextn->new_node==NULL) printf("1 wrong stuff too!\n");
                        else {
@@ -898,6 +915,28 @@ bNodeTree *ntreeCopyTree(bNodeTree *ntree, int internal_select)
                                nnode->flag |= NODE_SELECT;
                        }
                        node->flag &= ~NODE_ACTIVE;
+
+                       /* deselect original sockets */
+                       for(sock= node->inputs.first; sock; sock= sock->next) {
+                               if(sock->flag & SOCK_SEL) sock->flag&= ~SOCK_SEL;
+                       }
+                       for(sock= node->outputs.first; sock; sock= sock->next) {
+                               if(sock->flag & SOCK_SEL) sock->flag&= ~SOCK_SEL;
+                       }
+                       
+                       /* set tree selin and selout to new sockets */
+                       for(sock= nnode->inputs.first; sock; sock= sock->next) {
+                               if(sock->flag & SOCK_SEL) {
+                                       ntree->selin= sock;
+                                       break;
+                               }
+                       }
+                       for(sock= nnode->outputs.first; sock; sock= sock->next) {
+                               if(sock->flag & SOCK_SEL) {
+                                       ntree->selout= sock;
+                                       break;
+                               }
+                       }
                }
                if(node==last) break;
        }
@@ -941,7 +980,7 @@ bNodeTree *ntreeCopyTree(bNodeTree *ntree, int internal_select)
 /* ************** Free stuff ********** */
 
 /* goes over entire tree */
-static void node_unlink_node(bNodeTree *ntree, bNode *node)
+void nodeUnlinkNode(bNodeTree *ntree, bNode *node)
 {
        bNodeLink *link, *next;
        bNodeSocket *sock;
@@ -985,7 +1024,7 @@ static void composit_free_node_cache(bNode *node)
 
 void nodeFreeNode(bNodeTree *ntree, bNode *node)
 {
-       node_unlink_node(ntree, node);
+       nodeUnlinkNode(ntree, node);
        BLI_remlink(&ntree->nodes, node);
 
        /* since it is called while free database, node->id is undefined */
@@ -2335,6 +2374,8 @@ static void registerCompositNodes(ListBase *ntypelist)
        
        nodeRegisterType(ntypelist, &cmp_node_filter);
        nodeRegisterType(ntypelist, &cmp_node_blur);
+       nodeRegisterType(ntypelist, &cmp_node_dblur);
+       nodeRegisterType(ntypelist, &cmp_node_bilateralblur);
        nodeRegisterType(ntypelist, &cmp_node_vecblur);
        nodeRegisterType(ntypelist, &cmp_node_dilateerode);
        nodeRegisterType(ntypelist, &cmp_node_defocus);
index d48be54fe10cc38c55ca09c16b013508eeeb12fd..54d090ddb225c4c46aefc74fe7727d00ba5b86a5 100644 (file)
@@ -225,6 +225,7 @@ void free_object(Object *ob)
        ob->path= 0;
        if(ob->ipo) ob->ipo->id.us--;
        if(ob->action) ob->action->id.us--;
+       if(ob->poselib) ob->poselib->id.us--;
        if(ob->dup_group) ob->dup_group->id.us--;
        if(ob->defbase.first)
                BLI_freelistN(&ob->defbase);
index 85ac809bf700a77b2448a04971e6dfd3b1de8230..82b2d785c8ce0e246a767575e6c01e0d68cf9aec 100644 (file)
@@ -257,8 +257,8 @@ int psys_check_enabled(Object *ob, ParticleSystem *psys)
                return 0;
 
        psmd= psys_get_modifier(ob, psys);
-       if(G.rendering) {
-               if(!psys->renderdata || !(psmd->modifier.mode & eModifierMode_Render))
+       if(psys->renderdata) {
+               if(!(psmd->modifier.mode & eModifierMode_Render))
                        return 0;
        }
        else if(!(psmd->modifier.mode & eModifierMode_Realtime))
@@ -295,7 +295,6 @@ void free_keyed_keys(ParticleSystem *psys)
 }
 void free_child_path_cache(ParticleSystem *psys)
 {
-
        if(psys->childcache){
                if(psys->childcache[0])
                        MEM_freeN(psys->childcache[0]);
@@ -363,28 +362,98 @@ void psys_free(Object *ob, ParticleSystem * psys)
        }
 }
 
-/* these two functions move away particle data and bring it back after
+/* these functions move away particle data and bring it back after
  * rendering, to make different render settings possible without
  * removing the previous data. this should be solved properly once */
 
-typedef struct ParticleRenderDataup {
+typedef struct ParticleRenderElem {
+       int curchild, totchild;
+       float lambda, t, scalemin, scalemax;
+} ParticleRenderElem;
+
+typedef struct ParticleRenderData {
        ChildParticle *child;
        ParticleCacheKey **pathcache;
        ParticleCacheKey **childcache;
        int totchild, totcached, totchildcache;
        DerivedMesh *dm;
        int totdmvert, totdmedge, totdmface;
-} ParticleRenderDataup;
 
-void psys_particles_to_render_backup(Object *ob, ParticleSystem *psys)
+       float mat[4][4];
+       float viewmat[4][4], winmat[4][4];
+       int winx, winy;
+
+       int dosimplify;
+       ParticleRenderElem *elems;
+       int *origindex;
+} ParticleRenderData;
+
+static float psys_render_viewport_falloff(double rate, float dist, float width)
+{
+       return pow(rate, dist/width);
+}
+
+static float psys_render_projected_area(ParticleSystem *psys, float *center, float area, double vprate, float *viewport)
+{
+       ParticleRenderData *data= psys->renderdata;
+       float co[3], view[3], ortho1[3], ortho2[2], w, dx, dy, radius;
+       
+       /* transform to view space */
+       VECCOPY(co, center);
+       co[3]= 1.0f;
+       Mat4MulVec4fl(data->viewmat, co);
+       
+       /* compute two vectors orthogonal to view vector */
+       VECCOPY(view, co);
+       Normalize(view);
+       VecOrthoBasisf(view, ortho1, ortho2);
+
+       /* compute on screen minification */
+       w= co[2]*data->winmat[2][3] + data->winmat[3][3];
+       dx= data->winx*ortho2[0]*data->winmat[0][0];
+       dy= data->winy*ortho2[1]*data->winmat[1][1];
+       w= sqrt(dx*dx + dy*dy)/w;
+
+       /* w squared because we are working with area */
+       area= area*w*w;
+
+       /* viewport of the screen test */
+
+       /* project point on screen */
+       Mat4MulVec4fl(data->winmat, co);
+       if(co[3] != 0.0f) {
+               co[0]= 0.5f*data->winx*(1.0f + co[0]/co[3]);
+               co[1]= 0.5f*data->winy*(1.0f + co[1]/co[3]);
+       }
+
+       /* screen space radius */
+       radius= sqrt(area/M_PI);
+
+       /* make smaller using fallof once over screen edge */
+       *viewport= 1.0f;
+
+       if(co[0]+radius < 0.0f)
+               *viewport *= psys_render_viewport_falloff(vprate, -(co[0]+radius), data->winx);
+       else if(co[0]-radius > data->winx)
+               *viewport *= psys_render_viewport_falloff(vprate, (co[0]-radius) - data->winx, data->winx);
+
+       if(co[1]+radius < 0.0f)
+               *viewport *= psys_render_viewport_falloff(vprate, -(co[1]+radius), data->winy);
+       else if(co[1]-radius > data->winy)
+               *viewport *= psys_render_viewport_falloff(vprate, (co[1]-radius) - data->winy, data->winy);
+       
+       return area;
+}
+
+void psys_render_set(Object *ob, ParticleSystem *psys, float viewmat[][4], float winmat[][4], int winx, int winy)
 {
-       ParticleRenderDataup *data;
+       ParticleRenderData*data;
        ParticleSystemModifierData *psmd= psys_get_modifier(ob, psys);
 
        if(!G.rendering)
                return;
 
-       data= MEM_callocN(sizeof(ParticleRenderDataup), "ParticleRenderDataup");
+       data= MEM_callocN(sizeof(ParticleRenderData), "ParticleRenderData");
 
        data->child= psys->child;
        data->totchild= psys->totchild;
@@ -404,17 +473,26 @@ void psys_particles_to_render_backup(Object *ob, ParticleSystem *psys)
        psys->childcache= NULL;
        psys->totchild= psys->totcached= psys->totchildcache= 0;
 
+       Mat4CpyMat4(data->winmat, winmat);
+       Mat4MulMat4(data->viewmat, ob->obmat, viewmat);
+       Mat4MulMat4(data->mat, data->viewmat, winmat);
+       data->winx= winx;
+       data->winy= winy;
+
        psys->renderdata= data;
 }
 
-void psys_render_backup_to_particles(Object *ob, ParticleSystem *psys)
+void psys_render_restore(Object *ob, ParticleSystem *psys)
 {
-       ParticleRenderDataup *data;
+       ParticleRenderData*data;
        ParticleSystemModifierData *psmd= psys_get_modifier(ob, psys);
 
        data= psys->renderdata;
        if(!data)
                return;
+       
+       if(data->elems)
+               MEM_freeN(data->elems);
 
        if(psmd->dm) {
                psmd->dm->needsFree= 1;
@@ -428,7 +506,7 @@ void psys_render_backup_to_particles(Object *ob, ParticleSystem *psys)
                psys->child= 0;
                psys->totchild= 0;
        }
-       
+
        psys->child= data->child;
        psys->totchild= data->totchild;
        psys->pathcache= data->pathcache;
@@ -449,6 +527,211 @@ void psys_render_backup_to_particles(Object *ob, ParticleSystem *psys)
        psys->renderdata= NULL;
 }
 
+int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot)
+{
+       DerivedMesh *dm= ctx->dm;
+       Mesh *me= (Mesh*)(ctx->ob->data);
+       MFace *mf, *mface;
+       MVert *mvert;
+       ParticleRenderData *data;
+       ParticleRenderElem *elems, *elem;
+       ParticleSettings *part= ctx->psys->part;
+       float *facearea, (*facecenter)[3], size[3], fac, powrate;
+       float co1[3], co2[3], co3[3], co4[3], lambda, arearatio, t, area, viewport;
+       double vprate;
+       int *origindex, *facetotvert;
+       int a, b, totorigface, totface, newtot, skipped;
+
+       if(part->draw_as!=PART_DRAW_PATH || !(part->draw & PART_DRAW_REN_STRAND))
+               return tot;
+       if(!ctx->psys->renderdata || !(part->simplify_flag & PART_SIMPLIFY_ENABLE))
+               return tot;
+
+       mvert= dm->getVertArray(dm);
+       mface= dm->getFaceArray(dm);
+       origindex= dm->getFaceDataArray(dm, CD_ORIGINDEX);
+       totface= dm->getNumFaces(dm);
+       totorigface= me->totface;
+
+       if(totface == 0 || totorigface == 0 || origindex == NULL)
+               return tot;
+
+       facearea= MEM_callocN(sizeof(float)*totorigface, "SimplifyFaceArea");
+       facecenter= MEM_callocN(sizeof(float[3])*totorigface, "SimplifyFaceCenter");
+       facetotvert= MEM_callocN(sizeof(int)*totorigface, "SimplifyFaceArea");
+       elems= MEM_callocN(sizeof(ParticleRenderElem)*totorigface, "SimplifyFaceElem");
+
+       data= ctx->psys->renderdata;
+       data->dosimplify= 1;
+       data->elems= elems;
+       data->origindex= origindex;
+
+       /* compute number of children per original face */
+       for(a=0; a<tot; a++) {
+               b= origindex[ctx->index[a]];
+               if(b != -1)
+                       elems[b].totchild++;
+       }
+
+       /* compute areas and centers of original faces */
+       for(mf=mface, a=0; a<totface; a++, mf++) {
+               b= origindex[a];
+
+               if(b != -1) {
+                       VECCOPY(co1, mvert[mf->v1].co);
+                       VECCOPY(co2, mvert[mf->v2].co);
+                       VECCOPY(co3, mvert[mf->v3].co);
+
+                       VECADD(facecenter[b], facecenter[b], co1);
+                       VECADD(facecenter[b], facecenter[b], co2);
+                       VECADD(facecenter[b], facecenter[b], co3);
+
+                       if(mf->v4) {
+                               VECCOPY(co4, mvert[mf->v4].co);
+                               VECADD(facecenter[b], facecenter[b], co4);
+                               facearea[b] += AreaQ3Dfl(co1, co2, co3, co4);
+                               facetotvert[b] += 4;
+                       }
+                       else {
+                               facearea[b] += AreaT3Dfl(co1, co2, co3);
+                               facetotvert[b] += 3;
+                       }
+               }
+       }
+
+       for(a=0; a<totorigface; a++)
+               if(facetotvert[a] > 0)
+                       VecMulf(facecenter[a], 1.0f/facetotvert[a]);
+
+       /* for conversion from BU area / pixel area to reference screen size */
+       mesh_get_texspace(me, 0, 0, size);
+       fac= ((size[0] + size[1] + size[2])/3.0f)/part->simplify_refsize;
+       fac= fac*fac;
+
+       powrate= log(0.5f)/log(part->simplify_rate*0.5f);
+       if(part->simplify_flag & PART_SIMPLIFY_VIEWPORT)
+               vprate= pow(1.0 - part->simplify_viewport, 5.0);
+       else
+               vprate= 1.0;
+
+       /* set simplification parameters per original face */
+       for(a=0, elem=elems; a<totorigface; a++, elem++) {
+               area = psys_render_projected_area(ctx->psys, facecenter[a], facearea[a], vprate, &viewport);
+               arearatio= fac*area/facearea[a];
+
+               if(arearatio < 1.0f || viewport < 1.0f) {
+                       /* lambda is percentage of elements to keep */
+                       lambda= (arearatio < 1.0f)? pow(arearatio, powrate): 1.0f;
+                       lambda *= viewport;
+
+                       /* compute transition region */
+                       t= part->simplify_transition;
+                       elem->t= (lambda-t < 0.0f)? lambda: (lambda+t > 1.0f)? 1.0f-lambda: t;
+
+                       /* scale at end and beginning of the transition region */
+                       elem->scalemax= (lambda+t < 1.0f)? 1.0f/lambda: 1.0f/(1.0f - elem->t*elem->t/t);
+                       elem->scalemin= (lambda+t < 1.0f)? 0.0f: elem->scalemax*(1.0f-elem->t/t);
+
+                       /* extend lambda to include transition */
+                       lambda= lambda + elem->t;
+                       if(lambda > 1.0f)
+                               lambda= 1.0f;
+               }
+               else {
+                       lambda= arearatio;
+
+                       elem->scalemax= 1.0f; //sqrt(lambda);
+                       elem->scalemin= 1.0f; //sqrt(lambda);
+               }
+
+               elem->lambda= lambda;
+               elem->scalemin= sqrt(elem->scalemin);
+               elem->scalemax= sqrt(elem->scalemax);
+               elem->curchild= 0;
+       }
+
+       MEM_freeN(facearea);
+       MEM_freeN(facecenter);
+       MEM_freeN(facetotvert);
+
+       /* move indices and set random number skipping */
+       ctx->skip= MEM_callocN(sizeof(int)*tot, "SimplificationSkip");
+
+       skipped= 0;
+       for(a=0, newtot=0; a<tot; a++) {
+               b= origindex[ctx->index[a]];
+               if(b != -1) {
+                       if(elems[b].curchild++ < ceil(elems[b].lambda*elems[b].totchild)) {
+                               ctx->index[newtot]= ctx->index[a];
+                               ctx->skip[newtot]= skipped;
+                               skipped= 0;
+                               newtot++;
+                       }
+                       else skipped++;
+               }
+               else skipped++;
+       }
+
+       for(a=0, elem=elems; a<totorigface; a++, elem++)
+               elem->curchild= 0;
+
+       return newtot;
+}
+
+int psys_render_simplify_params(ParticleSystem *psys, ChildParticle *cpa, float *params)
+{
+       ParticleRenderData *data;
+       ParticleRenderElem *elem;
+       float x, w, scale, alpha, lambda, t, scalemin, scalemax;
+       int b;
+
+       if(!(psys->renderdata && (psys->part->simplify_flag & PART_SIMPLIFY_ENABLE)))
+               return 0;
+       
+       data= psys->renderdata;
+       if(!data->dosimplify)
+               return 0;
+       
+       b= data->origindex[cpa->num];
+       if(b == -1)
+               return 0;
+
+       elem= &data->elems[b];
+
+       lambda= elem->lambda;
+       t= elem->t;
+       scalemin= elem->scalemin;
+       scalemax= elem->scalemax;
+
+       if(lambda >= 1.0f) {
+               scale= scalemin;
+               alpha= 1.0f;
+       }
+       else {
+               x= (elem->curchild+0.5f)/elem->totchild;
+               if(x < lambda-t) {
+                       scale= scalemax;
+                       alpha= 1.0f;
+               }
+               else if(x >= lambda+t) {
+                       scale= scalemin;
+                       alpha= 0.0f;
+               }
+               else {
+                       w= (lambda+t - x)/(2.0f*t);
+                       scale= scalemin + (scalemax - scalemin)*w;
+                       alpha= w;
+               }
+       }
+
+       params[0]= scale;
+       params[1]= alpha;
+
+       elem->curchild++;
+
+       return 1;
+}
+
 /************************************************/
 /*                     Interpolated Particles                          */
 /************************************************/
@@ -2512,7 +2795,6 @@ static void default_particle_settings(ParticleSettings *part)
        part->disp=100;
        part->from= PART_FROM_FACE;
        part->length= 1.0;
-       part->rotfac= 1.0;
        part->nbetween= 4;
        part->boidneighbours= 5;
 
@@ -2550,6 +2832,11 @@ static void default_particle_settings(ParticleSettings *part)
        }
 
        part->ipo = NULL;
+
+       part->simplify_refsize= 1920;
+       part->simplify_rate= 1.0f;
+       part->simplify_transition= 0.1f;
+       part->simplify_viewport= 0.8;
 }
 
 
index af1db36b648a20b75ce60c46e8bc8e84b3e41a67..ac06f75737ff714f014a3eab2968997272c22364 100644 (file)
@@ -105,13 +105,13 @@ static int get_current_display_percentage(ParticleSystem *psys)
                return psys->part->disp;
 }
 
-static void alloc_particles(ParticleSystem *psys, int new_totpart)
+static void alloc_particles(Object *ob, ParticleSystem *psys, int new_totpart)
 {
        ParticleData *newpars = 0, *pa;
-       int i, child_nbr, totpart, totsaved = 0;
+       int i, totpart, totsaved = 0;
 
-       if(new_totpart<0){
-               if(psys->part->distr==PART_DISTR_GRID){
+       if(new_totpart<0) {
+               if(psys->part->distr==PART_DISTR_GRID) {
                        totpart= psys->part->grid_res;
                        totpart*=totpart*totpart;
                }
@@ -123,7 +123,7 @@ static void alloc_particles(ParticleSystem *psys, int new_totpart)
 
        if(totpart)
                newpars= MEM_callocN(totpart*sizeof(ParticleData), "particles");
-       if(psys->particles){
+       if(psys->particles) {
                totsaved=MIN2(psys->totpart,totpart);
                /*save old pars*/
                if(totsaved)
@@ -136,16 +136,7 @@ static void alloc_particles(ParticleSystem *psys, int new_totpart)
        }
        psys->particles=newpars;
 
-       child_nbr= (psys->renderdata)? psys->part->ren_child_nbr: psys->part->child_nbr;
-       if(child_nbr && psys->part->childtype){
-               if(psys->child)
-                       MEM_freeN(psys->child);
-               psys->child = NULL;
-               if(totpart)
-                       psys->child= MEM_callocN(totpart*child_nbr*sizeof(ChildParticle), "child_particles");
-               psys->totchild=totpart*child_nbr;
-       }
-       else if(psys->child){
+       if(psys->child) {
                MEM_freeN(psys->child);
                psys->child=0;
                psys->totchild=0;
@@ -154,6 +145,32 @@ static void alloc_particles(ParticleSystem *psys, int new_totpart)
        psys->totpart=totpart;
 }
 
+static int get_alloc_child_particles_tot(ParticleSystem *psys)
+{
+       int child_nbr;
+
+       if(!psys->part->childtype)
+               return 0;
+
+       child_nbr= (psys->renderdata)? psys->part->ren_child_nbr: psys->part->child_nbr;
+       return psys->totpart*child_nbr;
+}
+
+static void alloc_child_particles(ParticleSystem *psys, int tot)
+{
+       if(psys->child){
+               MEM_freeN(psys->child);
+               psys->child=0;
+               psys->totchild=0;
+       }
+
+       if(psys->part->childtype) {
+               psys->totchild= tot;
+               if(psys->totchild)
+                       psys->child= MEM_callocN(psys->totchild*sizeof(ChildParticle), "child_particles");
+       }
+}
+
 /* only run this if from == PART_FROM_FACE */
 void psys_calc_dmfaces(Object *ob, DerivedMesh *dm, ParticleSystem *psys)
 {
@@ -607,7 +624,7 @@ void psys_thread_distribute_particle(ParticleThread *thread, ParticleData *pa, C
                }
 
                mf= dm->getFaceData(dm, ctx->index[p], CD_MFACE);
-               
+
                //switch(distr){
                //      case PART_DISTR_JIT:
                //              i=index[p];
@@ -741,12 +758,16 @@ void *exec_distribution(void *data)
 
        if(thread->ctx->from == PART_FROM_CHILD) {
                totpart= psys->totchild;
-               cpa= psys->child + thread->num;
+               cpa= psys->child;
 
-               rng_skip(thread->rng, 5*thread->num);
-               for(p=thread->num; p<totpart; p+=thread->tot, cpa+=thread->tot) {
-                       psys_thread_distribute_particle(thread, NULL, cpa, p);
-                       rng_skip(thread->rng, 5*(thread->tot-1));
+               for(p=0; p<totpart; p++, cpa++) {
+                       if(thread->ctx->skip) /* simplification skip */
+                               rng_skip(thread->rng, 5*thread->ctx->skip[p]);
+
+                       if((p+thread->num) % thread->tot == 0)
+                               psys_thread_distribute_particle(thread, NULL, cpa, p);
+                       else /* thread skip */
+                               rng_skip(thread->rng, 5);
                }
        }
        else {
@@ -757,7 +778,7 @@ void *exec_distribution(void *data)
        }
 
        return 0;
-}      
+}
 
 /* creates a distribution of coordinates on a DerivedMesh      */
 /*                                                                                                                     */
@@ -813,7 +834,6 @@ int psys_threads_init_distribution(ParticleThread *threads, DerivedMesh *finaldm
        
        if(from==PART_FROM_CHILD){
                distr=PART_DISTR_RAND;
-               cpa=psys->child;
                if(part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES){
                        dm= finaldm;
                        children=1;
@@ -828,7 +848,7 @@ int psys_threads_init_distribution(ParticleThread *threads, DerivedMesh *finaldm
 
                        BLI_kdtree_balance(tree);
 
-                       totpart=psys->totchild;
+                       totpart=get_alloc_child_particles_tot(psys);
                        cfrom=from=PART_FROM_FACE;
 
                        if(part->flag&PART_CHILD_SEAMS){
@@ -879,6 +899,9 @@ int psys_threads_init_distribution(ParticleThread *threads, DerivedMesh *finaldm
                        /* no need to figure out distribution */
                        int child_nbr= (psys->renderdata)? part->ren_child_nbr: part->child_nbr;
 
+                       totpart= get_alloc_child_particles_tot(psys);
+                       alloc_child_particles(psys, totpart);
+                       cpa=psys->child;
                        for(i=0; i<child_nbr; i++){
                                for(p=0; p<psys->totpart; p++,cpa++){
                                        float length=2.0;
@@ -1100,8 +1123,8 @@ int psys_threads_init_distribution(ParticleThread *threads, DerivedMesh *finaldm
        sum[0]= 0.0f;
        for(i=0;i<tot; i++)
                sum[i+1]= sum[i]+weight[i]*totweight;
-
-       if(part->flag&PART_TRAND){
+       
+       if((part->flag&PART_TRAND) || (part->simplify_flag&PART_SIMPLIFY_ENABLE)) {
                float pos;
 
                for(p=0; p<totpart; p++) {
@@ -1156,9 +1179,6 @@ int psys_threads_init_distribution(ParticleThread *threads, DerivedMesh *finaldm
        }
 
        /* 5. */
-       if(children)
-               from=PART_FROM_CHILD;
-
        ctx->tree= tree;
        ctx->seams= seams;
        ctx->totseam= totseam;
@@ -1169,17 +1189,21 @@ int psys_threads_init_distribution(ParticleThread *threads, DerivedMesh *finaldm
        ctx->jitoff= jitoff;
        ctx->weight= weight;
        ctx->maxweight= maxweight;
-       ctx->from= from;
+       ctx->from= (children)? PART_FROM_CHILD: from;
        ctx->cfrom= cfrom;
        ctx->distr= distr;
        ctx->dm= dm;
        ctx->tpars= tpars;
 
-       seed= 31415926 + ctx->psys->seed;
+       if(children) {
+               totpart= psys_render_simplify_distribution(ctx, totpart);
+               alloc_child_particles(psys, totpart);
+       }
 
-       if(from!=PART_FROM_CHILD || psys->totchild < 10000)
+       if(!children || psys->totchild < 10000)
                totthread= 1;
        
+       seed= 31415926 + ctx->psys->seed;
        for(i=0; i<totthread; i++) {
                threads[i].rng= rng_new(seed);
                threads[i].tot= totthread;
@@ -1323,6 +1347,7 @@ void psys_threads_free(ParticleThread *threads)
        if(ctx->jitoff) MEM_freeN(ctx->jitoff);
        if(ctx->weight) MEM_freeN(ctx->weight);
        if(ctx->index) MEM_freeN(ctx->index);
+       if(ctx->skip) MEM_freeN(ctx->skip);
        if(ctx->seams) MEM_freeN(ctx->seams);
        //if(ctx->vertpart) MEM_freeN(ctx->vertpart);
        BLI_kdtree_free(ctx->tree);
@@ -1508,10 +1533,9 @@ void reset_particle(ParticleData *pa, ParticleSystem *psys, ParticleSystemModifi
        ParticleTexture ptex;
        ParticleKey state;
        IpoCurve *icu=0;
-       float fac, nor[3]={0,0,0},loc[3],tloc[3],vel[3]={0.0,0.0,0.0},rot[4],*q2=0;
+       float fac, rotfac, phasefac, nor[3]={0,0,0},loc[3],tloc[3],vel[3]={0.0,0.0,0.0},rot[4],*q2=0;
        float r_vel[3],r_ave[3],r_rot[4],p_vel[3]={0.0,0.0,0.0};
-       float x_vec[3]={1.0,0.0,0.0}, utan[3]={0.0,1.0,0.0}, vtan[3]={0.0,0.0,1.0};
-
+       float x_vec[3]={1.0,0.0,0.0}, utan[3]={0.0,1.0,0.0}, vtan[3]={0.0,0.0,1.0}, rot_vec[3]={0.0,0.0,0.0};
        float q_one[4]={1.0,0.0,0.0,0.0}, q_phase[4];
        part=psys->part;
 
@@ -1612,7 +1636,7 @@ void reset_particle(ParticleData *pa, ParticleSystem *psys, ParticleSystemModifi
                }
                
                /* -rotation                                                    */
-               if(part->rotmode==PART_ROT_RAND){
+               if(part->randrotfac != 0.0f){
                        QUATCOPY(r_rot,pa->r_rot);
                        Mat4ToQuat(ob->obmat,rot);
                        QuatMul(r_rot,r_rot,rot);
@@ -1663,34 +1687,49 @@ void reset_particle(ParticleData *pa, ParticleSystem *psys, ParticleSystemModifi
        pa->state.rot[1]=pa->state.rot[2]=pa->state.rot[3]=0.0;
 
        if(part->rotmode){
+               /* create vector into which rotation is aligned */
                switch(part->rotmode){
                        case PART_ROT_NOR:
-                               VecMulf(nor,-1.0);
-                               q2= vectoquat(nor, OB_POSX, OB_POSZ);
-                               VecMulf(nor,-1.0);
+                               VecCopyf(rot_vec, nor);
                                break;
                        case PART_ROT_VEL:
-                               VecMulf(vel,-1.0);
-                               q2= vectoquat(vel, OB_POSX, OB_POSZ);
-                               VecMulf(vel,-1.0);
+                               VecCopyf(rot_vec, vel);
+                               break;
+                       case PART_ROT_GLOB_X:
+                       case PART_ROT_GLOB_Y:
+                       case PART_ROT_GLOB_Z:
+                               rot_vec[part->rotmode - PART_ROT_GLOB_X] = 1.0f;
                                break;
-                       case PART_ROT_RAND:
-                               q2= r_rot;
+                       case PART_ROT_OB_X:
+                       case PART_ROT_OB_Y:
+                       case PART_ROT_OB_Z:
+                               VecCopyf(rot_vec, ob->obmat[part->rotmode - PART_ROT_OB_X]);
                                break;
                }
-               /* how much to rotate from rest position */
-               QuatInterpol(rot,q_one,q2,part->rotfac);
+               
+               /* create rotation quat */
+               VecMulf(rot_vec,-1.0);
+               q2= vectoquat(rot_vec, OB_POSX, OB_POSZ);
+
+               /* randomize rotation quat */
+               if(part->randrotfac!=0.0f)
+                       QuatInterpol(rot, q2, r_rot, part->randrotfac);
+               else
+                       QuatCopy(rot,q2);
 
-               /* phase */
-               VecRotToQuat(x_vec,part->phasefac*(float)M_PI,q_phase);
+               /* rotation phase */
+               phasefac = part->phasefac;
+               if(part->randphasefac != 0.0f) /* abuse r_ave[0] as a random number */
+                       phasefac += part->randphasefac * pa->r_ave[0];
+               VecRotToQuat(x_vec, phasefac*(float)M_PI, q_phase);
 
-               /* combine amount & phase */
-               QuatMul(pa->state.rot,rot,q_phase);
+               /* combine base rotation & phase */
+               QuatMul(pa->state.rot, rot, q_phase);
        }
 
        /* -angular velocity                                    */
 
-       pa->state.ave[0]=pa->state.ave[1]=pa->state.ave[2]=0.0;
+       pa->state.ave[0] = pa->state.ave[1] = pa->state.ave[2] = 0.0;
 
        if(part->avemode){
                switch(part->avemode){
@@ -1711,15 +1750,15 @@ void reset_particle(ParticleData *pa, ParticleSystem *psys, ParticleSystemModifi
                }
        }
 
-       pa->dietime=pa->time+pa->lifetime;
+       pa->dietime = pa->time + pa->lifetime;
 
        if(pa->time >= cfra)
-               pa->alive=PARS_UNBORN;
+               pa->alive = PARS_UNBORN;
 
-       pa->state.time=cfra;
+       pa->state.time = cfra;
 
-       pa->stick_ob=0;
-       pa->flag&=~PARS_STICKY;
+       pa->stick_ob = 0;
+       pa->flag &= ~PARS_STICKY;
 }
 static void reset_all_particles(Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float dtime, float cfra, int from)
 {
@@ -4188,13 +4227,16 @@ static void psys_update_path_cache(Object *ob, ParticleSystemModifierData *psmd,
 
        if(distr){
                if(alloc)
-                       alloc_particles(psys,psys->totpart);
+                       alloc_particles(ob,psys,psys->totpart);
 
-               if(psys->totchild && part->childtype){
-                       distribute_particles(ob,psys,PART_FROM_CHILD);
+               if(get_alloc_child_particles_tot(psys)) {
+                       /* don't generate children while computing the hair keys */
+                       if(!(psys->part->type == PART_HAIR) || (psys->flag & PSYS_HAIR_DONE)) {
+                               distribute_particles(ob,psys,PART_FROM_CHILD);
 
-                       if(part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES && part->parents!=0.0)
-                               psys_find_parents(ob,psmd,psys);
+                               if(part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES && part->parents!=0.0)
+                                       psys_find_parents(ob,psmd,psys);
+                       }
                }
        }
 
@@ -4353,10 +4395,10 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier
                        return;
                }
        }
-       else {  
-               if(psys->recalc)
+       else if(part->phystype != PART_PHYS_NO) {       /* cache shouldn't be used for none physics */
+               if(psys->recalc && (psys->flag & PSYS_PROTECT_CACHE) == 0)
                        clear_particles_from_cache(ob,psys,(int)cfra);
-               else if(get_particles_from_cache(ob, psys, (int)cfra)){
+               else if(get_particles_from_cache(ob, psys, (int)cfra)) {
                        cached_step(ob,psmd,psys,cfra,vg_size);
                        psys->cfra=cfra;
                        psys->recalc = 0;
@@ -4413,11 +4455,11 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier
        if(init) {
                if(distr) {
                        if(alloc)
-                               alloc_particles(psys, totpart);
+                               alloc_particles(ob, psys, totpart);
 
                        distribute_particles(ob, psys, part->from);
 
-                       if(psys->totchild && part->childtype)
+                       if(get_alloc_child_particles_tot(psys))
                                distribute_particles(ob, psys, PART_FROM_CHILD);
                }
                initialize_all_particles(ob, psys, psmd);
index ff7b429845d4ea16425175cecd251492c72ecb72..47640ad07ae4c909b7d822a4d31cdb9209f17975 100644 (file)
@@ -47,6 +47,7 @@
 #include "MEM_guardedalloc.h"
 
 #include "DNA_armature_types.h"        
+#include "DNA_color_types.h"
 #include "DNA_constraint_types.h"
 #include "DNA_curve_types.h"
 #include "DNA_group_types.h"
@@ -63,6 +64,7 @@
 #include "BKE_anim.h"
 #include "BKE_armature.h"              
 #include "BKE_bad_level_calls.h"
+#include "BKE_colortools.h"
 #include "BKE_constraint.h"
 #include "BKE_depsgraph.h"
 #include "BKE_global.h"
 #include "BKE_node.h"
 #include "BKE_object.h"
 #include "BKE_scene.h"
+#include "BKE_sculpt.h"
 #include "BKE_world.h"
 #include "BKE_utildefines.h"
 
 #include "BIF_previewrender.h"
-#include "BDR_sculptmode.h"
 
 #include "BPY_extern.h"
 #include "BLI_arithb.h"
@@ -168,7 +170,7 @@ void free_scene(Scene *sce)
                MEM_freeN(sce->nodetree);
        }
 
-       sculptmode_free_all(sce);
+       sculptdata_free(sce);
 }
 
 Scene *add_scene(char *name)
@@ -259,7 +261,7 @@ Scene *add_scene(char *name)
        BLI_init_rctf(&sce->r.safety, 0.1f, 0.9f, 0.1f, 0.9f);
        sce->r.osa= 8;
 
-       sculptmode_init(sce);
+       sculptdata_init(sce);
        
        /* note; in header_info.c the scene copy happens..., if you add more to renderdata it has to be checked there */
        scene_add_render_layer(sce);
@@ -578,3 +580,127 @@ void scene_add_render_layer(Scene *sce)
        srl->passflag= SCE_PASS_COMBINED|SCE_PASS_Z;
 }
 
+/* Initialize 'permanent' sculpt data that is saved with file kept after
+   switching out of sculptmode. */
+void sculptdata_init(Scene *sce)
+{
+       SculptData *sd;
+
+       if(!sce)
+               return;
+
+       sd= &sce->sculptdata;
+
+       if(sd->cumap)
+               curvemapping_free(sd->cumap);
+
+       memset(sd, 0, sizeof(SculptData));
+
+       sd->drawbrush.size = sd->smoothbrush.size = sd->pinchbrush.size =
+               sd->inflatebrush.size = sd->grabbrush.size =
+               sd->layerbrush.size = sd->flattenbrush.size = 50;
+       sd->drawbrush.strength = sd->smoothbrush.strength =
+               sd->pinchbrush.strength = sd->inflatebrush.strength =
+               sd->grabbrush.strength = sd->layerbrush.strength =
+               sd->flattenbrush.strength = 25;
+       sd->drawbrush.dir = sd->pinchbrush.dir = sd->inflatebrush.dir = sd->layerbrush.dir= 1;
+       sd->drawbrush.airbrush = sd->smoothbrush.airbrush =
+               sd->pinchbrush.airbrush = sd->inflatebrush.airbrush =
+               sd->layerbrush.airbrush = sd->flattenbrush.airbrush = 0;
+       sd->drawbrush.view= 0;
+       sd->brush_type= DRAW_BRUSH;
+       sd->texact= -1;
+       sd->texfade= 1;
+       sd->averaging= 1;
+       sd->texsep= 0;
+       sd->texrept= SCULPTREPT_DRAG;
+       sd->flags= SCULPT_DRAW_BRUSH;
+       sd->tablet_size=3;
+       sd->tablet_strength=10;
+       sd->rake=0;
+       sculpt_reset_curve(sd);
+}
+
+void sculptdata_free(Scene *sce)
+{
+       SculptData *sd= &sce->sculptdata;
+       int a;
+
+       sculptsession_free(sce);
+
+       for(a=0; a<MAX_MTEX; a++) {
+               MTex *mtex= sd->mtex[a];
+               if(mtex) {
+                       if(mtex->tex) mtex->tex->id.us--;
+                       MEM_freeN(mtex);
+               }
+       }
+
+       curvemapping_free(sd->cumap);
+       sd->cumap = NULL;
+}
+
+void sculpt_vertexusers_free(SculptSession *ss)
+{
+       if(ss && ss->vertex_users){
+               MEM_freeN(ss->vertex_users);
+               MEM_freeN(ss->vertex_users_mem);
+               ss->vertex_users= NULL;
+               ss->vertex_users_mem= NULL;
+               ss->vertex_users_size= 0;
+       }
+}
+
+void sculptsession_free(Scene *sce)
+{
+       SculptSession *ss= sce->sculptdata.session;
+       if(ss) {
+               if(ss->projverts)
+                       MEM_freeN(ss->projverts);
+               if(ss->mats)
+                       MEM_freeN(ss->mats);
+
+               if(ss->propset) {
+                       if(ss->propset->texdata)
+                               MEM_freeN(ss->propset->texdata);
+                       if(ss->propset->num)
+                               MEM_freeN(ss->propset->num);
+                       MEM_freeN(ss->propset);
+               }
+
+               sculpt_vertexusers_free(ss);
+               if(ss->texcache)
+                       MEM_freeN(ss->texcache);
+               MEM_freeN(ss);
+               sce->sculptdata.session= NULL;
+       }
+}
+
+/*  Default curve approximates 0.5 * (cos(pi * x) + 1), with 0 <= x <= 1 */
+void sculpt_reset_curve(SculptData *sd)
+{
+       CurveMap *cm = NULL;
+
+       if(!sd->cumap)
+               sd->cumap = curvemapping_add(1, 0, 0, 1, 1);
+
+       cm = sd->cumap->cm;
+
+       if(cm->curve)
+               MEM_freeN(cm->curve);
+       cm->curve= MEM_callocN(6*sizeof(CurveMapPoint), "curve points");
+       cm->flag &= ~CUMA_EXTEND_EXTRAPOLATE;
+       cm->totpoint= 6;
+       cm->curve[0].x= 0;
+       cm->curve[0].y= 1;
+       cm->curve[1].x= 0.1;
+       cm->curve[1].y= 0.97553;
+       cm->curve[2].x= 0.3;
+       cm->curve[2].y= 0.79389;
+       cm->curve[3].x= 0.9;
+       cm->curve[3].y= 0.02447;
+       cm->curve[4].x= 0.7;
+       cm->curve[4].y= 0.20611;
+       cm->curve[5].x= 1;
+       cm->curve[5].y= 0;
+}
index 4a3d8f70b1df1c343fe8cf3f141898213e5d4456..f2258f0e1c42f5610ad64c4dbe361072f5f5170f 100644 (file)
@@ -2307,9 +2307,8 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow)
                                                }
 
                                                if (( (sb->totpoint-a) == bs->v1) ){ 
-                                                       actspringlen= VecLenf( (bproot+bs->v2)->pos, bp->pos);
                                                        VecSubf(sd,(bproot+bs->v2)->pos, bp->pos);
-                                                       Normalize(sd);
+                                                       actspringlen=Normalize(sd);
                                                        
                                                        /* friction stuff V1 */
                                                        VecSubf(velgoal,bp->vec,(bproot+bs->v2)->vec);
@@ -2330,9 +2329,8 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow)
                                                }
                                                
                                                if (( (sb->totpoint-a) == bs->v2) ){ 
-                                                       actspringlen= VecLenf( (bproot+bs->v1)->pos, bp->pos);
                                                        VecSubf(sd,bp->pos,(bproot+bs->v1)->pos);
-                                                       Normalize(sd);
+                                                       actspringlen=Normalize(sd);
                                                        
                                                        /* friction stuff V2 */
                                                        VecSubf(velgoal,bp->vec,(bproot+bs->v1)->vec);
index bcb51fa1393de0445a04631dda641aa858fcddc5..eb13ddc318cdfdbd1765596fda744b9bcf91f0e5 100644 (file)
@@ -135,7 +135,8 @@ void BLI_dlist_reinit(struct DynamicList *dlist);
         * converts it to a regular full path.
         * Also removes garbage from directory paths, like /../ or double slashes etc 
         */
-void BLI_cleanup_dir(const char *relabase, char *dir);
+void BLI_cleanup_file(const char *relabase, char *dir);
+void BLI_cleanup_dir(const char *relabase, char *dir); /* same as above but adds a trailing slash */
 
        /**
         * Blender's path code replacement function.
index b5cf9cd81e9c552e406ae12abd641addaa8a6f6b..50b864df5f80a2f6bb478983294698765efb5304 100644 (file)
  * Contributor(s): Campbell Barton
  *
  * ***** END GPL/BL DUAL LICENSE BLOCK *****
- *
- * The old math stuff from Ton. These will slowly phase out in favour
- * of MTC calls. (or even MoTO :) )
- * */
+ */
 
 /* Box Packer */
 
diff --git a/source/blender/blenlib/BLI_bpath.h b/source/blender/blenlib/BLI_bpath.h
new file mode 100644 (file)
index 0000000..e932c39
--- /dev/null
@@ -0,0 +1,60 @@
+/**
+ *
+ * ***** BEGIN GPL/BL DUAL 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. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License.  See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Campbell Barton
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/* Based on ghash, difference is ghash is not a fixed size,
+ * so for BPath we dont need to malloc  */
+
+struct BPathIterator {
+       char*   path;
+       char*   lib;
+       char*   name;
+       void*   data;
+       int             len;
+       int             type;
+};
+
+void                   BLI_bpathIterator_init          (struct BPathIterator *bpi);
+char*                  BLI_bpathIterator_getPath       (struct BPathIterator *bpi);
+char*                  BLI_bpathIterator_getLib        (struct BPathIterator *bpi);
+char*                  BLI_bpathIterator_getName       (struct BPathIterator *bpi);
+int                            BLI_bpathIterator_getType       (struct BPathIterator *bpi);
+int                            BLI_bpathIterator_getPathMaxLen(struct BPathIterator *bpi);
+void                   BLI_bpathIterator_step          (struct BPathIterator *bpi);
+int                            BLI_bpathIterator_isDone        (struct BPathIterator *bpi);
+void                   BLI_bpathIterator_copyPathExpanded( struct BPathIterator *bpi, char *path_expanded);
+
+/* high level funcs */
+
+/* creates a text file with missing files if there are any */
+void checkMissingFiles(char *txtname );
+void makeFilesRelative(char *txtname, int *tot, int *changed, int *failed, int *linked);
+void makeFilesAbsolute(char *txtname, int *tot, int *changed, int *failed, int *linked);
+void findMissingFiles(char *str);
index 5846bbda40e4e274d2308379f314d1830d5d7855..6af377edfba6d368839b2e831e6534f009c22f98 100644 (file)
@@ -117,14 +117,16 @@ void BLI_ghash_insert(GHash *gh, void *key, void *val) {
        }
 }
 
-void* BLI_ghash_lookup(GHash *gh, void *key) {
-       unsigned int hash= gh->hashfp(key)%gh->nbuckets;
-       Entry *e;
-       
-       for (e= gh->buckets[hash]; e; e= e->next)
-               if (gh->cmpfp(key, e->key)==0)
-                       return e->val;
-       
+void* BLI_ghash_lookup(GHash *gh, void *key) 
+{
+       if(gh) {
+               unsigned int hash= gh->hashfp(key)%gh->nbuckets;
+               Entry *e;
+               
+               for (e= gh->buckets[hash]; e; e= e->next)
+                       if (gh->cmpfp(key, e->key)==0)
+                               return e->val;
+       }       
        return NULL;
 }
 
diff --git a/source/blender/blenlib/intern/bpath.c b/source/blender/blenlib/intern/bpath.c
new file mode 100644 (file)
index 0000000..a6c71a8
--- /dev/null
@@ -0,0 +1,561 @@
+/**
+ *
+ * ***** BEGIN GPL/BL DUAL 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. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License.  See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Campbell barton
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include "BLI_bpath.h"
+#include "BKE_global.h"
+#include "DNA_ID.h" /* Library */
+#include "DNA_vfont_types.h"
+#include "DNA_image_types.h"
+#include "DNA_sound_types.h"
+#include "DNA_scene_types.h" /* to get the current frame */
+#include <stdlib.h>
+#include <string.h>
+
+#include "BKE_main.h" /* so we can access G.main->*.first */
+#include "BKE_image.h" /* so we can check the image's type */
+
+#include "blendef.h"
+#include "BKE_utildefines.h"
+
+/* for writing to a textblock */
+#include "BKE_text.h" 
+#include "BLI_blenlib.h"
+#include "DNA_text_types.h"
+
+/* path/file handeling stuff */
+#ifndef WIN32
+  #include <dirent.h>
+  #include <unistd.h>
+#else
+  #include "BLI_winstuff.h"
+  #include <io.h>
+#endif
+
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+
+#define FILE_MAX                       240
+
+
+/* TODO - BPATH_PLUGIN, BPATH_SEQ */
+enum BPathTypes {
+       BPATH_IMAGE = 0,
+       BPATH_SOUND,
+       BPATH_FONT,
+       BPATH_LIB,
+
+       BPATH_DONE
+};
+
+
+void BLI_bpathIterator_init( struct BPathIterator *bpi ) {
+       bpi->type = BPATH_IMAGE;
+       bpi->data = NULL;
+       BLI_bpathIterator_step(bpi);
+}
+
+char* BLI_bpathIterator_getPath( struct BPathIterator *bpi) {
+       return bpi->path;
+}
+void BLI_bpathIterator_copyPathExpanded( struct BPathIterator *bpi, char *path_expanded) {
+       char *filepath, *libpath;
+       
+       filepath = BLI_bpathIterator_getPath(bpi);
+       libpath = BLI_bpathIterator_getLib(bpi);
+       
+       BLI_strncpy(path_expanded, filepath, FILE_MAXDIR*2);
+       
+       if (libpath) { /* check the files location relative to its library path */
+               BLI_convertstringcode(path_expanded, libpath, G.scene->r.cfra);
+       } else { /* local data, use the blend files path */
+               BLI_convertstringcode(path_expanded, G.sce, G.scene->r.cfra);
+       }
+}
+char* BLI_bpathIterator_getLib( struct BPathIterator *bpi) {
+       return bpi->lib;
+}
+char* BLI_bpathIterator_getName( struct BPathIterator *bpi) {
+       return bpi->name;
+}
+int    BLI_bpathIterator_getType( struct BPathIterator *bpi) {
+       return bpi->type;
+}
+int    BLI_bpathIterator_getPathMaxLen( struct BPathIterator *bpi) {
+       return bpi->len;
+}
+
+/* gets the first or the next image that has a path - not a viewer node or generated image */
+static struct Image *ima_getpath__internal(struct Image *ima, int step_next) {
+       if (ima==NULL)
+               return NULL;
+       
+       if (step_next)
+               ima = ima->id.next;
+       
+       while (ima) {
+               if (ima->packedfile==NULL && ELEM3(ima->source, IMA_SRC_FILE, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE))
+                       break;
+               /* image is not a image with a path, skip it */
+               ima = ima->id.next;
+       }       
+       return ima;
+}
+
+static struct VFont *vf_getpath__internal(struct VFont *vf, int step_next) {
+       if (vf==NULL)
+               return NULL;
+       
+       if (step_next)
+               vf = vf->id.next;
+       
+       while (vf) {
+               if (vf->packedfile==NULL && BLI_streq(vf->name, "<builtin>")==0) {
+                       break;
+               }
+               
+               /* font with no path, skip it */
+               vf = vf->id.next;
+       }       
+       return vf;
+}
+
+static struct bSound *snd_getpath__internal(struct bSound *snd, int step_next) {
+       if (snd==NULL)
+               return NULL;
+       
+       if (step_next)
+               snd = snd->id.next;
+       
+       while (snd) {
+               if (snd->packedfile==NULL) {
+                       break;
+               }
+               
+               /* font with no path, skip it */
+               snd = snd->id.next;
+       }       
+       return snd;
+}
+
+void BLI_bpathIterator_step( struct BPathIterator *bpi) {
+       while (bpi->type != BPATH_DONE) {
+               
+               if  ((bpi->type) == BPATH_IMAGE) {
+                       /*if (bpi->data)        bpi->data = ((ID *)bpi->data)->next;*/
+                       if (bpi->data)  bpi->data = ima_getpath__internal( (Image *)bpi->data, 1 ); /* must skip images that have no path */
+                       else                    bpi->data = ima_getpath__internal(G.main->image.first, 0);
+                       
+                       if (bpi->data) {
+                               /* get the path info from this datatype */
+                               Image *ima = (Image *)bpi->data;
+                               
+                               bpi->lib = ima->id.lib ? ima->id.lib->filename : NULL;
+                               bpi->path = ima->name;
+                               bpi->name = ima->id.name+2;
+                               bpi->len = sizeof(ima->name);
+                               
+                               /* we are done, advancing to the next item, this type worked fine */
+                               break;
+                               
+                       } else {
+                               bpi->type+=1; /* advance to the next type */
+                       }
+                       
+                       
+               } else if  ((bpi->type) == BPATH_SOUND) {
+                       if (bpi->data)  bpi->data = snd_getpath__internal( (bSound *)bpi->data, 1 ); /* must skip images that have no path */
+                       else                    bpi->data = snd_getpath__internal(G.main->sound.first, 0);
+                       
+                       if (bpi->data) {
+                               /* get the path info from this datatype */
+                               bSound *snd = (bSound *)bpi->data;
+                               
+                               bpi->lib = snd->id.lib ? snd->id.lib->filename : NULL;
+                               bpi->path = snd->sample->name;
+                               bpi->name = snd->id.name+2;
+                               bpi->len = sizeof(snd->sample->name);
+                               
+                               /* we are done, advancing to the next item, this type worked fine */
+                               break;
+                       } else {
+                               bpi->type+=1; /* advance to the next type */
+                       }
+                       
+                       
+               } else if  ((bpi->type) == BPATH_FONT) {
+                       
+                       if (bpi->data)  bpi->data = vf_getpath__internal( (VFont *)bpi->data, 1 );
+                       else                    bpi->data = vf_getpath__internal( G.main->vfont.first, 0 );
+                       
+                       if (bpi->data) {
+                               /* get the path info from this datatype */
+                               VFont *vf = (VFont *)bpi->data;
+                               
+                               bpi->lib = vf->id.lib ? vf->id.lib->filename : NULL;
+                               bpi->path = vf->name;
+                               bpi->name = vf->id.name+2;
+                               bpi->len = sizeof(vf->name);
+                               
+                               /* we are done, advancing to the next item, this type worked fine */
+                               break;
+                       } else {
+                               bpi->type+=1; /* advance to the next type */
+                       }
+                       
+                       
+               } else if  ((bpi->type) == BPATH_LIB) {
+                       
+                       if (bpi->data)  bpi->data = ((ID *)bpi->data)->next;
+                       else                    bpi->data = G.main->library.first;
+                       
+                       if (bpi->data) {
+                               /* get the path info from this datatype */
+                               Library *lib = (Library *)bpi->data;
+                               
+                               bpi->lib = NULL;
+                               bpi->path = lib->name;
+                               bpi->name = NULL;
+                               bpi->len = sizeof(lib->name);
+                               
+                               /* we are done, advancing to the next item, this type worked fine */
+                               break;
+                       } else {
+                               bpi->type+=1; /* advance to the next type */
+                       }
+               }
+       }
+}
+
+int BLI_bpathIterator_isDone( struct BPathIterator *bpi) {
+       return bpi->type==BPATH_DONE;
+}
+
+/* include the path argument */
+static void bpathToText(Text *btxt, struct BPathIterator *bpi)
+{
+       char *name;
+       char path_expanded[FILE_MAXDIR*2];
+       
+       switch(BLI_bpathIterator_getType(bpi)) {
+       case BPATH_IMAGE:
+               txt_insert_buf( btxt, "Image \"" );
+               break;
+       case BPATH_SOUND:
+               txt_insert_buf( btxt, "Sound \"" );
+               break;
+       case BPATH_FONT:
+               txt_insert_buf( btxt, "Font \"" );
+               break;
+       case BPATH_LIB:
+               txt_insert_buf( btxt, "Library \"" );
+               break;
+       default:
+               txt_insert_buf( btxt, "Unknown \"" );
+               break;
+       }
+       
+       name = BLI_bpathIterator_getName(bpi);
+       
+       if (name) {
+               txt_insert_buf( btxt, name );
+       }
+       txt_insert_buf( btxt, "\" " );
+       
+       BLI_bpathIterator_copyPathExpanded(bpi, path_expanded);
+       
+       txt_insert_buf( btxt, path_expanded );
+       txt_insert_buf( btxt, "\n" );
+       txt_move_eof( btxt, 0 );
+}
+
+/* high level function */
+void checkMissingFiles( char *txtname ) {
+       Text *btxt = NULL;
+       struct BPathIterator bpi;
+       
+       /* be sure there is low chance of the path being too short */
+       char filepath_expanded[FILE_MAXDIR*2]; 
+       char *filepath, *libpath;
+       int files_missing = 0;
+       
+       BLI_bpathIterator_init(&bpi);
+       while (!BLI_bpathIterator_isDone(&bpi)) {
+               filepath = BLI_bpathIterator_getPath(&bpi);
+               libpath = BLI_bpathIterator_getLib(&bpi);
+               
+               BLI_bpathIterator_copyPathExpanded( &bpi, filepath_expanded );
+               
+               if (!BLI_exists(filepath_expanded)) {
+                       if (!btxt) {
+                               btxt = add_empty_text( "missing_files.log" );
+                               if (txtname) {
+                                       BLI_strncpy(txtname, btxt->id.name+2, 24);
+                               }
+                       }
+                       bpathToText(btxt, &bpi);
+                       files_missing = 1;
+               }
+               BLI_bpathIterator_step(&bpi);
+       }
+}
+
+/* dont log any errors at the moment, should probably do this */
+void makeFilesRelative(char *txtname, int *tot, int *changed, int *failed, int *linked) {
+       struct BPathIterator bpi;
+       char *filepath, *libpath;
+       
+       /* be sure there is low chance of the path being too short */
+       char filepath_relative[(FILE_MAXDIR * 2) + FILE_MAXFILE];
+       
+       Text *btxt = NULL;
+       
+       *tot = *changed = *failed = *linked = 0;
+       
+       BLI_bpathIterator_init(&bpi);
+       while (!BLI_bpathIterator_isDone(&bpi)) {
+               filepath = BLI_bpathIterator_getPath(&bpi);
+               libpath = BLI_bpathIterator_getLib(&bpi);
+               
+               if(strncmp(filepath, "//", 2)) {
+                       if (libpath) { /* cant make relative if we are library - TODO, LOG THIS */
+                               (*linked)++;
+                       } else { /* local data, use the blend files path */
+                               BLI_strncpy(filepath_relative, filepath, sizeof(filepath_relative));
+                               /* Important BLI_cleanup_dir runs before the path is made relative
+                                * because it wont work for paths that start with "//../" */ 
+                               BLI_cleanup_file(G.sce, filepath_relative); /* fix any /foo/../foo/ */
+                               BLI_makestringcode(G.sce, filepath_relative);
+                               /* be safe and check the length */
+                               if (BLI_bpathIterator_getPathMaxLen(&bpi) <= strlen(filepath_relative)) {
+                                       if (!btxt) {
+                                               btxt = add_empty_text( "missing_no_rel.log" );
+                                               if (txtname) {
+                                                       BLI_strncpy(txtname, btxt->id.name+2, 24);
+                                               }
+                                       }
+                                       bpathToText(btxt, &bpi);
+                                       (*failed)++;
+                               } else {
+                                       if(strncmp(filepath_relative, "//", 2)==0) {
+                                               strcpy(filepath, filepath_relative);
+                                               (*changed)++;
+                                       } else {
+                                               if (!btxt) {
+                                                       btxt = add_empty_text( "missing_no_rel.log" );
+                                                       if (txtname) {
+                                                               BLI_strncpy(txtname, btxt->id.name+2, 24);
+                                                       }
+                                               }
+                                               bpathToText(btxt, &bpi);
+                                               (*failed)++;
+                                       }
+                               }
+                       }
+               }
+               BLI_bpathIterator_step(&bpi);
+               (*tot)++;
+       }
+}
+
+/* dont log any errors at the moment, should probably do this -
+ * Verry similar to makeFilesRelative - keep in sync! */
+void makeFilesAbsolute(char *txtname, int *tot, int *changed, int *failed, int *linked) {
+       struct BPathIterator bpi;
+       char *filepath, *libpath;
+       
+       /* be sure there is low chance of the path being too short */
+       char filepath_absolute[(FILE_MAXDIR * 2) + FILE_MAXFILE];
+       
+       Text *btxt = NULL;
+       
+       *tot = *changed = *failed = *linked = 0;
+       
+       BLI_bpathIterator_init(&bpi);
+       while (!BLI_bpathIterator_isDone(&bpi)) {
+               filepath = BLI_bpathIterator_getPath(&bpi);
+               libpath = BLI_bpathIterator_getLib(&bpi);
+               
+               if(strncmp(filepath, "//", 2)==0) {
+                       if (libpath) { /* cant make absolute if we are library - TODO, LOG THIS */
+                               (*linked)++;
+                       } else { /* get the expanded path and check it is relative or too long */
+                               BLI_bpathIterator_copyPathExpanded( &bpi, filepath_absolute );
+                               BLI_cleanup_file(G.sce, filepath_absolute); /* fix any /foo/../foo/ */
+                               /* to be safe, check the length */
+                               if (BLI_bpathIterator_getPathMaxLen(&bpi) <= strlen(filepath_absolute)) {
+                                       if (!btxt) {
+                                               btxt = add_empty_text( "missing_no_abs.log" );
+                                               if (txtname) {
+                                                       BLI_strncpy(txtname, btxt->id.name+2, 24);
+                                               }
+                                       }
+                                       bpathToText(btxt, &bpi);
+                                       (*failed)++;
+                               } else {
+                                       if(strncmp(filepath_absolute, "//", 2)) {
+                                               strcpy(filepath, filepath_absolute);
+                                               (*changed)++;
+                                       } else {
+                                               if (!btxt) {
+                                                       btxt = add_empty_text( "missing_no_abs.log" );
+                                                       if (txtname) {
+                                                               BLI_strncpy(txtname, btxt->id.name+2, 24);
+                                                       }
+                                               }
+                                               bpathToText(btxt, &bpi);
+                                               (*failed)++;
+                                       }
+                               }
+                       }
+               }
+               BLI_bpathIterator_step(&bpi);
+               (*tot)++;
+       }
+}
+
+
+/* find this file recursively, use the biggest file so thumbnails dont get used by mistake
+ - dir: subdir to search
+ - filename: set this filename
+ - filesize: filesize for the file
+*/
+#define MAX_RECUR 16
+static int findFileRecursive(char *filename_new, const char *dirname, const char *filename, int *filesize, int *recur_depth)
+{
+       /* file searching stuff */
+       DIR *dir;
+       int file = 0;
+       struct dirent *de;
+       struct stat status;
+       char path[FILE_MAX];
+       int size;
+       
+       dir = opendir(dirname);
+       
+       if (dir==0)
+               return 0;
+       
+       if (*filesize == -1)
+               *filesize = 0; /* dir opened fine */
+       
+       while ((de = readdir(dir)) != NULL) {
+               
+               if (strncmp(".", de->d_name, 2)==0 || strncmp("..", de->d_name, 3)==0)
+                       continue;
+               
+               BLI_join_dirfile(path, dirname, de->d_name);
+               
+               if (stat(path, &status) != 0)
+                       continue; /* cant stat, dont bother with this file, could print debug info here */
+               
+               if (S_ISREG(status.st_mode)) { /* is file */
+                       if (strncmp(filename, de->d_name, FILE_MAX)==0) { /* name matches */
+                               /* open the file to read its size */
+                               file = open(path, O_BINARY|O_RDONLY);
+                               if (file >=0 ) {
+                                       size = BLI_filesize(file);
+                                       if (size > *filesize) { /* find the biggest file */
+                                               *filesize = size;
+                                               BLI_strncpy(filename_new, path, FILE_MAX);
+                                       }
+                                       close(file);
+                               }
+                       }
+               } else if (S_ISDIR(status.st_mode)) { /* is subdir */
+                       if (*recur_depth <= MAX_RECUR) {
+                               (*recur_depth)++;
+                               findFileRecursive(filename_new, path, filename, filesize, recur_depth);
+                               (*recur_depth)--;
+                       }
+               }
+       }
+       closedir(dir);
+       return 1;
+}
+
+/* high level function - call from fileselector */
+void findMissingFiles(char *str) {
+       struct BPathIterator bpi;
+       
+       /* be sure there is low chance of the path being too short */
+       char filepath_expanded[FILE_MAXDIR*2]; 
+       char *filepath, *libpath;
+       int filesize, recur_depth;
+       
+       char dirname[FILE_MAX], filename[FILE_MAX], filename_new[FILE_MAX], dummyname[FILE_MAX];
+       
+       BLI_split_dirfile(str, dirname, dummyname);
+       
+       BLI_bpathIterator_init(&bpi);
+       
+       while (!BLI_bpathIterator_isDone(&bpi)) {
+               filepath = BLI_bpathIterator_getPath(&bpi);
+               libpath = BLI_bpathIterator_getLib(&bpi);
+               
+               if (libpath==NULL) {
+                       
+                       BLI_bpathIterator_copyPathExpanded( &bpi, filepath_expanded );
+                       
+                       if (!BLI_exists(filepath_expanded)) {
+                               /* can the dir be opened? */
+                               filesize = -1;
+                               recur_depth = 0;
+                               BLI_split_dirfile(filepath, dummyname, filename); /* the file to find */
+                               
+                               findFileRecursive(filename_new, dirname, filename, &filesize, &recur_depth);
+                               if (filesize == -1) { /* could not open dir */
+                                       printf("Could not open dir \"%s\"\n", dirname);
+                                       return;
+                               }
+                               
+                               if (filesize > 0) {
+                                       
+                                       if (BLI_bpathIterator_getPathMaxLen( &bpi ) < strlen(filename_new)) { 
+                                               printf("cannot set path \"%s\" too long!", filename_new);
+                                       } else {
+                                               /* copy the found path into the old one */
+                                               if (G.relbase_valid)
+                                                       BLI_makestringcode(G.sce, filename_new);
+                                               
+                                               strcpy( BLI_bpathIterator_getPath( &bpi ), filename_new );
+                                       }
+                               }
+                       }
+               }
+               BLI_bpathIterator_step(&bpi);
+       }
+}
index 7c94cc80847284b426281cdfe5627fcb8948a25c..d1b2efa28c72bf2954fff85dc038e72d08672b0f 100644 (file)
@@ -776,6 +776,16 @@ int BLI_strcaseeq(char *a, char *b) {
  */
 
 void BLI_cleanup_dir(const char *relabase, char *dir)
+{
+       BLI_cleanup_file(relabase, dir);
+#ifdef WIN32
+       strcat(dir, "\\");
+#else
+       strcat(dir, "/");
+#endif
+}
+
+void BLI_cleanup_file(const char *relabase, char *dir)
 {
        short a;
        char *start, *eind;
@@ -814,9 +824,7 @@ void BLI_cleanup_dir(const char *relabase, char *dir)
                        dir[a] = 0;
                }
        }
-
-       strcat(dir, "\\");
-#else  
+#else
        if(dir[0]=='.') {       /* happens, for example in FILE_MAIN */
           dir[0]= '/';
           dir[1]= 0;
@@ -850,8 +858,6 @@ void BLI_cleanup_dir(const char *relabase, char *dir)
                        if (a<=0) break;
                }
        }
-
-       strcat(dir, "/");
 #endif
 }
 
index 9a6e69fe1b0ce2ed2507322b7a098701eaeb4948..d215bdf67cd334b75764d333c68638771dcb3f80 100644 (file)
 #include "BKE_sca.h" // for init_actuator
 #include "BKE_scene.h"
 #include "BKE_softbody.h"      // sbNew()
+#include "BKE_sculpt.h"
 #include "BKE_texture.h" // for open_plugin_tex
 #include "BKE_utildefines.h" // SWITCH_INT DATA ENDB DNA1 O_BINARY GLOB USER TEST REND
 #include "BKE_idprop.h"
 #include "BLO_undofile.h"
 #include "BLO_readblenfile.h" // streaming read pipe, for BLO_readblenfile BLO_readblenfilememory
 
-#include "multires.h"
-
 #include "readfile.h"
 
 #include "genfile.h"
@@ -1527,6 +1526,22 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
                link->tosock= newdataadr(fd, link->tosock);
        }
        
+       /* set selin and selout */
+       for(node= ntree->nodes.first; node; node= node->next) {
+               for(sock= node->inputs.first; sock; sock= sock->next) {
+                       if(sock->flag & SOCK_SEL) {
+                               ntree->selin= sock;
+                               break;
+                       }
+               }
+               for(sock= node->outputs.first; sock; sock= sock->next) {
+                       if(sock->flag & SOCK_SEL) {
+                               ntree->selout= sock;
+                               break;
+                       }
+               }
+       }
+       
        /* type verification is in lib-link */
 }
 
@@ -1818,12 +1833,12 @@ static void lib_link_action(FileData *fd, Main *main)
        while(act) {
                if(act->id.flag & LIB_NEEDLINK) {
                        act->id.flag -= LIB_NEEDLINK;
-
+                       
                        for (chan=act->chanbase.first; chan; chan=chan->next) {
                                chan->ipo= newlibadr_us(fd, act->id.lib, chan->ipo);
                                lib_link_constraint_channels(fd, &act->id, &chan->constraintChannels);
                        }
-
+                       
                }
                act= act->id.next;
        }
@@ -1848,10 +1863,10 @@ static void direct_link_action(FileData *fd, bAction *act)
        bActionChannel *achan;
 
        link_list(fd, &act->chanbase);
+       link_list(fd, &act->markers);
 
        for (achan = act->chanbase.first; achan; achan=achan->next)
                link_list(fd, &achan->constraintChannels);
-
 }
 
 static void direct_link_armature(FileData *fd, bArmature *arm)
@@ -2771,6 +2786,7 @@ static void lib_link_object(FileData *fd, Main *main)
                        ob->track= newlibadr(fd, ob->id.lib, ob->track);
                        ob->ipo= newlibadr_us(fd, ob->id.lib, ob->ipo);
                        ob->action = newlibadr_us(fd, ob->id.lib, ob->action);
+                       ob->poselib= newlibadr_us(fd, ob->id.lib, ob->poselib);
                        ob->dup_group= newlibadr_us(fd, ob->id.lib, ob->dup_group);
                        
                        ob->proxy= newlibadr_us(fd, ob->id.lib, ob->proxy);
@@ -2946,7 +2962,6 @@ static void direct_link_pose(FileData *fd, bPose *pose) {
                pchan->iktree.first= pchan->iktree.last= NULL;
                pchan->path= NULL;
        }
-
 }
 
 static void direct_link_modifiers(FileData *fd, ListBase *lb)
@@ -3345,6 +3360,12 @@ static void direct_link_scene(FileData *fd, Scene *sce)
        /* SculptData textures */
        for(a=0; a<MAX_MTEX; ++a)
                sce->sculptdata.mtex[a]= newdataadr(fd,sce->sculptdata.mtex[a]);
+       /* Sculpt intensity curve */
+       sce->sculptdata.cumap= newdataadr(fd, sce->sculptdata.cumap);
+       if(sce->sculptdata.cumap)
+               direct_link_curvemapping(fd, sce->sculptdata.cumap);
+       else
+               sculpt_reset_curve(&sce->sculptdata);
 
        if(sce->ed) {
                ListBase *old_seqbasep= &((Editing *)sce->ed)->seqbase;
@@ -3382,6 +3403,24 @@ static void direct_link_scene(FileData *fd, Scene *sce)
                                } else {
                                        seq->strip->stripdata = 0;
                                }
+                               if (seq->flag & SEQ_USE_CROP) {
+                                       seq->strip->crop = newdataadr(
+                                               fd, seq->strip->crop);
+                               } else {
+                                       seq->strip->crop = 0;
+                               }
+                               if (seq->flag & SEQ_USE_TRANSFORM) {
+                                       seq->strip->transform = newdataadr(
+                                               fd, seq->strip->transform);
+                               } else {
+                                       seq->strip->transform = 0;
+                               }
+                               if (seq->flag & SEQ_USE_PROXY) {
+                                       seq->strip->proxy = newdataadr(
+                                               fd, seq->strip->proxy);
+                               } else {
+                                       seq->strip->proxy = 0;
+                               }
                        }
                }
                END_SEQ
@@ -6848,7 +6887,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                }               
                
                for(ma=main->mat.first; ma; ma= ma->id.next) {
-                       if (ma->samp_gloss_mir == 0) {
+                       if(ma->samp_gloss_mir == 0) {
                                ma->gloss_mir = ma->gloss_tra= 1.0;
                                ma->aniso_gloss_mir = 1.0;
                                ma->samp_gloss_mir = ma->samp_gloss_tra= 18;
@@ -6856,11 +6895,23 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                                ma->dist_mir = 0.0;
                                ma->fadeto_mir = MA_RAYMIR_FADETOSKY;
                        }
+
+                       if(ma->strand_min == 0.0f)
+                               ma->strand_min= 1.0f;
                }
 
-               for(part=main->particle.first; part; part=part->id.next)
+               for(part=main->particle.first; part; part=part->id.next) {
                        if(part->ren_child_nbr==0)
                                part->ren_child_nbr= part->child_nbr;
+
+                       if(part->simplify_refsize==0) {
+                               part->simplify_refsize= 1920;
+                               part->simplify_rate= 1.0f;
+                               part->simplify_transition= 0.1f;
+                               part->simplify_viewport= 0.8f;
+                       }
+               }
+
                if (main->versionfile < 245 || main->subversionfile < 12)
                {
                        /* initialize skeleton generation toolsettings */
@@ -7864,6 +7915,7 @@ static void expand_object(FileData *fd, Main *mainvar, Object *ob)
        expand_doit(fd, mainvar, ob->data);
        expand_doit(fd, mainvar, ob->ipo);
        expand_doit(fd, mainvar, ob->action);
+       expand_doit(fd, mainvar, ob->poselib);
 
        for (md=ob->modifiers.first; md; md=md->next) {
                expand_modifier(fd, mainvar, md);
index 4c6226a2b9efcc8ca1dae3f83a89484202fb77a6..275e3b18c4c4dd5b1ec486f682351159be644a12 100644 (file)
@@ -558,7 +558,7 @@ static void write_particlesystems(WriteData *wd, ListBase *particles)
                                ParticleData *pa = psys->particles;
 
                                for(a=0; a<psys->totpart; a++, pa++)
-                                       writedata(wd, DATA, MEM_allocN_len(pa->hair),pa->hair);
+                                       writestruct(wd, DATA, "HairKey", pa->totkey, pa->hair);
                        }
                }
                if(psys->child) writestruct(wd, DATA, "ChildParticle", psys->totchild ,psys->child);
@@ -1429,6 +1429,8 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
 
                for(a=0; a<MAX_MTEX; ++a)
                        writestruct(wd, DATA, "MTex", 1, sce->sculptdata.mtex[a]);
+               if(sce->sculptdata.cumap)
+                       write_curvemapping(wd, sce->sculptdata.cumap);
 
                ed= sce->ed;
                if(ed) {
@@ -1468,7 +1470,15 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
 
                                        strip= seq->strip;
                                        writestruct(wd, DATA, "Strip", 1, strip);
-
+                                       if(seq->flag & SEQ_USE_CROP && strip->crop) {
+                                               writestruct(wd, DATA, "StripCrop", 1, strip->crop);
+                                       }
+                                       if(seq->flag & SEQ_USE_TRANSFORM && strip->transform) {
+                                               writestruct(wd, DATA, "StripTransform", 1, strip->transform);
+                                       }
+                                       if(seq->flag & SEQ_USE_PROXY && strip->proxy) {
+                                               writestruct(wd, DATA, "StripProxy", 1, strip->proxy);
+                                       }
                                        if(seq->type==SEQ_IMAGE)
                                                writestruct(wd, DATA, "StripElem", strip->len, strip->stripdata);
                                        else if(seq->type==SEQ_MOVIE || seq->type==SEQ_RAM_SOUND || seq->type == SEQ_HD_SOUND)
@@ -1735,16 +1745,21 @@ static void write_actions(WriteData *wd, ListBase *idbase)
 {
        bAction                 *act;
        bActionChannel  *chan;
+       TimeMarker *marker;
        
        for(act=idbase->first; act; act= act->id.next) {
                if (act->id.us>0 || wd->current) {
                        writestruct(wd, ID_AC, "bAction", 1, act);
                        if (act->id.properties) IDP_WriteProperty(act->id.properties, wd);
-
+                       
                        for (chan=act->chanbase.first; chan; chan=chan->next) {
                                writestruct(wd, DATA, "bActionChannel", 1, chan);
                                write_constraint_channels(wd, &chan->constraintChannels);
                        }
+                       
+                       for (marker=act->markers.first; marker; marker=marker->next) {
+                               writestruct(wd, DATA, "TimeMarker", 1, marker);
+                       }
                }
        }
 }
index e99c35e45ce1b65b6c78d75fcf5e224f4ae30a14..e72d535815e2f859d35f7571bc39fba214759e46 100644 (file)
@@ -720,6 +720,8 @@ static ImBuf * ffmpeg_fetchibuf(struct anim * anim, int position) {
                                uint8_t* dst2[4]= {
                                        dst[0] + (anim->y - 1)*dstStride[0],
                                        0, 0, 0 };
+                               int i;
+                               unsigned char* r;
 
                                sws_scale(anim->img_convert_ctx,
                                          anim->pFrame->data,
@@ -728,6 +730,15 @@ static ImBuf * ffmpeg_fetchibuf(struct anim * anim, int position) {
                                          anim->pCodecCtx->height,
                                          dst2,
                                          dstStride2);
+                               
+                               /* workaround: sws_scale sets alpha = 0... */
+                               
+                               r = (unsigned char*) ibuf->rect;
+
+                               for (i = 0; i < ibuf->x * ibuf->y; i++) {
+                                       r[3] = 0xff;
+                                       r+=4;
+                               }
 
                                av_free_packet(&packet);
                                break;
index 5290a677678a5d0f3a168016ce3e599d9eb2336a..24a090d93f673ca30385a4f42add51384deb2067 100644 (file)
@@ -64,7 +64,7 @@
        BlockDXT1
 ----------------------------------------------------------------------------*/
 
-unsigned int BlockDXT1::evaluatePalette(Color32 color_array[4]) const
+uint BlockDXT1::evaluatePalette(Color32 color_array[4]) const
 {
        // Does bit expansion before interpolation.
        color_array[0].b = (col0.b << 3) | (col0.b >> 2);
@@ -179,9 +179,9 @@ void BlockDXT1::decodeBlock(ColorBlock * block) const
        evaluatePalette(color_array);
        
        // Write color block.
-       for( unsigned int j = 0; j < 4; j++ ) {
-               for( unsigned int i = 0; i < 4; i++ ) {
-                       unsigned int idx = (row[j] >> (2 * i)) & 3;
+       for( uint j = 0; j < 4; j++ ) {
+               for( uint i = 0; i < 4; i++ ) {
+                       uint idx = (row[j] >> (2 * i)) & 3;
                        block->color(i, j) = color_array[idx];
                }
        }       
@@ -190,7 +190,7 @@ void BlockDXT1::decodeBlock(ColorBlock * block) const
 void BlockDXT1::setIndices(int * idx)
 {
        indices = 0;
-       for(unsigned int i = 0; i < 16; i++) {
+       for(uint i = 0; i < 16; i++) {
                indices |= (idx[i] & 3) << (2 * i);
        }
 }
@@ -199,16 +199,14 @@ void BlockDXT1::setIndices(int * idx)
 /// Flip DXT1 block vertically.
 inline void BlockDXT1::flip4()
 {
-       unsigned char tmp;
-       swap(row[0], row[3], tmp);
-       swap(row[1], row[2], tmp);
+       swap(row[0], row[3]);
+       swap(row[1], row[2]);
 }
 
 /// Flip half DXT1 block vertically.
 inline void BlockDXT1::flip2()
 {
-       unsigned char tmp;
-       swap(row[0], row[1], tmp);
+       swap(row[0], row[1]);
 }
 
 
@@ -248,16 +246,14 @@ void AlphaBlockDXT3::decodeBlock(ColorBlock * block) const
 /// Flip DXT3 alpha block vertically.
 void AlphaBlockDXT3::flip4()
 {
-       unsigned short tmp;
-       swap(row[0], row[3], tmp);
-       swap(row[1], row[2], tmp);
+       swap(row[0], row[3]);
+       swap(row[1], row[2]);
 }
 
 /// Flip half DXT3 alpha block vertically.
 void AlphaBlockDXT3::flip2()
 {
-       unsigned short tmp;
-       swap(row[0], row[1], tmp);
+       swap(row[0], row[1]);
 }
 
 /// Flip DXT3 block vertically.
@@ -279,7 +275,7 @@ void BlockDXT3::flip2()
        BlockDXT5
 ----------------------------------------------------------------------------*/
 
-void AlphaBlockDXT5::evaluatePalette(unsigned char alpha[8]) const
+void AlphaBlockDXT5::evaluatePalette(uint8 alpha[8]) const
 {
        if (alpha0 > alpha1) {
                evaluatePalette8(alpha);
@@ -289,35 +285,35 @@ void AlphaBlockDXT5::evaluatePalette(unsigned char alpha[8]) const
        }
 }
 
-void AlphaBlockDXT5::evaluatePalette8(unsigned char alpha[8]) const
+void AlphaBlockDXT5::evaluatePalette8(uint8 alpha[8]) const
 {
        // 8-alpha block:  derive the other six alphas.
        // Bit code 000 = alpha0, 001 = alpha1, others are interpolated.
        alpha[0] = alpha0;
        alpha[1] = alpha1;
-       alpha[2] = (6 * alpha0 + 1 * alpha1) / 7;       // bit code 010
-       alpha[3] = (5 * alpha0 + 2 * alpha1) / 7;       // bit code 011
-       alpha[4] = (4 * alpha0 + 3 * alpha1) / 7;       // bit code 100
-       alpha[5] = (3 * alpha0 + 4 * alpha1) / 7;       // bit code 101
-       alpha[6] = (2 * alpha0 + 5 * alpha1) / 7;       // bit code 110
-       alpha[7] = (1 * alpha0 + 6 * alpha1) / 7;       // bit code 111
+       alpha[2] = (6 * alpha[0] + 1 * alpha[1]) / 7;   // bit code 010
+       alpha[3] = (5 * alpha[0] + 2 * alpha[1]) / 7;   // bit code 011
+       alpha[4] = (4 * alpha[0] + 3 * alpha[1]) / 7;   // bit code 100
+       alpha[5] = (3 * alpha[0] + 4 * alpha[1]) / 7;   // bit code 101
+       alpha[6] = (2 * alpha[0] + 5 * alpha[1]) / 7;   // bit code 110
+       alpha[7] = (1 * alpha[0] + 6 * alpha[1]) / 7;   // bit code 111
 }
 
-void AlphaBlockDXT5::evaluatePalette6(unsigned char alpha[8]) const
+void AlphaBlockDXT5::evaluatePalette6(uint8 alpha[8]) const
 {
        // 6-alpha block.
        // Bit code 000 = alpha0, 001 = alpha1, others are interpolated.
        alpha[0] = alpha0;
        alpha[1] = alpha1;
-       alpha[2] = (4 * alpha0 + 1 * alpha1) / 5;       // Bit code 010
-       alpha[3] = (3 * alpha0 + 2 * alpha1) / 5;       // Bit code 011
-       alpha[4] = (2 * alpha0 + 3 * alpha1) / 5;       // Bit code 100
-       alpha[5] = (1 * alpha0 + 4 * alpha1) / 5;       // Bit code 101
+       alpha[2] = (4 * alpha[0] + 1 * alpha[1]) / 5;   // Bit code 010
+       alpha[3] = (3 * alpha[0] + 2 * alpha[1]) / 5;   // Bit code 011
+       alpha[4] = (2 * alpha[0] + 3 * alpha[1]) / 5;   // Bit code 100
+       alpha[5] = (1 * alpha[0] + 4 * alpha[1]) / 5;   // Bit code 101
        alpha[6] = 0x00;                                                        // Bit code 110
        alpha[7] = 0xFF;                                                        // Bit code 111
 }
 
-void AlphaBlockDXT5::indices(unsigned char index_array[16]) const
+void AlphaBlockDXT5::indices(uint8 index_array[16]) const
 {
        index_array[0x0] = bits0;
        index_array[0x1] = bits1;
@@ -337,52 +333,52 @@ void AlphaBlockDXT5::indices(unsigned char index_array[16]) const
        index_array[0xF] = bitsF;
 }
 
-unsigned int AlphaBlockDXT5::index(unsigned int index) const
+uint AlphaBlockDXT5::index(uint index) const
 {
        int offset = (3 * index + 16);
-       return (this->u >> offset) & 0x7;
+       return uint((this->u >> offset) & 0x7);
 }
 
-void AlphaBlockDXT5::setIndex(unsigned int index, unsigned int value)
+void AlphaBlockDXT5::setIndex(uint index, uint value)
 {
        int offset = (3 * index + 16);
-       unsigned long long mask = ((unsigned long long)(0x7)) << offset;
-       this->u = (this->u & ~mask) | (((unsigned long long)(value)) << offset);
+       uint64 mask = uint64(0x7) << offset;
+       this->u = (this->u & ~mask) | (uint64(value) << offset);
 }
 
 void AlphaBlockDXT5::decodeBlock(ColorBlock * block) const
 {
-       unsigned char alpha_array[8];
+       uint8 alpha_array[8];
        evaluatePalette(alpha_array);
        
-       unsigned char index_array[16];
+       uint8 index_array[16];
        indices(index_array);
        
-       for(unsigned int i = 0; i < 16; i++) {
+       for(uint i = 0; i < 16; i++) {
                block->color(i).a = alpha_array[index_array[i]];
        }
 }
 
 void AlphaBlockDXT5::flip4()
 {
-       unsigned long long * b = (unsigned long long *)this;
+       uint64 * b = (uint64 *)this;
        
        // @@ The masks might have to be byte swapped.
-       unsigned long long tmp = (*b & (unsigned long long)(0x000000000000FFFFLL));
-       tmp |= (*b & (unsigned long long)(0x000000000FFF0000LL)) << 36;
-       tmp |= (*b & (unsigned long long)(0x000000FFF0000000LL)) << 12;
-       tmp |= (*b & (unsigned long long)(0x000FFF0000000000LL)) >> 12;
-       tmp |= (*b & (unsigned long long)(0xFFF0000000000000LL)) >> 36;
+       uint64 tmp = (*b & (uint64)(0x000000000000FFFFLL));
+       tmp |= (*b & (uint64)(0x000000000FFF0000LL)) << 36;
+       tmp |= (*b & (uint64)(0x000000FFF0000000LL)) << 12;
+       tmp |= (*b & (uint64)(0x000FFF0000000000LL)) >> 12;
+       tmp |= (*b & (uint64)(0xFFF0000000000000LL)) >> 36;
        
        *b = tmp;
 }
 
 void AlphaBlockDXT5::flip2()
 {
-       unsigned int * b = (unsigned int *)this;
+       uint * b = (uint *)this;
        
        // @@ The masks might have to be byte swapped.
-       unsigned int tmp = (*b & 0xFF000000);
+       uint tmp = (*b & 0xFF000000);
        tmp |=  (*b & 0x00000FFF) << 12;
        tmp |= (*b & 0x00FFF000) >> 12;
        
@@ -396,6 +392,7 @@ void BlockDXT5::decodeBlock(ColorBlock * block) const
        
        // Decode alpha.
        alpha.decodeBlock(block);
+
 }
 
 /// Flip DXT5 block vertically.
@@ -416,13 +413,13 @@ void BlockDXT5::flip2()
 /// Decode ATI1 block.
 void BlockATI1::decodeBlock(ColorBlock * block) const
 {
-       unsigned char alpha_array[8];
+       uint8 alpha_array[8];
        alpha.evaluatePalette(alpha_array);
        
-       unsigned char index_array[16];
+       uint8 index_array[16];
        alpha.indices(index_array);
        
-       for(unsigned int i = 0; i < 16; i++) {
+       for(uint i = 0; i < 16; i++) {
                Color32 & c = block->color(i);
                c.b = c.g = c.r = alpha_array[index_array[i]];
                c.a = 255;
@@ -445,13 +442,13 @@ void BlockATI1::flip2()
 /// Decode ATI2 block.
 void BlockATI2::decodeBlock(ColorBlock * block) const
 {
-       unsigned char alpha_array[8];
-       unsigned char index_array[16];
+       uint8 alpha_array[8];
+       uint8 index_array[16];
        
        x.evaluatePalette(alpha_array);
        x.indices(index_array);
        
-       for(unsigned int i = 0; i < 16; i++) {
+       for(uint i = 0; i < 16; i++) {
                Color32 & c = block->color(i);
                c.r = alpha_array[index_array[i]];
        }
@@ -459,7 +456,7 @@ void BlockATI2::decodeBlock(ColorBlock * block) const
        y.evaluatePalette(alpha_array);
        y.indices(index_array);
     &