diff --git a/CMakeLists.txt b/CMakeLists.txt index 4eb5e9c659d..673c5e99348 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -68,6 +68,7 @@ OPTION(WITH_FFMPEG "Enable FFMPeg Support (http://ffmpeg.mplayerhq.hu/)" OFF) OPTION(WITH_OPENAL "Enable OpenAL Support (http://www.openal.org)" ON) OPTION(YESIAMSTUPID "Enable execution on 64-bit platforms" OFF) OPTION(WITH_OPENMP "Enable OpenMP (has to be supported by the compiler)" OFF) +OPTION(WITH_BINRELOC "Enable binreloc filepath support" OFF) IF(NOT WITH_GAMEENGINE AND WITH_PLAYER) MESSAGE("WARNING: WITH_PLAYER needs WITH_GAMEENGINE") @@ -264,6 +265,9 @@ IF(WIN32) SET(FFMPEG_LIB avcodec-51 avformat-51 avutil-49) SET(FFMPEG_LIBPATH ${FFMPEG}/lib) + SET(BINRELC ${LIBDIR}/binreloc) + SET(BINRELC_INC ${BINRELOC}/include) + SET(LLIBS kernel32 user32 gdi32 comdlg32 advapi32 shell32 ole32 oleaut32 uuid ws2_32 vfw32 winmm) IF(WITH_OPENAL) SET(LLIBS ${LLIBS} dxguid) diff --git a/config/linux2-config.py b/config/linux2-config.py index 4bf7e755c49..abba0f97ef2 100644 --- a/config/linux2-config.py +++ b/config/linux2-config.py @@ -114,6 +114,8 @@ BF_ICONV_INC = '${BF_ICONV}/include' BF_ICONV_LIB = 'iconv' BF_ICONV_LIBPATH = '${BF_ICONV}/lib' +WITH_BF_BINRELOC = 'true' + # enable ffmpeg support WITH_BF_FFMPEG = 'true' # -DWITH_FFMPEG BF_FFMPEG = '#extern/ffmpeg' diff --git a/config/win32-vc-config.py b/config/win32-vc-config.py index d1a63022ac8..8044617814c 100644 --- a/config/win32-vc-config.py +++ b/config/win32-vc-config.py @@ -106,6 +106,8 @@ BF_WINTAB_INC = '${BF_WINTAB}/INCLUDE' WITH_BF_YAFRAY = 'true' +WITH_BF_BINRELOC = 'false' + #WITH_BF_NSPR = 'true' #BF_NSPR = $(LIBDIR)/nspr #BF_NSPR_INC = -I$(BF_NSPR)/include -I$(BF_NSPR)/include/nspr diff --git a/extern/CMakeLists.txt b/extern/CMakeLists.txt index 0f07bde72d5..1842aa05246 100644 --- a/extern/CMakeLists.txt +++ b/extern/CMakeLists.txt @@ -43,3 +43,6 @@ IF(WITH_VERSE) SUBDIRS(verse) ENDIF(WITH_VERSE) +if(WITH_BINRELOC) + SUBDIRS(binreloc) +ENDIF(WITH_BINRELOC) diff --git a/extern/Makefile b/extern/Makefile index 04b282a8926..4ca63b6e7f9 100644 --- a/extern/Makefile +++ b/extern/Makefile @@ -56,6 +56,10 @@ ifneq ($(NAN_NO_KETSJI), true) DIRS += bullet2 endif +ifeq ($(WITH_BINRELOC), true) + DIRS += binreloc +endif + TARGET = ifneq ($(OS),irix) TARGET=solid diff --git a/extern/SConscript b/extern/SConscript index 766e2a5b188..bcf67055788 100644 --- a/extern/SConscript +++ b/extern/SConscript @@ -17,3 +17,6 @@ if env['WITH_BF_VERSE']: if env['WITH_BF_FFMPEG'] and env['BF_FFMPEG_LIB'] == '': SConscript(['ffmpeg/SConscript']); + +if env['OURPLATFORM'] == 'linux2': + SConscript(['binreloc/SConscript']); \ No newline at end of file diff --git a/extern/binreloc/CMakeLists.txt b/extern/binreloc/CMakeLists.txt new file mode 100644 index 00000000000..ee4dccf4cda --- /dev/null +++ b/extern/binreloc/CMakeLists.txt @@ -0,0 +1,26 @@ +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2008 by The Blender Foundation +# All rights reserved. +# + +SET(INC ./include ${WINTAB_INC}) +ADD_DEFINITIONS(-DWITH_BINRELOC) +FILE(GLOB SRC *.c) + +BLENDERLIB(binreloc "${SRC}" "${INC}") +#, libtype=['core','player'], priority = [25,15] ) diff --git a/extern/binreloc/Makefile b/extern/binreloc/Makefile new file mode 100644 index 00000000000..dbd093500a1 --- /dev/null +++ b/extern/binreloc/Makefile @@ -0,0 +1,37 @@ +# +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2008 by The Blender Foundation +# All rights reserved. +# +# + +LIBNAME = binreloc +DIR = $(OCGDIR)/extern/$(LIBNAME) + +include nan_definitions.mk + +CPPFLAGS += -I./include + + +include nan_compile.mk + + +install: all debug + @[ -d $(DIR) ] || mkdir $(DIR) + @[ -d $(DIR)/include ] || mkdir $(DIR)/include + @../../intern/tools/cpifdiff.sh include/*.h $(DIR)/include/ diff --git a/extern/binreloc/SConscript b/extern/binreloc/SConscript new file mode 100644 index 00000000000..a39dff7f399 --- /dev/null +++ b/extern/binreloc/SConscript @@ -0,0 +1,13 @@ +#!/usr/bin/python +import sys +import os + +Import('env') +defs = 'ENABLE_BINRELOC' +cflags = [] + +sources = ['binreloc.c'] +incs = 'include' + +env.BlenderLib ( 'extern_binreloc', sources, Split(incs), Split(defs), libtype=['intern','player'], priority=[36, 114], compileflags = cflags) + diff --git a/extern/binreloc/binreloc.c b/extern/binreloc/binreloc.c new file mode 100644 index 00000000000..c6dc0ae709f --- /dev/null +++ b/extern/binreloc/binreloc.c @@ -0,0 +1,766 @@ +/* + * BinReloc - a library for creating relocatable executables + * Written by: Hongli Lai + * http://autopackage.org/ + * + * This source code is public domain. You can relicense this code + * under whatever license you want. + * + * See http://autopackage.org/docs/binreloc/ for + * more information and how to use this. + */ + +#ifndef __BINRELOC_C__ +#define __BINRELOC_C__ + +#ifdef ENABLE_BINRELOC + #include + #include + #include +#endif /* ENABLE_BINRELOC */ +#include +#include +#include +#include +#include "binreloc.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + + +/** @internal + * Find the canonical filename of the executable. Returns the filename + * (which must be freed) or NULL on error. If the parameter 'error' is + * not NULL, the error code will be stored there, if an error occured. + */ +static char * +_br_find_exe (BrInitError *error) +{ +#ifndef ENABLE_BINRELOC + if (error) + *error = BR_INIT_ERROR_DISABLED; + return NULL; +#else + char *path, *path2, *line, *result; + size_t buf_size; + ssize_t size; + struct stat stat_buf; + FILE *f; + + /* Read from /proc/self/exe (symlink) */ + if (sizeof (path) > SSIZE_MAX) + buf_size = SSIZE_MAX - 1; + else + buf_size = PATH_MAX - 1; + path = (char *) malloc (buf_size); + if (path == NULL) { + /* Cannot allocate memory. */ + if (error) + *error = BR_INIT_ERROR_NOMEM; + return NULL; + } + path2 = (char *) malloc (buf_size); + if (path2 == NULL) { + /* Cannot allocate memory. */ + if (error) + *error = BR_INIT_ERROR_NOMEM; + free (path); + return NULL; + } + + strncpy (path2, "/proc/self/exe", buf_size - 1); + + while (1) { + int i; + + size = readlink (path2, path, buf_size - 1); + if (size == -1) { + /* Error. */ + free (path2); + break; + } + + /* readlink() success. */ + path[size] = '\0'; + + /* Check whether the symlink's target is also a symlink. + * We want to get the final target. */ + i = stat (path, &stat_buf); + if (i == -1) { + /* Error. */ + free (path2); + break; + } + + /* stat() success. */ + if (!S_ISLNK (stat_buf.st_mode)) { + /* path is not a symlink. Done. */ + free (path2); + return path; + } + + /* path is a symlink. Continue loop and resolve this. */ + strncpy (path, path2, buf_size - 1); + } + + + /* readlink() or stat() failed; this can happen when the program is + * running in Valgrind 2.2. Read from /proc/self/maps as fallback. */ + + buf_size = PATH_MAX + 128; + line = (char *) realloc (path, buf_size); + if (line == NULL) { + /* Cannot allocate memory. */ + free (path); + if (error) + *error = BR_INIT_ERROR_NOMEM; + return NULL; + } + + f = fopen ("/proc/self/maps", "r"); + if (f == NULL) { + free (line); + if (error) + *error = BR_INIT_ERROR_OPEN_MAPS; + return NULL; + } + + /* The first entry should be the executable name. */ + result = fgets (line, (int) buf_size, f); + if (result == NULL) { + fclose (f); + free (line); + if (error) + *error = BR_INIT_ERROR_READ_MAPS; + return NULL; + } + + /* Get rid of newline character. */ + buf_size = strlen (line); + if (buf_size <= 0) { + /* Huh? An empty string? */ + fclose (f); + free (line); + if (error) + *error = BR_INIT_ERROR_INVALID_MAPS; + return NULL; + } + if (line[buf_size - 1] == 10) + line[buf_size - 1] = 0; + + /* Extract the filename; it is always an absolute path. */ + path = strchr (line, '/'); + + /* Sanity check. */ + if (strstr (line, " r-xp ") == NULL || path == NULL) { + fclose (f); + free (line); + if (error) + *error = BR_INIT_ERROR_INVALID_MAPS; + return NULL; + } + + path = strdup (path); + free (line); + fclose (f); + return path; +#endif /* ENABLE_BINRELOC */ +} + + +/** @internal + * Find the canonical filename of the executable which owns symbol. + * Returns a filename which must be freed, or NULL on error. + */ +static char * +_br_find_exe_for_symbol (const void *symbol, BrInitError *error) +{ +#ifndef ENABLE_BINRELOC + if (error) + *error = BR_INIT_ERROR_DISABLED; + return (char *) NULL; +#else + #define SIZE PATH_MAX + 100 + FILE *f; + size_t address_string_len; + char *address_string, line[SIZE], *found; + + if (symbol == NULL) + return (char *) NULL; + + f = fopen ("/proc/self/maps", "r"); + if (f == NULL) + return (char *) NULL; + + address_string_len = 4; + address_string = (char *) malloc (address_string_len); + found = (char *) NULL; + + while (!feof (f)) { + char *start_addr, *end_addr, *end_addr_end, *file; + void *start_addr_p, *end_addr_p; + size_t len; + + if (fgets (line, SIZE, f) == NULL) + break; + + /* Sanity check. */ + if (strstr (line, " r-xp ") == NULL || strchr (line, '/') == NULL) + continue; + + /* Parse line. */ + start_addr = line; + end_addr = strchr (line, '-'); + file = strchr (line, '/'); + + /* More sanity check. */ + if (!(file > end_addr && end_addr != NULL && end_addr[0] == '-')) + continue; + + end_addr[0] = '\0'; + end_addr++; + end_addr_end = strchr (end_addr, ' '); + if (end_addr_end == NULL) + continue; + + end_addr_end[0] = '\0'; + len = strlen (file); + if (len == 0) + continue; + if (file[len - 1] == '\n') + file[len - 1] = '\0'; + + /* Get rid of "(deleted)" from the filename. */ + len = strlen (file); + if (len > 10 && strcmp (file + len - 10, " (deleted)") == 0) + file[len - 10] = '\0'; + + /* I don't know whether this can happen but better safe than sorry. */ + len = strlen (start_addr); + if (len != strlen (end_addr)) + continue; + + + /* Transform the addresses into a string in the form of 0xdeadbeef, + * then transform that into a pointer. */ + if (address_string_len < len + 3) { + address_string_len = len + 3; + address_string = (char *) realloc (address_string, address_string_len); + } + + memcpy (address_string, "0x", 2); + memcpy (address_string + 2, start_addr, len); + address_string[2 + len] = '\0'; + sscanf (address_string, "%p", &start_addr_p); + + memcpy (address_string, "0x", 2); + memcpy (address_string + 2, end_addr, len); + address_string[2 + len] = '\0'; + sscanf (address_string, "%p", &end_addr_p); + + + if (symbol >= start_addr_p && symbol < end_addr_p) { + found = file; + break; + } + } + + free (address_string); + fclose (f); + + if (found == NULL) + return (char *) NULL; + else + return strdup (found); +#endif /* ENABLE_BINRELOC */ +} + + +#ifndef BINRELOC_RUNNING_DOXYGEN + #undef NULL + #define NULL ((void *) 0) /* typecasted as char* for C++ type safeness */ +#endif + +static char *exe = (char *) NULL; + + +/** Initialize the BinReloc library (for applications). + * + * This function must be called before using any other BinReloc functions. + * It attempts to locate the application's canonical filename. + * + * @note If you want to use BinReloc for a library, then you should call + * br_init_lib() instead. + * + * @param error If BinReloc failed to initialize, then the error code will + * be stored in this variable. Set to NULL if you want to + * ignore this. See #BrInitError for a list of error codes. + * + * @returns 1 on success, 0 if BinReloc failed to initialize. + */ +int +br_init (BrInitError *error) +{ + exe = _br_find_exe (error); + return exe != NULL; +} + + +/** Initialize the BinReloc library (for libraries). + * + * This function must be called before using any other BinReloc functions. + * It attempts to locate the calling library's canonical filename. + * + * @note The BinReloc source code MUST be included in your library, or this + * function won't work correctly. + * + * @param error If BinReloc failed to initialize, then the error code will + * be stored in this variable. Set to NULL if you want to + * ignore this. See #BrInitError for a list of error codes. + * + * @returns 1 on success, 0 if a filename cannot be found. + */ +int +br_init_lib (BrInitError *error) +{ + exe = _br_find_exe_for_symbol ((const void *) "", error); + return exe != NULL; +} + + +/** Find the canonical filename of the current application. + * + * @param default_exe A default filename which will be used as fallback. + * @returns A string containing the application's canonical filename, + * which must be freed when no longer necessary. If BinReloc is + * not initialized, or if br_init() failed, then a copy of + * default_exe will be returned. If default_exe is NULL, then + * NULL will be returned. + */ +char * +br_find_exe (const char *default_exe) +{ + if (exe == (char *) NULL) { + /* BinReloc is not initialized. */ + if (default_exe != (const char *) NULL) + return strdup (default_exe); + else + return (char *) NULL; + } + return strdup (exe); +} + + +/** Locate the directory in which the current application is installed. + * + * The prefix is generated by the following pseudo-code evaluation: + * \code + * dirname(exename) + * \endcode + * + * @param default_dir A default directory which will used as fallback. + * @return A string containing the directory, which must be freed when no + * longer necessary. If BinReloc is not initialized, or if the + * initialization function failed, then a copy of default_dir + * will be returned. If default_dir is NULL, then NULL will be + * returned. + */ +char * +br_find_exe_dir (const char *default_dir) +{ + if (exe == NULL) { + /* BinReloc not initialized. */ + if (default_dir != NULL) + return strdup (default_dir); + else + return NULL; + } + + return br_dirname (exe); +} + + +/** Locate the prefix in which the current application is installed. + * + * The prefix is generated by the following pseudo-code evaluation: + * \code + * dirname(dirname(exename)) + * \endcode + * + * @param default_prefix A default prefix which will used as fallback. + * @return A string containing the prefix, which must be freed when no + * longer necessary. If BinReloc is not initialized, or if + * the initialization function failed, then a copy of default_prefix + * will be returned. If default_prefix is NULL, then NULL will be returned. + */ +char * +br_find_prefix (const char *default_prefix) +{ + char *dir1, *dir2; + + if (exe == (char *) NULL) { + /* BinReloc not initialized. */ + if (default_prefix != (const char *) NULL) + return strdup (default_prefix); + else + return (char *) NULL; + } + + dir1 = br_dirname (exe); + dir2 = br_dirname (dir1); + free (dir1); + return dir2; +} + + +/** Locate the application's binary folder. + * + * The path is generated by the following pseudo-code evaluation: + * \code + * prefix + "/bin" + * \endcode + * + * @param default_bin_dir A default path which will used as fallback. + * @return A string containing the bin folder's path, which must be freed when + * no longer necessary. If BinReloc is not initialized, or if + * the initialization function failed, then a copy of default_bin_dir will + * be returned. If default_bin_dir is NULL, then NULL will be returned. + */ +char * +br_find_bin_dir (const char *default_bin_dir) +{ + char *prefix, *dir; + + prefix = br_find_prefix ((const char *) NULL); + if (prefix == (char *) NULL) { + /* BinReloc not initialized. */ + if (default_bin_dir != (const char *) NULL) + return strdup (default_bin_dir); + else + return (char *) NULL; + } + + dir = br_build_path (prefix, "bin"); + free (prefix); + return dir; +} + + +/** Locate the application's superuser binary folder. + * + * The path is generated by the following pseudo-code evaluation: + * \code + * prefix + "/sbin" + * \endcode + * + * @param default_sbin_dir A default path which will used as fallback. + * @return A string containing the sbin folder's path, which must be freed when + * no longer necessary. If BinReloc is not initialized, or if the + * initialization function failed, then a copy of default_sbin_dir will + * be returned. If default_bin_dir is NULL, then NULL will be returned. + */ +char * +br_find_sbin_dir (const char *default_sbin_dir) +{ + char *prefix, *dir; + + prefix = br_find_prefix ((const char *) NULL); + if (prefix == (char *) NULL) { + /* BinReloc not initialized. */ + if (default_sbin_dir != (const char *) NULL) + return strdup (default_sbin_dir); + else + return (char *) NULL; + } + + dir = br_build_path (prefix, "sbin"); + free (prefix); + return dir; +} + + +/** Locate the application's data folder. + * + * The path is generated by the following pseudo-code evaluation: + * \code + * prefix + "/share" + * \endcode + * + * @param default_data_dir A default path which will used as fallback. + * @return A string containing the data folder's path, which must be freed when + * no longer necessary. If BinReloc is not initialized, or if the + * initialization function failed, then a copy of default_data_dir + * will be returned. If default_data_dir is NULL, then NULL will be + * returned. + */ +char * +br_find_data_dir (const char *default_data_dir) +{ + char *prefix, *dir; + + prefix = br_find_prefix ((const char *) NULL); + if (prefix == (char *) NULL) { + /* BinReloc not initialized. */ + if (default_data_dir != (const char *) NULL) + return strdup (default_data_dir); + else + return (char *) NULL; + } + + dir = br_build_path (prefix, "share"); + free (prefix); + return dir; +} + + +/** Locate the application's localization folder. + * + * The path is generated by the following pseudo-code evaluation: + * \code + * prefix + "/share/locale" + * \endcode + * + * @param default_locale_dir A default path which will used as fallback. + * @return A string containing the localization folder's path, which must be freed when + * no longer necessary. If BinReloc is not initialized, or if the + * initialization function failed, then a copy of default_locale_dir will be returned. + * If default_locale_dir is NULL, then NULL will be returned. + */ +char * +br_find_locale_dir (const char *default_locale_dir) +{ + char *data_dir, *dir; + + data_dir = br_find_data_dir ((const char *) NULL); + if (data_dir == (char *) NULL) { + /* BinReloc not initialized. */ + if (default_locale_dir != (const char *) NULL) + return strdup (default_locale_dir); + else + return (char *) NULL; + } + + dir = br_build_path (data_dir, "locale"); + free (data_dir); + return dir; +} + + +/** Locate the application's library folder. + * + * The path is generated by the following pseudo-code evaluation: + * \code + * prefix + "/lib" + * \endcode + * + * @param default_lib_dir A default path which will used as fallback. + * @return A string containing the library folder's path, which must be freed when + * no longer necessary. If BinReloc is not initialized, or if the initialization + * function failed, then a copy of default_lib_dir will be returned. + * If default_lib_dir is NULL, then NULL will be returned. + */ +char * +br_find_lib_dir (const char *default_lib_dir) +{ + char *prefix, *dir; + + prefix = br_find_prefix ((const char *) NULL); + if (prefix == (char *) NULL) { + /* BinReloc not initialized. */ + if (default_lib_dir != (const char *) NULL) + return strdup (default_lib_dir); + else + return (char *) NULL; + } + + dir = br_build_path (prefix, "lib"); + free (prefix); + return dir; +} + + +/** Locate the application's libexec folder. + * + * The path is generated by the following pseudo-code evaluation: + * \code + * prefix + "/libexec" + * \endcode + * + * @param default_libexec_dir A default path which will used as fallback. + * @return A string containing the libexec folder's path, which must be freed when + * no longer necessary. If BinReloc is not initialized, or if the initialization + * function failed, then a copy of default_libexec_dir will be returned. + * If default_libexec_dir is NULL, then NULL will be returned. + */ +char * +br_find_libexec_dir (const char *default_libexec_dir) +{ + char *prefix, *dir; + + prefix = br_find_prefix ((const char *) NULL); + if (prefix == (char *) NULL) { + /* BinReloc not initialized. */ + if (default_libexec_dir != (const char *) NULL) + return strdup (default_libexec_dir); + else + return (char *) NULL; + } + + dir = br_build_path (prefix, "libexec"); + free (prefix); + return dir; +} + + +/** Locate the application's configuration files folder. + * + * The path is generated by the following pseudo-code evaluation: + * \code + * prefix + "/etc" + * \endcode + * + * @param default_etc_dir A default path which will used as fallback. + * @return A string containing the etc folder's path, which must be freed when + * no longer necessary. If BinReloc is not initialized, or if the initialization + * function failed, then a copy of default_etc_dir will be returned. + * If default_etc_dir is NULL, then NULL will be returned. + */ +char * +br_find_etc_dir (const char *default_etc_dir) +{ + char *prefix, *dir; + + prefix = br_find_prefix ((const char *) NULL); + if (prefix == (char *) NULL) { + /* BinReloc not initialized. */ + if (default_etc_dir != (const char *) NULL) + return strdup (default_etc_dir); + else + return (char *) NULL; + } + + dir = br_build_path (prefix, "etc"); + free (prefix); + return dir; +} + + +/*********************** + * Utility functions + ***********************/ + +/** Concatenate str1 and str2 to a newly allocated string. + * + * @param str1 A string. + * @param str2 Another string. + * @returns A newly-allocated string. This string should be freed when no longer needed. + */ +char * +br_strcat (const char *str1, const char *str2) +{ + char *result; + size_t len1, len2; + + if (str1 == NULL) + str1 = ""; + if (str2 == NULL) + str2 = ""; + + len1 = strlen (str1); + len2 = strlen (str2); + + result = (char *) malloc (len1 + len2 + 1); + memcpy (result, str1, len1); + memcpy (result + len1, str2, len2); + result[len1 + len2] = '\0'; + + return result; +} + + +char * +br_build_path (const char *dir, const char *file) +{ + char *dir2, *result; + size_t len; + int must_free = 0; + + len = strlen (dir); + if (len > 0 && dir[len - 1] != '/') { + dir2 = br_strcat (dir, "/"); + must_free = 1; + } else + dir2 = (char *) dir; + + result = br_strcat (dir2, file); + if (must_free) + free (dir2); + return result; +} + + +/* Emulates glibc's strndup() */ +static char * +br_strndup (const char *str, size_t size) +{ + char *result = (char *) NULL; + size_t len; + + if (str == (const char *) NULL) + return (char *) NULL; + + len = strlen (str); + if (len == 0) + return strdup (""); + if (size > len) + size = len; + + result = (char *) malloc (len + 1); + memcpy (result, str, size); + result[size] = '\0'; + return result; +} + + +/** Extracts the directory component of a path. + * + * Similar to g_dirname() or the dirname commandline application. + * + * Example: + * \code + * br_dirname ("/usr/local/foobar"); --> Returns: "/usr/local" + * \endcode + * + * @param path A path. + * @returns A directory name. This string should be freed when no longer needed. + */ +char * +br_dirname (const char *path) +{ + char *end, *result; + + if (path == (const char *) NULL) + return (char *) NULL; + + end = strrchr (path, '/'); + if (end == (const char *) NULL) + return strdup ("."); + + while (end > path && *end == '/') + end--; + result = br_strndup (path, end - path + 1); + if (result[0] == 0) { + free (result); + return strdup ("/"); + } else + return result; +} + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __BINRELOC_C__ */ diff --git a/extern/binreloc/include/binreloc.h b/extern/binreloc/include/binreloc.h new file mode 100644 index 00000000000..5d0d9f4a209 --- /dev/null +++ b/extern/binreloc/include/binreloc.h @@ -0,0 +1,80 @@ +/* + * BinReloc - a library for creating relocatable executables + * Written by: Hongli Lai + * http://autopackage.org/ + * + * This source code is public domain. You can relicense this code + * under whatever license you want. + * + * See http://autopackage.org/docs/binreloc/ for + * more information and how to use this. + */ + +#ifndef __BINRELOC_H__ +#define __BINRELOC_H__ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +/** These error codes can be returned by br_init(), br_init_lib(), gbr_init() or gbr_init_lib(). */ +typedef enum { + /** Cannot allocate memory. */ + BR_INIT_ERROR_NOMEM, + /** Unable to open /proc/self/maps; see errno for details. */ + BR_INIT_ERROR_OPEN_MAPS, + /** Unable to read from /proc/self/maps; see errno for details. */ + BR_INIT_ERROR_READ_MAPS, + /** The file format of /proc/self/maps is invalid; kernel bug? */ + BR_INIT_ERROR_INVALID_MAPS, + /** BinReloc is disabled (the ENABLE_BINRELOC macro is not defined). */ + BR_INIT_ERROR_DISABLED +} BrInitError; + + +#ifndef BINRELOC_RUNNING_DOXYGEN +/* Mangle symbol names to avoid symbol collisions with other ELF objects. */ + #define br_init zLhm65070058860608_br_init + #define br_init_lib zLhm65070058860608_br_init_lib + #define br_find_exe zLhm65070058860608_br_find_exe + #define br_find_exe_dir zLhm65070058860608_br_find_exe_dir + #define br_find_prefix zLhm65070058860608_br_find_prefix + #define br_find_bin_dir zLhm65070058860608_br_find_bin_dir + #define br_find_sbin_dir zLhm65070058860608_br_find_sbin_dir + #define br_find_data_dir zLhm65070058860608_br_find_data_dir + #define br_find_locale_dir zLhm65070058860608_br_find_locale_dir + #define br_find_lib_dir zLhm65070058860608_br_find_lib_dir + #define br_find_libexec_dir zLhm65070058860608_br_find_libexec_dir + #define br_find_etc_dir zLhm65070058860608_br_find_etc_dir + #define br_strcat zLhm65070058860608_br_strcat + #define br_build_path zLhm65070058860608_br_build_path + #define br_dirname zLhm65070058860608_br_dirname + + +#endif +int br_init (BrInitError *error); +int br_init_lib (BrInitError *error); + +char *br_find_exe (const char *default_exe); +char *br_find_exe_dir (const char *default_dir); +char *br_find_prefix (const char *default_prefix); +char *br_find_bin_dir (const char *default_bin_dir); +char *br_find_sbin_dir (const char *default_sbin_dir); +char *br_find_data_dir (const char *default_data_dir); +char *br_find_locale_dir (const char *default_locale_dir); +char *br_find_lib_dir (const char *default_lib_dir); +char *br_find_libexec_dir (const char *default_libexec_dir); +char *br_find_etc_dir (const char *default_etc_dir); + +/* Utility functions */ +char *br_strcat (const char *str1, const char *str2); +char *br_build_path (const char *dir, const char *file); +char *br_dirname (const char *path); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __BINRELOC_H__ */ diff --git a/intern/bmfont/BMF_Api.h b/intern/bmfont/BMF_Api.h index 1b4a4ee3129..4465242e9fa 100644 --- a/intern/bmfont/BMF_Api.h +++ b/intern/bmfont/BMF_Api.h @@ -152,8 +152,9 @@ void BMF_DrawStringTexture(BMF_Font* font, char* string, float x, float y, float * @param fbuf float image buffer, when NULL to not operate on it. * @param w image buffer width. * @param h image buffer height. + * @param channels number of channels in the image (3 or 4 - currently) */ -void BMF_DrawStringBuf(BMF_Font* font, char *str, int posx, int posy, float *col, unsigned char *buf, float *fbuf, int w, int h); +void BMF_DrawStringBuf(BMF_Font* font, char *str, int posx, int posy, float *col, unsigned char *buf, float *fbuf, int w, int h, int channels); #ifdef __cplusplus diff --git a/intern/bmfont/intern/BMF_Api.cpp b/intern/bmfont/intern/BMF_Api.cpp index eaa8ffb939d..24e053515fb 100644 --- a/intern/bmfont/intern/BMF_Api.cpp +++ b/intern/bmfont/intern/BMF_Api.cpp @@ -180,7 +180,7 @@ void BMF_DrawStringTexture(BMF_Font* font, char *string, float x, float y, float ((BMF_BitmapFont*)font)->DrawStringTexture(string, x, y, z); } -void BMF_DrawStringBuf(BMF_Font* font, char *str, int posx, int posy, float *col, unsigned char *buf, float *fbuf, int w, int h) { +void BMF_DrawStringBuf(BMF_Font* font, char *str, int posx, int posy, float *col, unsigned char *buf, float *fbuf, int w, int h, int channels) { if (!font) return; - ((BMF_BitmapFont*)font)->DrawStringBuf(str, posx, posy, col, buf, fbuf, w, h); + ((BMF_BitmapFont*)font)->DrawStringBuf(str, posx, posy, col, buf, fbuf, w, h, channels); } diff --git a/intern/bmfont/intern/BMF_BitmapFont.cpp b/intern/bmfont/intern/BMF_BitmapFont.cpp index 8e670c099a3..afdcf7fbfbb 100644 --- a/intern/bmfont/intern/BMF_BitmapFont.cpp +++ b/intern/bmfont/intern/BMF_BitmapFont.cpp @@ -241,7 +241,7 @@ void BMF_BitmapFont::DrawStringTexture(char *str, float x, float y, float z) } #define FTOCHAR(val) val<=0.0f?0: (val>=1.0f?255: (char)(255.0f*val)) -void BMF_BitmapFont::DrawStringBuf(char *str, int posx, int posy, float *col, unsigned char *buf, float *fbuf, int w, int h) +void BMF_BitmapFont::DrawStringBuf(char *str, int posx, int posy, float *col, unsigned char *buf, float *fbuf, int w, int h, int channels) { int x, y; @@ -277,7 +277,9 @@ void BMF_BitmapFont::DrawStringBuf(char *str, int posx, int posy, float *col, un pixel[0] = colch[0]; pixel[1] = colch[1]; pixel[2] = colch[2]; - pixel[4] = 1; /*colch[3];*/ + if (channels==4) { + pixel[4] = 1; /*colch[3];*/ + } } } @@ -310,7 +312,9 @@ void BMF_BitmapFont::DrawStringBuf(char *str, int posx, int posy, float *col, un pixel[0] = col[0]; pixel[1] = col[1]; pixel[2] = col[2]; - pixel[3] = 1; /*col[3];*/ + if (channels==4) { + pixel[3] = 1; /*col[3];*/ + } } } } diff --git a/intern/bmfont/intern/BMF_BitmapFont.h b/intern/bmfont/intern/BMF_BitmapFont.h index 986de2bb399..f8d3d5370dd 100644 --- a/intern/bmfont/intern/BMF_BitmapFont.h +++ b/intern/bmfont/intern/BMF_BitmapFont.h @@ -130,8 +130,9 @@ public: * @param fbuf float image buffer, when NULL to not operate on it. * @param w image buffer width. * @param h image buffer height. + * @param channels number of channels in the image (3 or 4 - currently) */ - void DrawStringBuf(char *str, int posx, int posy, float *col, unsigned char *buf, float *fbuf, int w, int h); + void DrawStringBuf(char *str, int posx, int posy, float *col, unsigned char *buf, float *fbuf, int w, int h, int channels); protected: /** Pointer to the font data. */ diff --git a/release/Makefile b/release/Makefile index f608accf2b0..2c299c98250 100644 --- a/release/Makefile +++ b/release/Makefile @@ -31,7 +31,7 @@ include nan_definitions.mk -export VERSION := $(shell cat VERSION) +export VERSION := $(shell getversion.py) BLENDNAME=blender-$(VERSION)-$(CONFIG_GUESS)-py$(NAN_PYTHON_VERSION)$(TYPE) export DISTDIR=$(NAN_OBJDIR)/$(BLENDNAME) diff --git a/release/getversion.py b/release/getversion.py new file mode 100755 index 00000000000..a64a6189b6f --- /dev/null +++ b/release/getversion.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2008 by the Blender Foundation +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +import sys, os, re + +nanblenderhome = os.getenv("NANBLENDERHOME"); + +if nanblenderhome == None: + nanblenderhome = os.path.dirname(os.path.abspath(sys.argv[0]))+"/.." + +config = nanblenderhome+"/source/blender/blenkernel/BKE_blender.h" + +infile = open(config) + +major = None +minor = None + +for line in infile.readlines(): + m = re.search("#define BLENDER_VERSION\s+(\d+)", line) + if m: + major = m.group(1) + m = re.search("#define BLENDER_SUBVERSION\s+(\d+)", line) + if m: + minor = m.group(1) + if minor and major: + major = float(major) / 100.0 + break + +infile.close() + +if minor and major: + print str(major)+"."+minor +else: + print "unknownversion" diff --git a/release/scripts/export_m3g.py b/release/scripts/export_m3g.py index afb019fcc1e..08215b3d027 100644 --- a/release/scripts/export_m3g.py +++ b/release/scripts/export_m3g.py @@ -234,6 +234,19 @@ Tooltip: 'Export to M3G' # # * Modul shutil is not needed any longer. Exporter has its own copy_file. # (realized and inspired by ideasman_42 and Martin Neumann) +# +# History 0.8 +# +# * Blender works with SpotAngles 1..180 but M3G works only with 0..90 +# M3G use the 'half angle' (cut off angle) (Thanks to Martin Storsjö) +# +# * Error fixed: Texture coordinates was not calculated correct. +# (Thanks to Milan Piskla, Vlad, Max Gilead, Regis Cosnier ...) +# +# * New options in GUI: +# M3G Version 2.0 : Will export M3G files Vers. 2.0 in future +# Game Physics: Adds Game Physics infos for NOPE API +# # --------------------------------------------------------------------------# # TODO: Export only selected mesh # TODO: Optimize Bones <--> Vertex Group mapping @@ -1213,7 +1226,7 @@ class M3GVertexArray(M3GObject3D): # Reverse t coordinate because M3G uses a different 2D coordinate system than Blender. if self.uvmapping: for i in range(0,len(self.components),2): - self.components[i]= int(self.components[i]*(-1)) + self.components[i+1]= int(self.components[i+1]*(-1)) #Error in Version 0.7 for i in range(len(self.components)): if abs(self.components[i])>maxValue:raise Exception( i+". element too great/small!") @@ -1284,7 +1297,7 @@ class M3GVertexArray(M3GObject3D): self.blenderIndexes[key]=index #print"blenderIndexes",self.blenderIndexes else: - # print "VertexArray.append: element=",element + print "VertexArray.append: element=",element self.components.append(element) class M3GVertexBuffer(M3GObject3D): @@ -2001,7 +2014,7 @@ class M3GTranslator: self.scene = Blender.Scene.GetCurrent() self.world = self.translateWorld(self.scene) - for obj in self.scene.objects: + for obj in self.scene.objects : if obj.getType()=='Camera': # older Version: isinstance(obj.getData(),Types.CameraType) self.translateCamera(obj) elif obj.getType()=='Mesh': @@ -2176,7 +2189,7 @@ class M3GTranslator: if mOptions.createAmbientLight & mOptions.lightingEnabled: lLight = M3GLight() lLight.mode = lLight.modes['AMBIENT'] - lLight.color = self.translateRGB(AllWorlds[0].getAmb()) + lLight.color = self.translateRGB(blWorld.getAmb()) self.nodes.append(lLight) #TODO: Set background picture from world @@ -2550,7 +2563,7 @@ class M3GTranslator: mLight.intensity = lamp.energy #SpotAngle, SpotExponent (SPOT) if lampType == Lamp.Types.Spot: - mLight.spotAngle = lamp.spotSize + mLight.spotAngle = lamp.spotSize/2 mLight.spotExponent = lamp.spotBlend self.translateToNode(obj,mLight) @@ -2945,6 +2958,8 @@ class OptionMgr: self.perspectiveCorrection = rdict['perspectiveCorrection'] self.smoothShading = rdict['smoothShading'] self.exportAsJava = rdict['exportAsJava'] + self.exportVersion2 = rdict['exportVersion2'] + self.exportGamePhysics = rdict['exportGamePhysics'] except: self.save() # if data isn't valid, rewrite it @@ -2958,6 +2973,8 @@ class OptionMgr: self.perspectiveCorrection = False self.smoothShading = True self.exportAsJava = False + self.exportVersion2 = False + self.exportGamePhysics = False def save(self): d = {} @@ -2970,7 +2987,9 @@ class OptionMgr: d['perspectiveCorrection'] = self.perspectiveCorrection d['smoothShading'] = self.smoothShading d['exportAsJava'] = self.exportAsJava - + d['exportVersion2'] = self.exportVersion2 + d['exportGamePhysics'] = self.exportGamePhysics + Blender.Registry.SetKey('M3GExport', d, True) @@ -2993,6 +3012,8 @@ def gui(): perspectiveCorrection = Draw.Create(mOptions.perspectiveCorrection) smoothShading = Draw.Create(mOptions.smoothShading) exportAsJava = Draw.Create(mOptions.exportAsJava) + exportVersion2 = Draw.Create(mOptions.exportVersion2) + exportGamePhysics = Draw.Create(mOptions.exportGamePhysics) pupBlock = [\ ('Texturing'),\ @@ -3008,7 +3029,9 @@ def gui(): ('Posing'),\ ('All Armature Actions', exportAllActions, 'Exports all actions for armatures'),\ ('Export'),\ - ('As Java Source', exportAsJava, 'Exports scene as Java source code') + ('As Java Source', exportAsJava, 'Exports scene as Java source code'),\ + ('M3G Version 2.0', exportVersion2, 'Exports M3G Version 2.0 File'),\ + ('Game Physics', exportGamePhysics, 'Includes Game Physics infos for NOPE in export') ] # Only execute if use didn't quit (ESC). @@ -3022,6 +3045,8 @@ def gui(): mOptions.perspectiveCorrection = perspectiveCorrection.val mOptions.smoothShading = smoothShading.val mOptions.exportAsJava = exportAsJava.val + mOptions.exportVersion2 = exportVersion2.val + mOptions.exportGamePhysics = exportGamePhysics.val mOptions.save() if mOptions.exportAsJava: diff --git a/release/scripts/import_dxf.py b/release/scripts/import_dxf.py index 2a1081420e4..16f21f71fff 100644 --- a/release/scripts/import_dxf.py +++ b/release/scripts/import_dxf.py @@ -7,72 +7,98 @@ Group: 'Import' Tooltip: 'Import for DXF geometry data (Drawing eXchange Format).' """ __author__ = 'Kitsu(Ed Blake) & migius(Remigiusz Fiedler)' -__version__ = '1.0.11 - 2007.11.17 by migius' +__version__ = '1.0.12 - 2008.01.17 by migius' __url__ = ["http://blenderartists.org/forum/showthread.php?t=84319", "http://wiki.blender.org/index.php/Scripts/Manual/Import/DXF-3D"] __email__ = ["Kitsune_e(at)yahoo.com", "migius(at)4d-vectors.de"] __bpydoc__ = """\ -This script imports DXF objects (2d/3d) into Blender. +This script imports objects from DXF (2d/3d) into Blender. -This script imports 2d and 3d Geometery from DXFr12 format files. -This version is focused on import of 3d-objects. +This script imports 2d and 3d geometery from DXFr12 format files. +Enhanced features are: +- configurable object filtering and geometry manipulation, +- configurable material pre-processing, +- DXF-data analyze and raporting. -Supported DXF Objects: +Supported DXF r12 objects: LINE, POINT, SOLID, TRACE, TEXT, INSERT (=block), -MINSERT (=arrays of blocks), +MINSERT (=array of blocks), CIRCLE, ARC, 3DFACE, 2d-POLYLINE (=plane, incl. arc, variable-width, curve, spline), -3d-POLYLINE (=non-plane polylines), +3d-POLYLINE (=non-plane), 3d-POLYMESH, -3d-POLYFACE +3d-POLYFACE, +VIEW, VPORT +XREF (External Reference). -under construction, partly supported DXF>r12 Objects: -LWPOLYLINE (LightWeight), MLINE, MTEXT, ELLIPSE +Supported DXF>r12 objects: +ELLIPSE, +(wip v1.0.12 partly supported) LWPOLYLINE (LightWeight), +(wip v1.0.12) MLINE, +(wip v1.0.12) MTEXT -Unsupported DXF Objects: -DXF r12: DIMENSION, XREF (External Reference), +Unsupported Objects: +DXF r12: DIMENSION. DXF>r12: SPLINE, GROUP, RAY/XLINE, LEADER, 3DSOLID, BODY, REGION, dynamic BLOCK -Supported Properties: -Hierarchy: Entire DXF BLOCKs hierarchy is preserved after import into Blender -visibility, frozen, -COLOR, LAYER, -thickness, width, -(todo: grouped, XDATA) -It is recommended to use DXF-object properties for coding Blender materials. +Supported Geometry: 2d and 3d DXF-objects. +Curves imported as curves or meshes optionally. + +Supported layout modes: +"model space" is default, +"paper space" as option (= "layout views") + +Scene definitions produced with AVE_RENDER: +scene: selection of lights assigned to the camera, +lights: DIRECT, OVERHEAD, SH_SPOT, +(wip v1.0.13 import of AVE_RENDER material definitions) + +Hierarchy: +Entire DXF BLOCK hierarchy is preserved after import into Blender +(BLOCKs as groups on layer19, INSERTs as dupliGroups on target layer). + +Supported properties: +visibility status, +frozen status, +thickness, +width, +color, +layer, +(wip v1.0.12: XDATA, grouped status) +It is recommended to use DXF-object properties for assign Blender materials. Notes: - Recommend that you run 'RemoveDoubles' on each imported mesh after using this script - Blocks are created on layer 19 then referenced at each insert point. -- Big DXF-files (over 1500 objects) decrease import performance. The problem is not the inefficiency of python-scripting but Blenders performance in creating new objects in his database - probably a database management problem. +- Big DXF-files (over 1500 objects) decrease import performance. +The problem is not the inefficiency of python-scripting but Blenders performance +in creating new objects in his database - probably a database management problem. TODO: - the new style object visibility - support for real 3d-solids (ACIS) -- (to see more, search for "-todo-" in script) +- (to see more, search for "--todo--" in script code) """ """ History: - v1.0 - 2007.11. by migius: "full 3d"-release + v1.0 - 2008.01. by migius planned tasks: -- command-line-mode/batch-mode -- in-place-editing for dupliGroups - -- filtering of unused/not-inserted BLOCKs - -- support for MLine - -- support for Ellipse - -- support for Mtext - -- blender_object.ID.properties[dxf_layer_name] + -- support for MLINE (is exported to r12 as BLOCK*Unnamed with LINEs) + -- support for MTEXT (is exported to r12 as TEXT???) + -- blender_object.properties['dxf_layer_name'] -- better support for long dxf-layer-names - -- Configuration files(.ini) should/can handle various material setups + -- add configuration file.ini handles multiple material setups -- added f_layerFilter -- to-check: obj/mat/group/_mapping-idea from ideasman42: -- curves: added "fill/non-fill" option for closed curves: CIRCLEs,ELLIPSEs,POLYLINEs @@ -80,10 +106,42 @@ History: -- "normalize Z" option to correct non-planar figures -- LINEs need "width" in 3d-space incl vGroups -- support width_force for LINEs/ELLIPSEs = "solidify" - -- bug: dxf-files without layer-section missing layersmap{} - -- color BYLAYER=256,BYBLOCK=0 - -- blocknames conventions length - v1.0.11: 2007.11.17 by migius + -- add better support for color_index BYLAYER=256, BYBLOCK=0 + -- bug: "oneMesh" produces sometimes errors + -- bug: Registry recall from hd_cache ?? only win32 bug?? + + v1.0.12: 2008.01.17 by migius + -- support DXF-definitions of scene, lights and cameras + -- support ortho mode for VIEWs and VPORTs as cameras + a8 lately used INI-dir/filename persistently stored in Registry + a8 lately used DXF-dir/filename persistently stored in Registry + a7 fix missing layersmap{} for dxf-files without "section:layer" + a6 added support for XREF external referenced BLOCKs + a6 check for bug in AutoCAD2002:DXFr12export: ELLIPSE->POLYLINE_ARC fault angles + a6 support VIEWs and VPORTs as cameras: ortho and perspective mode + a6 save resources through ignoring unused BLOCKs (not-inserted or on frozen/blocked layers) + a6 added try_finally: f.close() for all IO-files + a6 added handling for TypeError raise + a5 bugfix f_getOCS for (0,0,z!=1.0) (ellipse in Kai's dxf) + a4 added to analyzeTool: report about VIEWs, VPORTs, unused/xref BLOCKs + a4 bugfix: individual support for 2D/3DPOLYLINE/POLYMESH + a4 added to UI: (*wip)BLOCK-(F): name filtering for BLOCKs + a4 added to UI: BLOCK-(n): filter anoname/hatch BLOCKs *X... + a2 g_scale_as is no more GUI_A-variable + a2 bugfix "material": negative sign color_index + a2 added support for BLOCKs defined with origin !=(0,0,0) + a1 added 'global.reLocation-vector' option + + v1.0.11: 2007.11.24 by migius + c8 added 'curve_resolution_U' option + c8 added context_sensitivity for some UI-buttons + c8 bugfix ELLIPSE rotation, added closed_variant and caps + c7 rebuild UI: new layout, grouping and meta-buttons + c6 rewritten support for ELLIPSE mesh & curve representation + c6 restore selector-buttons for DXF-drawTypes: LINE & Co + c6 change header of INI/INF-files: # at begin + c6 apply scale(1,1,1) after glob.Scale for all mesh objects, not for curve objects. + c5 fixing 'material_on' option c4 added "analyze DXF-file" UI-option: print LAYER/BLOCK-dependences into a textfile c3 human-formating of data in INI-Files c2 added "caps" for closed Bezier-curves @@ -101,17 +159,19 @@ History: b2 fixing material assignment by LAYER+COLOR b1 fixing Bezier curves representation of POLYLINEs-arc-segments b0 added global_scale_presets: "yard/feet/inch to meter" + v1.0.10: 2007.10.18 by migius a6 bugfix CircleDrawCaps for OSX a5 added two "curve_res" UI-buttons for Bezier curves representation a5 improved Bezier curves representation of circles/arcs: correct handlers - a4 first try to fix malformed endpoints of Blender curves of imported ARCs and POLYLINE-arc segments. - a3 bugfix: open POLYLINEs with end_point.loc==start_point.loc + a4 try to fix malformed endpoints of Blender curves of ARC/POLYLINE-arc segments. + a3 bugfix: open-POLYLINEs with end_point.loc==start_point.loc a2 bugfix: f_transform for OCS=(0,0,-1) oriented objects - a1 added "fill_on" option to draw top and bottom sides of CIRCLEs and ELLIPSEs + a1 added "fill_on=caps" option to draw top and bottom sides of CIRCLEs and ELLIPSEs a1 rewrite f_CIRCLE.Draw: from Mesh.Primitive to Mesh - a1 bugfix "newScene"-mode: Cylinders/Arcs were drawn at <0,0,0>location - beta09: 2007.09.02 by migius + a1 bugfix "newScene"-mode: all Cylinders/Arcs were drawn at <0,0,0>location + + v1.0.beta09: 2007.09.02 by migius g5 redesign UI: grouping of buttons g3 update multi-import-mode: <*.*> button g- added multi-import-mode: (path/*) for importing many dxf-files at once @@ -124,7 +184,7 @@ History: f- added import POLYLINE-arc-segments into Blender-BezierCurves f- added import POLYLINE-Bezier-curves into Blender-Curves d5 rewrite: Optimization Levels, added 'directDrawing' - d4 added: f_set_thick(cntrolled by ini-parameters) + d4 added: f_set_thick(controlled by ini-parameters) d4 bugfix: face-normals in objects with minus thickness d4 added: placeholder'Empty'-size in f_Insert.draw d3 rewrite f_Text.Draw: added support for all Text's parameters @@ -139,23 +199,24 @@ History: a- added support for 2d-POLYLINE: splines, fitted curves, fitted surfaces a- redesign f_Drawer for block_definitions a- rewrite import into Blender-Curve-Object - beta08: 2007.07.27 by migius + + v1.0.beta08 - 2007.07.27 by migius: "full 3d"-release l- bugfix: solid_vgroups, clean:scene.objects.new() l- redesign UI to standard Draw.Register+FileSelector, advanced_config_option k- bugfix UI:fileSelect() for MacOSX os.listdir() k- added reset/save/load for config-data k- redesign keywords/drawTypes/Draw.Create_Buttons - j- new interface using UIBlock() with own FileSelector, cause Window.FileSelector() too buggy + j- new UI using UIBlock() with own FileSelector, cause problem Window.FileSelector() i- rewritten Class:Settings for better config-parameter management h- bugfix: face-normals in objects with minus thickness - h- added Vertex-Groups in polylines and solids generated Meshes, for easier material assignment + h- added Vertex-Groups in POLYLINE and SOLID meshes, for easy material assignment h- beautify code, whitespace->tabs h- added settings.thic_force switch for forcing thickness - h- added one Object/Mesh for all simple-entities from the same Layer, - sorted in Vertex-Groups(color_name) (fewer objects = better import performance) + h- added "one Mesh" option for all entities from the same Layer, sorted in
+ Vertex-Groups(color_name) (fewer objects = better import performance) g- rewrote: insert-point-handle-object is a small tetrahedron e- bugfix: closed-polymesh3d - - rewrote: startUI, type_map.keys, f_drawer, for all class_f_draw(added "settings" as attribut) + - rewrote: UI, type_map.keys, f_drawer, all class_f_draw(added "settings" as attribut) - added 2d/3d-support for Polyline_Width incl. angle intersection beta07: 2007.06.19 by migius - added 3d-support for LWPolylines @@ -167,7 +228,7 @@ History: - added 2d/3d-support for 3d-PolyLine, PolyMesh and PolyFace - added Global-Scale for size control of imported scenes beta04: 2007.06.12 by migius - - rewrote the f_calcBulge for correct import the arc-segments of Polylines + - rewrote the f_drawBulge for correct import the arc-segments of Polylines beta03: 2007.06.10 by migius - rewrote interface beta02: 2007.06.09 by migius @@ -180,13 +241,16 @@ History: - added 2d+3d-support for Solids and Traces v0.9 - 2007.01 by kitsu: (for 2.43) + - first draft of true POLYLINE import - v0.8 - 2006.12 by kitsu: + - first draft of object space coordinates OCS import - v0.5b - 2006.10 by kitsu: (for 2.42a) - - + - dxfReader.py + - color_map.py """ @@ -240,7 +304,7 @@ except ImportError: pass print '\n\n\n\n' -print 'Import DXF to Blender *** start ***' #--------------------- +print 'DXF-Importer *** start ***' #--------------------- SCENE = None WORLDX = Mathutils.Vector((1,0,0)) @@ -248,10 +312,13 @@ WORLDY = Mathutils.Vector((1,1,0)) WORLDZ = Mathutils.Vector((0,0,1)) G_SCALE = 1.0 #(0.0001-1000) global scaling factor for all dxf data +G_ORIGIN_X = 0.0 #global translation-vector (x,y,z) in DXF units +G_ORIGIN_Y = 0.0 +G_ORIGIN_Z = 0.0 MIN_DIST = 0.001 #cut-off value for sort out short-distance polyline-"duoble_vertex" ARC_RESOLUTION = 64 #(4-500) arc/circle resolution - number of segments ARC_RADIUS = 1.0 #(0.01-100) arc/circle radius for number of segments algorithm -CURV_RESOLUTION = 12 #(3-50) Bezier curves resolution +CURV_RESOLUTION = 12 #(1-128) Bezier curves U-resolution CURVARC_RESOLUTION = 4 #(3-32) resolution of circle represented as Bezier curve THIN_RESOLUTION = 8 #(4-64) thin_cylinder arc_resolution - number of segments MIN_THICK = MIN_DIST * 10.0 #minimal thickness by forced thickness @@ -266,8 +333,8 @@ FILENAME_MAX = 180 #max length of path+file_name string (FILE_MAXDIR + FILE_MAX MAX_NAMELENGTH = 17 #max_effective_obnamelength in blender =21=17+(.001) INIFILE_DEFAULT_NAME = 'importDXF' INIFILE_EXTENSION = '.ini' -INIFILE_HEADER = 'ImportDXF.py ver.1.0 config data' -INFFILE_HEADER = 'ImportDXF.py ver.1.0 analyze of DXF-data' +INIFILE_HEADER = '#ImportDXF.py ver.1.0 config data' +INFFILE_HEADER = '#ImportDXF.py ver.1.0 analyze of DXF-data' AUTO = BezTriple.HandleTypes.AUTO FREE = BezTriple.HandleTypes.FREE @@ -344,6 +411,174 @@ AT_LEAST = 1 #taller characters will override EXACT = 2 #taller characters will not override +class View: #----------------------------------------------------------------- + """Class for objects representing dxf VIEWs. + """ + def __init__(self, obj, active=None): + """Expects an object of type VIEW as input. + """ + if not obj.type == 'view': + raise TypeError, "Wrong type %s for VIEW object!" %obj.type + + self.type = obj.type + self.name = obj.get_type(2)[0] + self.data = obj.data[:] + + + self.centerX = getit(obj.data, 10, 0.0) #view center pointX (in DCS) + self.centerY = getit(obj.data, 20, 0.0) #view center pointY (in DCS) + self.height = obj.get_type(40)[0] #view height (in DCS) + self.width = obj.get_type(41)[0] #view width (in DCS) + + self.dir = [0,0,0] + self.dir[0] = getit(obj.data, 11, 0.0) #view directionX from target (in WCS) + self.dir[1] = getit(obj.data, 21, 0.0) # + self.dir[2] = getit(obj.data, 31, 0.0) # + + self.target = [0,0,0] + self.target[0] = getit(obj.data, 12, 0.0) #target pointX(in WCS) + self.target[1] = getit(obj.data, 22, 0.0) # + self.target[2] = getit(obj.data, 32, 0.0) # + + self.length = obj.get_type(42)[0] #Lens length + self.clip_front = getit(obj.data, 43) #Front clipping plane (offset from target point) + self.clip_back = getit(obj.data, 44) #Back clipping plane (offset from target point) + self.twist = obj.get_type(50)[0] #view twist angle in degrees + + self.flags = getit(obj, 70, 0) + self.paperspace = self.flags & 1 # + + self.mode = obj.get_type(71)[0] #view mode (VIEWMODE system variable) + + def __repr__(self): + return "%s: name - %s, focus length - %s" %(self.__class__.__name__, self.name, self.length) + + + def draw(self, settings): + """for VIEW: generate Blender_camera. + """ + obname = 'vw_%s' %self.name # create camera object name + #obname = 'ca_%s' %self.name # create camera object name + obname = obname[:MAX_NAMELENGTH] + + if self.target == [0,0,0] and Mathutils.Vector(self.dir).length == 1.0: + cam= Camera.New('ortho', obname) + ob= SCENE.objects.new(cam) + cam.type = 'ortho' + cam.scale = 1.0 # for ortho cameras + else: + cam= Camera.New('persp', obname) + ob= SCENE.objects.new(cam) + cam.type = 'persp' + cam.angle = 60.0 # for persp cameras + if self.length: + #cam.angle = 2 * atan(17.5/self.length) * 180/pi + cam.lens = self.length #for persp cameras + # hack to update Camera>Lens setting (inaccurate as a focal length) + #curLens = cam.lens; cam.lens = curLens + # AutoCAD gets clip distance from target: + dist = Mathutils.Vector(self.dir).length + cam.clipEnd = dist - self.clip_back + cam.clipStart = dist - self.clip_front + + cam.drawLimits = 1 + cam.drawSize = 10 + + v = Mathutils.Vector(self.dir) +# print 'deb:view cam:', cam #------------ +# print 'deb:view self.target:', self.target #------------ +# print 'deb:view self.dir:', self.dir #------------ +# print 'deb:view self.twist:', self.twist #------------ +# print 'deb:view self.clip_front=%s, self.clip_back=%s, dist=%s' %(self.clip_front, self.clip_back, dist) #------------ + transform(v.normalize(), -self.twist, ob) + ob.loc = Mathutils.Vector(self.target) + Mathutils.Vector(self.dir) + return ob + + +class Vport: #----------------------------------------------------------------- + """Class for objects representing dxf VPORTs. + """ + def __init__(self, obj, active=None): + """Expects an object of type VPORT as input. + """ + if not obj.type == 'vport': + raise TypeError, "Wrong type %s for VPORT object!" %obj.type + + self.type = obj.type + self.name = obj.get_type(2)[0] + self.data = obj.data[:] + #print 'deb:vport name, data:', self.name #------- + #print 'deb:vport data:', self.data #------- + + self.height = obj.get_type(40)[0] #vport height (in DCS) + self.centerX = getit(obj.data, 12, 0.0) #vport center pointX (in DCS) + self.centerY = getit(obj.data, 22, 0.0) #vport center pointY (in DCS) + self.width = self.height * obj.get_type(41)[0] #vport aspect ratio - width (in DCS) + + self.dir = [0,0,0] + self.dir[0] = getit(obj.data, 16, 0.0) #vport directionX from target (in WCS) + self.dir[1] = getit(obj.data, 26, 0.0) # + self.dir[2] = getit(obj.data, 36, 0.0) # + + self.target = [0,0,0] + self.target[0] = getit(obj.data, 17, 0.0) #target pointX(in WCS) + self.target[1] = getit(obj.data, 27, 0.0) # + self.target[2] = getit(obj.data, 37, 0.0) # + + self.length = obj.get_type(42)[0] #Lens length + self.clip_front = getit(obj.data, 43) #Front clipping plane (offset from target point) + self.clip_back = getit(obj.data, 44) #Back clipping plane (offset from target point) + self.twist = obj.get_type(51)[0] #view twist angle + + self.flags = getit(obj, 70, 0) + self.paperspace = self.flags & 1 # + + self.mode = obj.get_type(71)[0] #view mode (VIEWMODE system variable) + + def __repr__(self): + return "%s: name - %s, focus length - %s" %(self.__class__.__name__, self.name, self.length) + + def draw(self, settings): + """for VPORT: generate Blender_camera. + """ + obname = 'vp_%s' %self.name # create camera object name + #obname = 'ca_%s' %self.name # create camera object name + obname = obname[:MAX_NAMELENGTH] + + if self.target == [0,0,0] and Mathutils.Vector(self.dir).length == 1.0: + cam= Camera.New('ortho', obname) + ob= SCENE.objects.new(cam) + cam.type = 'ortho' + cam.scale = 1.0 # for ortho cameras + else: + cam= Camera.New('persp', obname) + ob= SCENE.objects.new(cam) + cam.type = 'persp' + cam.angle = 60.0 # for persp cameras + if self.length: + #cam.angle = 2 * atan(17.5/self.length) * 180/pi + cam.lens = self.length #for persp cameras + # hack to update Camera>Lens setting (inaccurate as a focal length) + #curLens = cam.lens; cam.lens = curLens + # AutoCAD gets clip distance from target: + dist = Mathutils.Vector(self.dir).length + cam.clipEnd = dist - self.clip_back + cam.clipStart = dist - self.clip_front + + cam.drawLimits = 1 + cam.drawSize = 10 + + v = Mathutils.Vector(self.dir) +# print 'deb:view cam:', cam #------------ +# print 'deb:view self.target:', self.target #------------ +# print 'deb:view self.dir:', self.dir #------------ +# print 'deb:view self.twist:', self.twist #------------ +# print 'deb:view self.clip_front=%s, self.clip_back=%s, dist=%s' %(self.clip_front, self.clip_back, dist) #------------ + transform(v.normalize(), -self.twist, ob) + ob.loc = Mathutils.Vector(self.target) + Mathutils.Vector(self.dir) + return ob + + class Layer: #----------------------------------------------------------------- """Class for objects representing dxf LAYERs. @@ -426,6 +661,7 @@ class Solid: #----------------------------------------------------------------- obj.type = 'solid' if not obj.type == 'solid': raise TypeError, "Wrong type \'%s\' for solid/trace object!" %obj.type + self.type = obj.type self.data = obj.data[:] @@ -597,10 +833,10 @@ class Line: #----------------------------------------------------------------- if settings.var['lines_as'] == 4: # as thin_box thic = settings.var['thick_min'] width = settings.var['width_min'] - if settings.var['lines_as'] == 3: # as thin cylinder + elif settings.var['lines_as'] == 3: # as thin cylinder cyl_rad = 0.5 * settings.var['width_min'] - if settings.var['curves_on']: # LINE curve representation------------------------- + if settings.var['lines_as'] == 5: # LINE curve representation------------------------- obname = 'li_%s' %self.layer # create object name from layer name obname = obname[:MAX_NAMELENGTH] @@ -610,6 +846,7 @@ class Line: #----------------------------------------------------------------- for point in curve: point.handleTypes = [VECT, VECT] curve.flagU = 0 # 0 sets the curve not cyclic=open + c.setResolu(settings.var['curve_res']) c.update() #important for handles calculation ob = SCENE.objects.new(c) # create a new curve_object @@ -733,13 +970,13 @@ class Point: #----------------------------------------------------------------- thic = settings.var['thick_min'] if thic < settings.var['dist_min']: thic = settings.var['dist_min'] - if points_as in [1,3,4]: - if points_as == 1: # as 'empty' + if True: #--todo-- points_as in [1,3,4,5]: + if True: # points_as in [1,5]: # as 'empty' c = 'Empty' - if points_as == 3: # as 'thin sphere' + elif points_as == 3: # as 'thin sphere' res = settings.var['thin_res'] c = Mesh.Primitives.UVsphere(res,res,thic) - if points_as == 4: # as 'thin box' + elif points_as == 4: # as 'thin box' c = Mesh.Primitives.Cube(thic) ob = SCENE.objects.new(c, obname) # create a new object transform(self.extrusion, 0, ob) @@ -767,7 +1004,6 @@ class Point: #----------------------------------------------------------------- - class LWpolyline: #----------------------------------------------------------------- """Class for objects representing dxf LWPOLYLINEs. """ @@ -974,14 +1210,21 @@ class Polyline: #-------------------------------------------------------------- """for POLYLINE: generate Blender_geometry. """ ob = [] - if self.plface: #---- 3dPolyFace - mesh with free topology + #---- 3dPolyFace - mesh with free topology + if self.plface and settings.drawTypes['plmesh']: ob = self.drawPlFace(settings) - elif self.plmesh: #---- 3dPolyMesh - mesh with ortogonal topology + #---- 3dPolyMesh - mesh with ortogonal topology + elif self.plmesh and settings.drawTypes['plmesh']: ob = self.drawPlMesh(settings) #---- 2dPolyline - plane polyline with arc/wide/thic segments + elif (self.poly2d and settings.drawTypes['polyline']): + if settings.var['plines_as'] == 5: # and self.spline: + ob = self.drawPolyCurve(settings) + else: + ob = self.drawPoly2d(settings) #---- 3dPolyline - non-plane polyline (thin segments = without arc/wide/thic) - elif self.poly2d or self.poly3d: - if settings.var['curves_on']: # and self.spline: + elif (self.poly3d and settings.drawTypes['pline3']): + if settings.var['plines3_as'] == 5: # and self.spline: ob = self.drawPolyCurve(settings) else: ob = self.drawPoly2d(settings) @@ -992,7 +1235,7 @@ class Polyline: #-------------------------------------------------------------- def drawPlFace(self, settings): #---- 3dPolyFace - mesh with free topology """Generate the geometery of polyface. """ - #print 'deb:polyface.draw.START:----------------' #------------------------ + #print 'deb:drawPlFace.START:----------------' #------------------------ points = [] faces = [] #print 'deb:len of pointsList ====== ', len(self.points) #------------------------ @@ -1003,22 +1246,24 @@ class Polyline: #-------------------------------------------------------------- points.append(point.loc) - #print 'deb:len of points_list:\n', len(points) #----------------------- - #print 'deb:points_list:\n', points #----------------------- - #print 'deb:faces_list:\n', faces #----------------------- + #print 'deb:drawPlFace: len of points_list:\n', len(points) #----------------------- + #print 'deb:drawPlFace: len of faces_list:\n', len(faces) #----------------------- + #print 'deb:drawPlFace: points_list:\n', points #----------------------- + #print 'deb:drawPlFace: faces_list:\n', faces #----------------------- obname = 'pf_%s' %self.layer # create object name from layer name obname = obname[:MAX_NAMELENGTH] me = Mesh.New(obname) # create a new mesh ob = SCENE.objects.new(me) # create a new mesh_object me.verts.extend(points) # add vertices to mesh me.faces.extend(faces) # add faces to the mesh + #print 'deb:drawPlFace: len of me.faces:\n', len(me.faces) #----------------------- if settings.var['meshSmooth_on']: # ---------------------- - for i in xrange(len(faces)): + for i in xrange(len(me.faces)): me.faces[i].smooth = True #me.Mode(AUTOSMOOTH) transform(self.extrusion, 0, ob) - #print 'deb:polyface.draw.END:----------------' #------------------------ + #print 'deb:drawPlFace.END:----------------' #------------------------ return ob @@ -1288,6 +1533,7 @@ class Polyline: #-------------------------------------------------------------- else: pline.setFlag(pline.getFlag() & ~6) # dont set top and button caps + pline.setResolu(settings.var['curve_res']) pline.update() ob = SCENE.objects.new(pline) # create a new curve_object @@ -1816,7 +2062,8 @@ class Vertex(object): #-------------------------------------------------------- v4 = getit(data, 74, None) # polyface:Face.vertex 4. self.face = [abs(v1)-1,abs(v2)-1,abs(v3)-1] if v4 != None: - self.face.append(abs(v4)-1) + if abs(v4) != abs(v1): + self.face.append(abs(v4)-1) else: #--parameter for polyline2d self.swidth = getit(data, 40, None) # start width self.ewidth = getit(data, 41, None) # end width @@ -2167,18 +2414,15 @@ class Circle: #---------------------------------------------------------------- radius = self.radius thic = set_thick(self.thic, settings) - if settings.var['curves_on']: - if False: # universal version - arc_res = 4 # ONLY 4 works well for point.handleTypes = [AUTO, AUTO] - start, end = 0.0, 360.0 - verts = calcArc(None, radius, start, end, arc_res, True) - c = Curve.New(obname) # create new curve data - curve = c.appendNurb(BezTriple.New(verts[0])) - for p in verts[1:-1]: - curve.append(BezTriple.New(p)) - for point in curve: - point.handleTypes = [AUTO, AUTO] - elif True: # universal version + width = 0.0 + if settings.var['lines_as'] == 4: # as thin_box + thic = settings.var['thick_min'] + width = settings.var['width_min'] + if settings.var['lines_as'] == 3: # as thin cylinder + cyl_rad = 0.5 * settings.var['width_min'] + + if settings.var['lines_as'] == 5: # draw CIRCLE as curve ------------- + if True: # universal version arc_res = settings.var['curve_arc'] #arc_res = 3 start, end = 0.0, 360.0 @@ -2214,9 +2458,10 @@ class Circle: #---------------------------------------------------------------- else: c.setFlag(c.getFlag() & ~6) # dont set top and button caps + c.setResolu(settings.var['curve_res']) c.update() - #remi --todo-----to check--------------------------- + #--todo-----to check--------------------------- ob = SCENE.objects.new(c) # create a new curve_object ob.loc = tuple(self.loc) if thic != 0.0: #hack: Blender<2.45 curve-extrusion @@ -2254,7 +2499,8 @@ class Circle: #---------------------------------------------------------------- start, end = 0.0 , 360.0 verts = calcArc(None, radius, start, end, arc_res, False) verts = verts[:-1] #list without last point/edge (cause by circle it is equal to the first point) - #print 'deb:circleDraw:edges:', edges #--------------- + #print 'deb:circleDraw: verts:', verts #--------------- + if thic != 0: len1 = len(verts) thic_verts = [] @@ -2395,7 +2641,7 @@ class Arc: #----------------------------------------------------------------- if settings.var['lines_as'] == 3: # as thin cylinder cyl_rad = 0.5 * settings.var['width_min'] - if settings.var['curves_on']: # draw ARC as curve ------------- + if settings.var['lines_as'] == 5: # draw ARC as curve ------------- arc_res = settings.var['curve_arc'] triples = True VectorTriples = calcArc(None, radius, start, end, arc_res, triples) @@ -2406,6 +2652,8 @@ class Arc: #----------------------------------------------------------------- for point in curve: point.handleTypes = [FREE, FREE] curve.flagU = 0 # 0 sets the curve not cyclic=open + arc.setResolu(settings.var['curve_res']) + arc.update() #important for handles calculation ob = SCENE.objects.new(arc) # create a new curve_object @@ -2420,8 +2668,8 @@ class Arc: #----------------------------------------------------------------- return ob else: # draw ARC as mesh -------------------- - arc = Mesh.New(obname) # create a new mesh - ob = SCENE.objects.new(arc) # create a new arc_object + me = Mesh.New(obname) # create a new mesh + ob = SCENE.objects.new(me) # create a new mesh_object # set a number of segments in entire circle arc_res = settings.var['arc_res'] * sqrt(radius) / sqrt(settings.var['arc_rad']) @@ -2430,34 +2678,19 @@ class Arc: #----------------------------------------------------------------- len1 = len(verts) #print 'deb:len1:', len1 #----------------------- if width != 0: - if False: - radius_out = radius + (0.5 * width) - radius_in = radius - (0.5 * width) - if radius_in <= 0.0: - radius_in = settings.var['dist_min'] - #radius_in = 0.0 - verts_in = [] - verts_out = [] - for point in verts: - pointVec = Mathutils.Vector(point) - pointVec = pointVec.normalize() - verts_in.append(list(radius_in * pointVec)) #vertex inside - verts_out.append(list(radius_out * pointVec)) #vertex outside - verts = verts_in + verts_out - else: - radius_out = radius + (0.5 * width) - radius_in = radius - (0.5 * width) - if radius_in <= 0.0: - radius_in = settings.var['dist_min'] - #radius_in = 0.0 - verts_in = [] - verts_out = [] - for point in verts: - pointVec = Mathutils.Vector(point) - pointVec = pointVec.normalize() - verts_in.append(list(radius_in * pointVec)) #vertex inside - verts_out.append(list(radius_out * pointVec)) #vertex outside - verts = verts_in + verts_out + radius_out = radius + (0.5 * width) + radius_in = radius - (0.5 * width) + if radius_in <= 0.0: + radius_in = settings.var['dist_min'] + #radius_in = 0.0 + verts_in = [] + verts_out = [] + for point in verts: + pointVec = Mathutils.Vector(point) + pointVec = pointVec.normalize() + verts_in.append(list(radius_in * pointVec)) #vertex inside + verts_out.append(list(radius_out * pointVec)) #vertex outside + verts = verts_in + verts_out #print 'deb:verts:', verts #--------------------- if thic != 0: @@ -2476,13 +2709,13 @@ class Arc: #----------------------------------------------------------------- f_end = [[len1+len1-1, 0+len1-1, len1+len1+len1-1, len1+len1+len1+len1-1]] faces = f_left + f_right + f_bottom + f_top + f_start + f_end - arc.verts.extend(verts) # add vertices to mesh - arc.faces.extend(faces) # add faces to the mesh + me.verts.extend(verts) # add vertices to mesh + me.faces.extend(faces) # add faces to the mesh if settings.var['meshSmooth_on']: # left and right side become smooth ---------------------- smooth_len = len(f_left) + len(f_right) for i in xrange(smooth_len): - arc.faces[i].smooth = True + me.faces[i].smooth = True # each MeshSide becomes vertexGroup for easier material assignment --------------------- if settings.var['vGroup_on']: # each MeshSide becomes vertexGroup for easier material assignment --------------------- @@ -2492,18 +2725,18 @@ class Arc: #----------------------------------------------------------------- for v in f_right: vg_right.extend(v) for v in f_top: vg_top.extend(v) for v in f_bottom: vg_bottom.extend(v) - arc.addVertGroup('side.left') ; arc.assignVertsToGroup('side.left', list(set(vg_left)), 1.0, replace) - arc.addVertGroup('side.right') ; arc.assignVertsToGroup('side.right', list(set(vg_right)), 1.0, replace) - arc.addVertGroup('side.top') ; arc.assignVertsToGroup('side.top', list(set(vg_top)), 1.0, replace) - arc.addVertGroup('side.bottom'); arc.assignVertsToGroup('side.bottom',list(set(vg_bottom)), 1.0, replace) - arc.addVertGroup('side.start'); arc.assignVertsToGroup('side.start', f_start[0], 1.0, replace) - arc.addVertGroup('side.end') ; arc.assignVertsToGroup('side.end', f_end[0], 1.0, replace) + me.addVertGroup('side.left') ; me.assignVertsToGroup('side.left', list(set(vg_left)), 1.0, replace) + me.addVertGroup('side.right') ; me.assignVertsToGroup('side.right', list(set(vg_right)), 1.0, replace) + me.addVertGroup('side.top') ; me.assignVertsToGroup('side.top', list(set(vg_top)), 1.0, replace) + me.addVertGroup('side.bottom'); me.assignVertsToGroup('side.bottom',list(set(vg_bottom)), 1.0, replace) + me.addVertGroup('side.start'); me.assignVertsToGroup('side.start', f_start[0], 1.0, replace) + me.addVertGroup('side.end') ; me.assignVertsToGroup('side.end', f_end[0], 1.0, replace) else: # if thick=0 - draw only flat ring faces = [[num, len1+num, len1+num+1, num+1] for num in xrange(len1 - 1)] - arc.verts.extend(verts) # add vertices to mesh - arc.faces.extend(faces) # add faces to the mesh + me.verts.extend(verts) # add vertices to mesh + me.faces.extend(faces) # add faces to the mesh elif thic != 0: thic_verts = [] @@ -2518,20 +2751,20 @@ class Arc: #----------------------------------------------------------------- #print 'deb:verts:', verts #--------------------- faces = [[num, num+1, num+len1+1, num+len1] for num in xrange(len1 - 1)] - arc.verts.extend(verts) # add vertices to mesh - arc.faces.extend(faces) # add faces to the mesh + me.verts.extend(verts) # add vertices to mesh + me.faces.extend(faces) # add faces to the mesh if settings.var['meshSmooth_on']: # left and right side become smooth ---------------------- for i in xrange(len(faces)): - arc.faces[i].smooth = True + me.faces[i].smooth = True else: edges = [[num, num+1] for num in xrange(len(verts)-1)] - arc.verts.extend(verts) # add vertices to mesh - arc.edges.extend(edges) # add edges to the mesh + me.verts.extend(verts) # add vertices to mesh + me.edges.extend(edges) # add edges to the mesh - #arc.update() - #ob = SCENE.objects.new(arc) # create a new arc_object - #ob.link(arc) + #me.update() + #ob = SCENE.objects.new(me) # create a new arc_object + #ob.link(me) ob.loc = tuple(center) #ob.loc = Mathutils.Vector(ob.loc) transform(self.extrusion, 0, ob) @@ -2582,30 +2815,44 @@ class Block: #----------------------------------------------------------------- """ if not obj.type == 'block': raise TypeError, "Wrong type %s for block object!" %obj.type + self.type = obj.type - self.data = obj.data[:] self.name = obj.name + self.data = obj.data[:] # required data - self.flags = obj.get_type(70)[0] - self.entities = dxfObject('block_contents') #creates empty entities_container for this block - self.entities.data = objectify([ent for ent in obj.data if type(ent) != list]) + self.flags = getit(obj, 70, 0) + self.anonim = self.flags & 1 #anonymous block generated by hatching, associative dimensioning, other + self.atrib = self.flags & 2 # has attribute definitions + self.xref = self.flags & 4 # is an external reference (xref) + self.xref_lay = self.flags & 8 # is an xref overlay + self.dep_ext = self.flags & 16 # is externally dependent + self.dep_res = self.flags & 32 # resolved external reference + self.xref_ext = self.flags & 64 # is a referenced external reference xref + #--todo--- if self.flag > 4: self.xref = True # optional data (with defaults) - self.path = getit(obj, 1, '') + self.path = getit(obj, 1, '') # Xref path name self.discription = getit(obj, 4, '') + self.entities = dxfObject('block_contents') #creates empty entities_container for this block + self.entities.data = objectify([ent for ent in obj.data if type(ent) != list]) + self.layer = getit(obj.data, 8, None) self.loc = self.get_loc(obj.data) + #print 'deb:Block %s data:\n%s' %(self.name, self.data) #------------ + #print 'deb:Block %s self.entities.data:\n%s' %(self.name, self.entities.data) #------------ + + def get_loc(self, data): """Gets the insert point of the block. """ loc = [0, 0, 0] - loc[0] = getit(data, 10, None) # 10 = x - loc[1] = getit(data, 20, None) # 20 = y - loc[2] = getit(data, 30, 0.0) # 30 = z + loc[0] = getit(data, 10, 0.0) # 10 = x + loc[1] = getit(data, 20, 0.0) # 20 = y + loc[2] = getit(data, 30, 0.0) # 30 = z return loc @@ -2626,9 +2873,10 @@ class Insert: #---------------------------------------------------------------- raise TypeError, "Wrong type %s for insert object!" %obj.type self.type = obj.type self.data = obj.data[:] + #print 'deb:Insert_init_ self.data:\n', self.data #----------- # required data - self.blockname = obj.get_type(2)[0] + self.name = obj.get_type(2)[0] # optional data (with defaults) self.rotation = getit(obj, 50, 0) @@ -2641,6 +2889,8 @@ class Insert: #---------------------------------------------------------------- self.rows, self.columns = self.get_array(obj.data) self.extrusion = get_extrusion(obj.data) + #self.flags = getit(obj.data, 66, 0) # + #self.attrib = self.flags & 1 def get_loc(self, data): @@ -2653,7 +2903,6 @@ class Insert: #---------------------------------------------------------------- return loc - def get_scale(self, data): """Gets the x/y/z scale factors of the insert. """ @@ -2664,7 +2913,6 @@ class Insert: #---------------------------------------------------------------- return scale - def get_array(self, data): """Returns the pair (row number, row spacing), (column number, column spacing). """ @@ -2675,9 +2923,38 @@ class Insert: #---------------------------------------------------------------- return (rows, rspace), (columns, cspace) + def get_target(self, data): + """Gets the origin location of the insert. + """ + loc = [0, 0, 0] + loc[0] = getit(data, 1011, 0.0) + loc[1] = getit(data, 1021, 0.0) + loc[2] = getit(data, 1031, 0.0) + return loc + + + def get_color(self, data): + """Gets the origin location of the insert. + """ + loc = [0, 0, 0] + loc[0] = getit(data, 1010, 0.0) + loc[1] = getit(data, 1020, 0.0) + loc[2] = getit(data, 1030, 0.0) + return loc + + + def get_ave_render(self, data): + """Gets the origin location of the insert. + """ + loc = [0, 0, 0] + loc[0] = getit(data, 1010, 0.0) + loc[1] = getit(data, 1020, 0.0) + loc[2] = getit(data, 1030, 0.0) + return loc + def __repr__(self): - return "%s: layer - %s, blockname - %s" %(self.__class__.__name__, self.layer, self.blockname) + return "%s: layer - %s, name - %s" %(self.__class__.__name__, self.layer, self.name) def draw(self, settings, deltaloc): @@ -2692,11 +2969,89 @@ class Insert: #---------------------------------------------------------------- insert object gives the location/scale/rotation of the block instances. """ - obname = settings.blocknamesmap[self.blockname] - obname = 'in_%s' %obname # create object name from block name - #obname = obname[:MAX_NAMELENGTH] + name = self.name.lower() + if name == 'ave_render': + if settings.var['lights_on']: #if lights support activated + a_data = get_ave_data(self.data) + # AVE_RENDER objects: + # 7:'Pref', 0:'Full Opt', 0:'Quick Opt', 1:'Scanl Opt', 2:'Raytr Opt', 0:'RFile Opt' + # 0:'Fog Opt', 0:'BG Opt', 0:'SCENE1','','','','','','','','','', + # '','','','','','','','','','','','', - if settings.drawTypes['insert']: #if insert_drawType activated + if a_data.key == 'SCENE': # define set of lights as blender group + scene_lights = 1 + elif False: # define set of lights as blender group + scene_lights = 1 + return + elif name == 'ave_global': + if settings.var['lights_on']: #if lights support activated + return + elif name == 'sh_spot': + if settings.var['lights_on']: #if lights support activated + obname = settings.blocknamesmap[self.name] + obname = 'sp_%s' %obname # create object name from block name + #obname = obname[:MAX_NAMELENGTH] + # blender: 'Lamp', 'Sun', 'Spot', 'Hemi', 'Area', or 'Photon' + li = Lamp.New('Spot', obname) + ob = SCENE.objects.new(li) + intensity = 2.0 #--todo-- ----------- + li.setEnergy(intensity) + target = self.get_target(self.data) + color = self.get_color(self.data) + li.R = color[0] + li.G = color[1] + li.B = color[2] + + ob.loc = tuple(self.loc) + transform(self.extrusion, 0, ob) + return ob + + elif name == 'overhead': + if settings.var['lights_on']: #if lights support activated + obname = settings.blocknamesmap[self.name] + obname = 'la_%s' %obname # create object name from block name + #obname = obname[:MAX_NAMELENGTH] + # blender: 'Lamp', 'Sun', 'Spot', 'Hemi', 'Area', or 'Photon' + li = Lamp.New('Lamp', obname) + ob = SCENE.objects.new(li) + intensity = 2.0 #--todo-- ----------- + li.setEnergy(intensity) + target = self.get_target(self.data) + color = self.get_color(self.data) + li.R = color[0] + li.G = color[1] + li.B = color[2] + + ob.loc = tuple(self.loc) + transform(self.extrusion, 0, ob) + return ob + + elif name == 'direct': + if settings.var['lights_on']: #if lights support activated + obname = settings.blocknamesmap[self.name] + obname = 'su_%s' %obname # create object name from block name + #obname = obname[:MAX_NAMELENGTH] + # blender: 'Lamp', 'Sun', 'Spot', 'Hemi', 'Area', or 'Photon' + li = Lamp.New('Sun', obname) + ob = SCENE.objects.new(li) + intensity = 2.0 #--todo-- ----------- + li.setEnergy(intensity) + color = self.get_color(self.data) + li.R = color[0] + li.G = color[1] + li.B = color[2] + + ob.loc = tuple(self.loc) + transform(self.extrusion, 0, ob) + return ob + + elif settings.drawTypes['insert']: #if insert_drawType activated + print 'deb:draw. settings.blocknamesmap:', settings.blocknamesmap #-------------------- + obname = settings.blocknamesmap[self.name] + obname = 'in_%s' %obname # create object name from block name + #obname = obname[:MAX_NAMELENGTH] + + # if material BYBLOCK def needed: use as placeholder a mesh-vertex instead of empty ob = SCENE.objects.new('Empty', obname) # create a new empty_object empty_size = 1.0 * settings.var['g_scale'] if empty_size < 0.01: empty_size = 0.01 #Blender limits (0.01-10.0) @@ -2704,19 +3059,22 @@ class Insert: #---------------------------------------------------------------- ob.drawSize = empty_size # get our block_def-group - block = settings.blocks(self.blockname) + block = settings.blocks(self.name) ob.DupGroup = block ob.enableDupGroup = True - #print 'deb:draw.block.deltaloc:', deltaloc #-------------------- - ob.loc = tuple(self.loc) - if deltaloc: - deltaloc = rotXY_Vec(self.rotation, deltaloc) - #print 'deb:draw.block.loc:', deltaloc #-------------------- - ob.loc = [ob.loc[0]+deltaloc[0], ob.loc[1]+deltaloc[1], ob.loc[2]+deltaloc[2]] - transform(self.extrusion, self.rotation, ob) - ob.size = tuple(self.scale) - return ob + if block.name.startswith('xr_'): + ob.name = 'xb_' + ob.name[3:] + + #print 'deb:draw.block.deltaloc:', deltaloc #-------------------- + ob.loc = tuple(self.loc) + if deltaloc: + deltaloc = rotXY_Vec(self.rotation, deltaloc) + #print 'deb:draw.block.loc:', deltaloc #-------------------- + ob.loc = [ob.loc[0]+deltaloc[0], ob.loc[1]+deltaloc[1], ob.loc[2]+deltaloc[2]] + transform(self.extrusion, self.rotation, ob) + ob.size = tuple(self.scale) + return ob @@ -2734,8 +3092,8 @@ class Ellipse: #--------------------------------------------------------------- self.data = obj.data[:] # required data - self.ratio = obj.get_type(40)[0] - self.start_angle = obj.get_type(41)[0] + self.ratio = obj.get_type(40)[0] # Ratio of minor axis to major axis + self.start_angle = obj.get_type(41)[0] # in radians self.end_angle = obj.get_type(42)[0] # optional data (with defaults) @@ -2747,7 +3105,6 @@ class Ellipse: #--------------------------------------------------------------- self.loc = self.get_loc(obj.data) self.major = self.get_major(obj.data) self.extrusion = get_extrusion(obj.data) - self.radius = sqrt(self.major[0]**2 + self.major[0]**2 + self.major[0]**2) def get_loc(self, data): @@ -2781,31 +3138,176 @@ class Ellipse: #--------------------------------------------------------------- def draw(self, settings): """for ELLIPSE: generate Blender_geometry. """ - # Generate the geometery + obname = 'el_%s' %self.layer # create object name from layer name + obname = obname[:MAX_NAMELENGTH] + center = self.loc - thic = set_thick(self.thic, settings) - - if settings.var['curves_on']: - ob = drawCurveArc(self) - else: - obname = 'el_%s' %self.layer # create object name from layer name - obname = obname[:MAX_NAMELENGTH] - me = Mesh.New(obname) # create a new mesh - ob = SCENE.objects.new(me) # create a new mesh_object - - major = Mathutils.Vector(self.major) - #remi--todo----AngleBetweenVecs makes abs(value)!----- - delta = Mathutils.AngleBetweenVecs(major, WORLDX) - radius = major.length + if True: start = degrees(self.start_angle) end = degrees(self.end_angle) + if abs(end - 360.0) < 0.00001: end = 360.0 + ellipse_closed = False + if end - start == 360.0: ellipse_closed = True + + else: # bug in AutoCAD_2002 dxf-exporter into r12 for ELLIPSE->POLYLINE_ARC + #print 'deb:calcEllipse---------:\n start=%s\n end=%s' %(self.start_angle, self.end_angle) #--------- + if self.start_angle > pi+pi: self.start_angle %= pi+pi + if self.end_angle > pi+pi: self.end_angle %= pi+pi + if abs(self.end_angle - pi - pi) < 0.00001: self.end_angle = pi + pi + ellipse_closed = False + if abs(self.end_angle - self.start_angle) == pi + pi: ellipse_closed = True + test = self.start_angle % pi + if test < 0.001 or pi - test < 0.001: start = self.start_angle + else: + start = atan(tan(self.start_angle) * self.ratio) + if start < 0.0: start += pi + if self.start_angle > pi: start += pi + test = self.end_angle % pi + if test < 0.001 or pi - test < 0.001: end = self.end_angle + else: + end = atan(tan(self.end_angle) * self.ratio) + if end < 0.0: end += pi + if self.end_angle > pi: end += pi + start = degrees(start) + end = degrees(end) + # rotation = Angle between major and WORLDX + # doesnt work, couse produces always positive value: rotation = Mathutils.AngleBetweenVecs(major, WORLDX) + if self.major[0] == 0: + rotation = 90.0 + if self.major[1] < 0: rotation += 180 + else: + rotation = degrees(atan(self.major[1] / self.major[0])) + if self.major[0] < 0: + rotation += 180.0 + + major = Mathutils.Vector(self.major) + #radius = sqrt(self.major[0]**2 + self.major[1]**2 + self.major[2]**2) + radius = major.length + #print 'deb:calcEllipse:\n center, radius, start, end:\n', center, radius, start, end #--------- + + thic = set_thick(self.thic, settings) + width = 0.0 + if settings.var['lines_as'] == 4: # as thin_box + thic = settings.var['thick_min'] + width = settings.var['width_min'] + if settings.var['lines_as'] == 3: # as thin cylinder + cyl_rad = 0.5 * settings.var['width_min'] + + if settings.var['lines_as'] == 5: # draw ELLIPSE as curve ------------- + arc_res = settings.var['curve_arc'] + triples = True + VectorTriples = calcArc(None, radius, start, end, arc_res, triples) + arc = Curve.New(obname) # create new curve data + curve = arc.appendNurb(BezTriple.New(VectorTriples[0])) + if ellipse_closed: + for p in VectorTriples[1:-1]: + curve.append(BezTriple.New(p)) + for point in curve: + point.handleTypes = [FREE, FREE] + curve.flagU = 1 # 0 sets the curve not cyclic=open + if settings.var['fill_on']: + arc.setFlag(6) # 2+4 set top and button caps + else: + arc.setFlag(arc.getFlag() & ~6) # dont set top and button caps + else: + for p in VectorTriples[1:]: + curve.append(BezTriple.New(p)) + for point in curve: + point.handleTypes = [FREE, FREE] + curve.flagU = 0 # 0 sets the curve not cyclic=open + + arc.setResolu(settings.var['curve_res']) + arc.update() #important for handles calculation + + ob = SCENE.objects.new(arc) # create a new curve_object + ob.loc = tuple(self.loc) + if thic != 0.0: #hack: Blender<2.45 curve-extrusion + thic = thic * 0.5 + arc.setExt1(1.0) # curve-extrusion: Blender2.45 accepts only (0.0 - 5.0) + ob.LocZ = thic + self.loc[2] + transform(self.extrusion, rotation, ob) + ob.SizeY *= self.ratio + if thic != 0.0: + ob.SizeZ *= abs(thic) + return ob + + + else: # draw ELLIPSE as mesh -------------------------------------- + me = Mesh.New(obname) # create a new mesh + ob = SCENE.objects.new(me) # create a new mesh_object # set a number of segments in entire circle arc_res = settings.var['arc_res'] * sqrt(radius) / sqrt(settings.var['arc_rad']) + + verts = calcArc(None, radius, start, end, arc_res, False) #verts = [list(point) for point in verts] - if thic != 0: - len1 = len(verts) + if False: #--todo--: if ellipse_closed: + verts = verts[:-1] #list without last point/edge (cause closed curve) + len1 = len(verts) + #print 'deb:len1:', len1 #----------------------- + if width != 0: + radius_out = radius + (0.5 * width) + radius_in = radius - (0.5 * width) + if radius_in <= 0.0: + radius_in = settings.var['dist_min'] + #radius_in = 0.0 + verts_in = [] + verts_out = [] + for point in verts: + pointVec = Mathutils.Vector(point) + pointVec = pointVec.normalize() + verts_in.append(list(radius_in * pointVec)) #vertex inside + verts_out.append(list(radius_out * pointVec)) #vertex outside + verts = verts_in + verts_out + + #print 'deb:verts:', verts #--------------------- + if thic != 0: + thic_verts = [] + thic_verts.extend([[point[0], point[1], point[2]+thic] for point in verts]) + if thic < 0.0: + thic_verts.extend(verts) + verts = thic_verts + else: + verts.extend(thic_verts) + f_bottom = [[num, num+1, len1+num+1, len1+num] for num in xrange(len1-1)] + f_top = [[num, len1+num, len1+num+1, num+1] for num in xrange(len1+len1, len1+len1+len1-1)] + f_left = [[num, len1+len1+num, len1+len1+num+1, num+1] for num in xrange(len1-1)] + f_right = [[num, num+1, len1+len1+num+1, len1+len1+num] for num in xrange(len1, len1+len1-1)] + f_start = [[0, len1, len1+len1+len1, len1+len1]] + f_end = [[len1+len1-1, 0+len1-1, len1+len1+len1-1, len1+len1+len1+len1-1]] + faces = f_left + f_right + f_bottom + f_top + f_start + f_end + + me.verts.extend(verts) # add vertices to mesh + me.faces.extend(faces) # add faces to the mesh + + if settings.var['meshSmooth_on']: # left and right side become smooth ---------------------- + smooth_len = len(f_left) + len(f_right) + for i in xrange(smooth_len): + me.faces[i].smooth = True + + if settings.var['vGroup_on']: + # each MeshSide becomes vertexGroup for easier material assignment --------------------- + replace = Blender.Mesh.AssignModes.REPLACE #or .AssignModes.ADD + vg_left, vg_right, vg_top, vg_bottom = [], [], [], [] + for v in f_left: vg_left.extend(v) + for v in f_right: vg_right.extend(v) + for v in f_top: vg_top.extend(v) + for v in f_bottom: vg_bottom.extend(v) + me.addVertGroup('side.left') ; me.assignVertsToGroup('side.left', list(set(vg_left)), 1.0, replace) + me.addVertGroup('side.right') ; me.assignVertsToGroup('side.right', list(set(vg_right)), 1.0, replace) + me.addVertGroup('side.top') ; me.assignVertsToGroup('side.top', list(set(vg_top)), 1.0, replace) + me.addVertGroup('side.bottom'); me.assignVertsToGroup('side.bottom',list(set(vg_bottom)), 1.0, replace) + me.addVertGroup('side.start'); me.assignVertsToGroup('side.start', f_start[0], 1.0, replace) + me.addVertGroup('side.end') ; me.assignVertsToGroup('side.end', f_end[0], 1.0, replace) + + + else: # if thick=0 - draw only flat ring + faces = [[num, len1+num, len1+num+1, num+1] for num in xrange(len1 - 1)] + me.verts.extend(verts) # add vertices to mesh + me.faces.extend(faces) # add faces to the mesh + + elif thic != 0: thic_verts = [] thic_verts.extend([[point[0], point[1], point[2]+thic] for point in verts]) if thic < 0.0: @@ -2815,21 +3317,28 @@ class Ellipse: #--------------------------------------------------------------- verts.extend(thic_verts) faces = [] #print 'deb:len1:', len1 #----------------------- - #print 'deb:verts:', verts #---------------------- + #print 'deb:verts:', verts #--------------------- faces = [[num, num+1, num+len1+1, num+len1] for num in xrange(len1 - 1)] - me.verts.extend(verts) # add vertices to mesh - me.faces.extend(faces) # add faces to the mesh + me.verts.extend(verts) # add vertices to mesh + me.faces.extend(faces) # add faces to the mesh + if settings.var['meshSmooth_on']: # left and right side become smooth ---------------------- + for i in xrange(len(faces)): + me.faces[i].smooth = True + else: edges = [[num, num+1] for num in xrange(len(verts)-1)] - me.verts.extend(verts) # add vertices to mesh - me.edges.extend(edges) # add edges to the mesh + me.verts.extend(verts) # add vertices to mesh + me.edges.extend(edges) # add edges to the mesh - ob.loc = tuple(center) - ob.SizeY = self.ratio - transform(self.extrusion, 0, ob) - - return ob + #print 'deb:calcEllipse transform rotation: ', rotation #--------- + ob.loc = tuple(center) + #old ob.SizeY = self.ratio + transform(self.extrusion, rotation, ob) + #old transform(self.extrusion, 0, ob) + ob.SizeY *= self.ratio + + return ob @@ -2945,6 +3454,8 @@ class Face: #----------------------------------------------------------------- #--------------------------------------------------------------------------------------- # type to object maping (sorted-dictionary for f_obiectify ONLY!, format={'key':Class} ) type_map = { + 'vport':Vport, + 'view':View, 'layer':Layer, 'block_record':BlockRecord, 'block':Block, @@ -2992,14 +3503,14 @@ def objectify(data): #--------------------------------------------------------- if item.type == 'vertex': #print 'deb:objectify gosub Vertex--------' #------------- v = Vertex(item) - if pline.spline: # Bspline-curve + if pline.spline: # if Bspline-curve # then for Blender-mesh filter only additional_vertices # OR # then for Blender-curve filter only spline_control_vertices if (v.spline and not curves_on) or (curves_on and v.splin2): #correct for real NURBS-import #if (v.spline and not curves_on) or (curves_on and not v.splin2): #fake for Bezier-emulation of NURBS-import pline.points.append(v) - elif pline.curved: # Bezier-curve + elif pline.curved: # if Bezier-curve # then for Blender-mesh filter only curve_additional_vertices # OR # then for Blender-curve filter curve_control_vertices @@ -3015,12 +3526,27 @@ def objectify(data): #--------------------------------------------------------- index -= 1 #so go back one step break objects.append(pline) + elif type(item) != list and item.type in ['block', 'insert']: + if not settings.var['block_nn'] and item.name.startswith('*X'): + #print 'deb:objectify item.type:"%s", item.name:"%s"' %(item.type, item.name) #------------ + pass + elif settings.var['blockFilter_on'] and not settings.accepted_block(item.name): + pass + else: + try: + objects.append(type_map[item.type](item)) + except TypeError: + pass elif type(item) != list and item.type in known_types: # proccess the object and append the resulting object - objects.append(type_map[item.type](item)) + try: + objects.append(type_map[item.type](item)) + except TypeError: + pass else: - # we will just let the data pass un-harrased - objects.append(item) + #we will just let the data pass un-harrased + #objects.append(item) + pass index += 1 #print 'deb:objectify objects:\n', objects #------------ #print 'deb:objectify END %%%%%%%%' #------------ @@ -3052,24 +3578,28 @@ class MatColors: #------------------------------------------------------------- If a layer name is provided, the color of that layer is used. """ - if color == None: - color = 256 # color 256=BYLAYER + if color == None: color = 256 # color 256=BYLAYER if type(color) == str: # looking for color of LAYER named "color" #--todo---bug with ARC from ARC-T0.DXF layer="T-3DARC-1"----- #print 'deb:color is string:--------: ', color #try: - #color = self.layersmap[color].color + #color = layersmap[color].color #print 'deb:color=self.map[color].color:', color #------------------ #except KeyError: #layer = Layer(name=color, color=256, frozen=False) - #self.layersmap[color] = layer + #layersmap[color] = layer #color = 0 - color = layersmap[color].color + if layersmap: color = layersmap[color].color + if color == 256: # color 0 = BYLAYER + #--todo-- should looking for color of LAYER + #if layersmap: color = layersmap[color].color + color = 3 if color == 0: # color 0 = BYBLOCK #--todo-- should looking for color of paret-BLOCK - #color = layersmap[color].color - pass + #if layersmap: color = layersmap[color].color + color = 3 color = abs(color) # cause the value could be nagative = means the layer is turned off + if color not in self.colMaterials.keys(): self.add(color) return self.colMaterials[color] @@ -3116,7 +3646,8 @@ class MatLayers: #------------------------------------------------------------- layername_short = layername if layername in layernamesmap.keys(): layername_short = layernamesmap[layername] - colorlayername = str(color) + layername_short + colorlayername = layername_short + if color: colorlayername = str(color) + colorlayername if colorlayername not in self.layMaterials.keys(): self.add(layername, color, colorlayername) return self.layMaterials[colorlayername] @@ -3130,14 +3661,17 @@ class MatLayers: #------------------------------------------------------------- #print 'deb:MatLayers material: ', mat #---------- #global settings #print 'deb:MatLayers material_from: ', settings.var['material_from'] #---------- - if settings.var['material_from'] == 3: mat_color = color - elif layersmap: mat_color = layersmap[layername].color + if settings.var['material_from'] == 3 and color: + if color == 0 or color == 256: mat_color = 3 + else: mat_color = color + elif layersmap and layername: + mat_color = layersmap[layername].color else: mat_color = 3 #print 'deb:MatLayers color: ', color #----------- #print 'deb:MatLayers mat_color: ', mat_color #----------- - mat.setRGBCol(color_map[mat_color]) - mat.mode |= Material.Modes.SHADELESS - mat.mode |= Material.Modes.WIRE + mat.setRGBCol(color_map[abs(mat_color)]) + #mat.mode |= Material.Modes.SHADELESS + #mat.mode |= Material.Modes.WIRE # try: mat.setMode('Shadeless', 'Wire') #work-around for 2.45rc-bug # except: pass self.layMaterials[colorlayername] = mat @@ -3160,7 +3694,7 @@ class Blocks: #---------------------------------------------------------------- """ self.blocksmap = blocksmap #a dictionary mapping block_name:block_data self.settings = settings - self.blocks = {} #container for blocks + self.blocks = {} #container for blender groups representing blocks def __call__(self, name=None): @@ -3179,13 +3713,32 @@ class Blocks: #---------------------------------------------------------------- def addBlock(self, name): """Create a new 'block group' for the block name. """ - - block_def = Group.New('bl_%s' %name) # Blender groupObject contains definition of BLOCK block = self.blocksmap[name] + prefix = 'bl' + if block.xref: prefix = 'xr' + blender_group = Group.New('%s_%s' %(prefix,name)) # Blender groupObject contains definition of BLOCK + block_def = [blender_group, block.loc] self.settings.write("\nDrawing block:\'%s\' ..." % name) - drawEntities(block.entities, self.settings, block_def) + + if block.xref: + obname = 'xr_%s' %name # create object name from xref block name + #obname = obname[:MAX_NAMELENGTH] + # if material BYBLOCK def needed: use as placeholder a mesh-vertex instead of empty + ob = SCENE.objects.new('Empty', obname) # create a new empty_object + empty_size = 1.0 * settings.var['g_scale'] + if empty_size < 0.01: empty_size = 0.01 #Blender limits (0.01-10.0) + elif empty_size > 10.0: empty_size = 10.0 + ob.drawSize = empty_size + ob.loc = tuple(block.loc) + ob.properties['xref_path'] = block.path + ob.layers = [19] + insertFlag=True; blockFlag=True + global oblist + oblist.append((ob, insertFlag, blockFlag)) + else: + drawEntities(block.entities, self.settings, block_def) self.settings.write("Drawing block:\'%s\' done!" %name) - self.blocks[name] = block_def + self.blocks[name] = blender_group @@ -3219,14 +3772,18 @@ class Settings: #-------------------------------------------------------------- '0' ] - self.var['blockFilter_on'] = False #deb:remi------------ - self.acceptedBlocks = ['BOX01', + #self.var['blockFilter_on'] = 0 #deb:remi------------ + self.acceptedBlocks = ['WALL_1871', 'BOX02' ] + self.unwantedBlocks = ['BOX05', + 'BOX04' + ] def update(self, keywords, drawTypes): """update all the important settings used by the draw functions. + mostly used after loading parameters from INI-file """ for k, v in keywords.iteritems(): @@ -3236,6 +3793,13 @@ class Settings: #-------------------------------------------------------------- self.drawTypes[t] = v #print 'deb:settings_update drawType %s= %s' %(t, self.drawTypes[t]) #-------------- + self.drawTypes['arc'] = self.drawTypes['line'] + self.drawTypes['circle'] = self.drawTypes['line'] + self.drawTypes['ellipse'] = self.drawTypes['line'] + self.drawTypes['trace'] = self.drawTypes['solid'] + self.drawTypes['insert'] = self.drawTypes['block'] + #self.drawTypes['vport'] = self.drawTypes['view'] + #print 'deb:self.drawTypes', self.drawTypes #--------------- @@ -3244,21 +3808,24 @@ class Settings: #-------------------------------------------------------------- """ #de: paßt die distance parameter an globalScale - if self.var['g_scale'] != 1: + if self.var['g_scale'] != 1.0: self.var['dist_min'] = self.var['dist_min'] / self.var['g_scale'] self.var['thick_min'] = self.var['thick_min'] / self.var['g_scale'] self.var['width_min'] = self.var['width_min'] / self.var['g_scale'] self.var['arc_rad'] = self.var['arc_rad'] / self.var['g_scale'] + self.g_origin = Mathutils.Vector(self.var['g_originX'], self.var['g_originY'], self.var['g_originZ']) + # First sort out all the section_items sections = dict([(item.name, item) for item in drawing.data]) # The section:header may be omited if 'header' in sections.keys(): - self.write("Found section:header!") + self.write("found section:header") else: self.write("File contains no section:header!") + if self.var['optimization'] == 0: self.var['one_mesh_on'] = 0 # The section:tables may be partialy or completely missing. self.layersTable = False self.colMaterials = MatColors({}) #A container for dxf-color based materials @@ -3267,44 +3834,101 @@ class Settings: #-------------------------------------------------------------- global layersmap, layernamesmap layersmap, layernamesmap = {}, {} if 'tables' in sections.keys(): - self.write("Found section:tables!") - # First sort out all the tables - tables = dict([(item.name, item) for item in sections["tables"].data]) - if 'layer' in tables.keys(): - self.write("Found table:layers!") - self.layersTable = True + self.write("found section:tables") + for table in drawing.tables.data: + if table.name == 'layer': + self.write("found table:layers") + layers = table + elif table.name == 'view': + print "found table:view" + views = table + elif table.name == 'vport': + print "found table:vport" + vports = table + if layers: #---------------------------------- # Read the layers table and get the layer colors - layersmap, layernamesmap = getLayersmap(drawing) + layersmap, layernamesmap = getLayersmap(layers) self.colMaterials = MatColors(layersmap) self.layMaterials = MatLayers(layersmap) else: self.write("File contains no table:layers!") + + + if views: #---------------------------------- + if self.var['views_on']: + global oblist + for item in views.data: + if type(item) != list and item.type == 'view': + #print 'deb:settings_valid views dir(item)=', dir(item) #------------- + #print 'deb:settings_valid views item=', item #------------- + ob = item.draw(self) + #viewsmap[item.name] = [item.length] + #--todo-- add to obj_list for global.Scaling + insertFlag, blockFlag = False, False + oblist.append((ob, insertFlag, blockFlag)) + + else: + self.write("File contains no table:views!") + + + if vports: #---------------------------------- + if self.var['views_on']: + global oblist + for item in vports.data: + if type(item) != list and item.type == 'vport': + #print 'deb:settings_valid views dir(item)=', dir(item) #------------- + #print 'deb:settings_valid views item=', item #------------- + ob = item.draw(self) + #viewsmap[item.name] = [item.length] + #--todo-- add to obj_list for global.Scaling + insertFlag, blockFlag = False, False + oblist.append((ob, insertFlag, blockFlag)) + else: + self.write("File contains no table:vports!") + + else: self.write("File contains no section:tables!") self.write("File contains no table:layers!") + # The section:blocks may be omited if 'blocks' in sections.keys(): - self.write("Found section:blocks!") + self.write("found section:blocks") # Read the block definitions and build our block object - if self.drawTypes['insert']: #if drawing of type 'Insert' activated - blocksmap, self.blocknamesmap, self.obj_number = getBlocksmap(drawing) #Build a dictionary of blockname:block_data pairs + if self.drawTypes['insert']: #if support for entity type 'Insert' is activated + #Build a dictionary of blockname:block_data pairs + blocksmap, self.obj_number = getBlocksmap(drawing, layersmap, self.var['layFrozen_on']) + self.blocknamesmap = getBlocknamesmap(blocksmap) self.blocks = Blocks(blocksmap, self) # initiates container for blocks_data - - #print 'deb: self.obj_number', self.obj_number #---------- + self.usedBlocks = blocksmap.keys() + #print 'deb:settings_valid self.usedBlocks', self.usedBlocks #---------- + else: + self.write("ignored, because support for BLOCKs is turn off!") + #print 'deb:settings_valid self.obj_number', self.obj_number #---------- else: self.write("File contains no section:blocks!") self.drawTypes['insert'] = False # The section:entities if 'entities' in sections.keys(): - self.write("Found section:entities!") + self.write("found section:entities") self.obj_number += len(drawing.entities.data) - #print 'deb: self.obj_number', self.obj_number #---------- + #print 'deb:settings_valid self.obj_number', self.obj_number #---------- self.obj_number = 1.0 / self.obj_number + def accepted_block(self, name): + if name not in self.usedBlocks: return False + if name in self.unwantedBlocks: return False + elif name in self.acceptedBlocks: return True + #elif (name.find('*X')+1): return False + #elif name.startswith('3'): return True + #elif name.endswith('H'): return False + return True + + def write(self, text, newline=True): """Wraps the built-in print command in a optimization check. """ @@ -3334,7 +3958,7 @@ class Settings: #-------------------------------------------------------------- """Given a layer name, and return its visible status. """ # if layer is off then color_index is negative - if layersmap[layername].color < 0: return True + if layersmap and layersmap[layername].color < 0: return True #print 'deb:layer_isOff: layer is ON' #--------------- return False @@ -3342,50 +3966,57 @@ class Settings: #-------------------------------------------------------------- def layer_isFrozen(self, layername): # no more used ------- """Given a layer name, and return its frozen status. """ - if layersmap[layername].frozen: return True + if layersmap and layersmap[layername].frozen: return True #print 'deb:layer_isFrozen: layer is not FROZEN' #--------------- return False def analyzeDXF(dxfFile): #--------------------------------------- - """list LAYER and BLOCK dependences into textfile + """list statistics about LAYER and BLOCK dependences into textfile.INF """ Window.WaitCursor(True) # Let the user know we are thinking - print 'start reading DXF file: %s.' % dxfFile + print 'reading DXF file: %s.' % dxfFile time1 = Blender.sys.time() #time marker1 drawing = readDXF(dxfFile, objectify) - print 'finished reading DXF file in %.4f sec.' % (Blender.sys.time()-time1) - Window.WaitCursor(False) + print 'finish reading in %.4f sec.' % (Blender.sys.time()-time1) # First sort out all the section_items sections = dict([(item.name, item) for item in drawing.data]) # The section:header may be omited - if 'header' in sections.keys(): print "Found section:header!" + if 'header' in sections.keys(): print "found section:header" else: print "File contains no section:header!" # The section:tables may be partialy or completely missing. layersTable = False global layersmap layersmap = {} + viewsmap = {} + vportsmap = {} + layersmap_str = '#File contains no table:layers!' + viewsmap_str = '#File contains no table:views!' + vportsmap_str = '#File contains no table:vports!' if 'tables' in sections.keys(): - print "Found section:tables!" + print "found section:tables" for table in drawing.tables.data: if table.name == 'layer': - print "Found table:layers!" + print "found table:layers" layers = table - break - if layers: - layersmap = {} + elif table.name == 'view': + print "found table:view" + views = table + elif table.name == 'vport': + print "found table:vport" + vports = table + if layers: #---------------------------------- for item in layers.data: if type(item) != list and item.type == 'layer': #print dir(item) layersmap[item.name] = [item.color, item.frozen] #print 'deb:analyzeDXF: layersmap=' , layersmap #------------- - layersmap_str = '#list of LAYERs: layername, layercolor, frozen\n' - + layersmap_str = '#list of LAYERs: name, color, frozen_status ---------------------------\n' key_list = layersmap.keys() key_list.sort() for key in key_list: @@ -3397,58 +4028,119 @@ def analyzeDXF(dxfFile): #--------------------------------------- #print 'deb:analyzeDXF: layersmap_str=\n' , layersmap_str #------------- else: print "File contains no table:layers!" + + if views: #---------------------------------- + for item in views.data: + if type(item) != list and item.type == 'view': + #print dir(item) + viewsmap[item.name] = [item.length] + #print 'deb:analyzeDXF: viewsmap=' , viewsmap #------------- + viewsmap_str = '#list of VIEWs: name, focus_length ------------------------------------\n' + key_list = viewsmap.keys() + key_list.sort() + for key in key_list: + #for view_name, view_data in viewsmap.iteritems(): + view_name, view_data = key, viewsmap[key] + view_str = '\'%s\': length=%s' %(view_name,view_data[0])#------------- + #if view_data[1]: view_str += ', something' + viewsmap_str += view_str + '\n' + #print 'deb:analyzeDXF: layersmap_str=\n' , layersmap_str #------------- + else: + print "File contains no table:views!" + + if vports: #---------------------------------- + for item in vports.data: + if type(item) != list and item.type == 'vport': + #print dir(item) + vportsmap[item.name] = [item.length] + #print 'deb:analyzeDXF: vportsmap=' , vportsmap #------------- + vportsmap_str = '#list of VPORTs: name, focus_length -----------------------------------\n' + key_list = vportsmap.keys() + key_list.sort() + for key in key_list: + #for vport_name, vport_data in vportsmap.iteritems(): + vport_name, vport_data = key, vportsmap[key] + vport_str = '\'%s\': length=%s' %(vport_name,vport_data[0])#------------- + #if vport_data[1]: vport_str += ', something' + vportsmap_str += vport_str + '\n' + #print 'deb:analyzeDXF: vportsmap_str=\n' , vportsmap_str #------------- + else: + print "File contains no table:vports!" + else: print "File contains no section:tables!" - print "File contains no table:layers!" + print "File contains no tables:layers,views,vports!" # The section:blocks may be omited if 'blocks' in sections.keys(): - print "Found section:blocks!" + print "found section:blocks" blocksmap = {} for item in drawing.blocks.data: #print 'deb:getBlocksmap item=' ,item #-------- #print 'deb:getBlocksmap item.entities=' ,item.entities #-------- #print 'deb:getBlocksmap item.entities.data=' ,item.entities.data #-------- if type(item) != list and item.type == 'block': - insertList = [] + xref = False + if item.xref: xref = True + childList = [] + used = False for item2 in item.entities.data: if type(item2) != list and item2.type == 'insert': - #print dir(item2) - item2str = [item2.blockname, item2.layer, item2.color_index, item2.scale, item2.space] - insertList.append(item2str) - try: - blocksmap[item.name] = insertList - except KeyError: - # annon block - print 'Cannot map "%s" - "%s" as Block!' %(item.name, item) + #print 'deb:getBlocksmap dir(item2)=', dir(item2) #---------- + item2str = [item2.name, item2.layer, item2.color_index, item2.scale, item2.space] + childList.append(item2str) + try: blocksmap[item.name] = [used, childList, xref] + except KeyError: print 'Cannot map "%s" - "%s" as Block!' %(item.name, item) #print 'deb:analyzeDXF: blocksmap=' , blocksmap #------------- - blocksmap_str = '#list of BLOCKs: child, layer, color, scale, space\n' + + for item2 in drawing.entities.data: + if type(item2) != list and item2.type == 'insert': + if not layersmap or (layersmap and not layersmap[item2.layer][1]): #if insert_layer is not frozen + blocksmap[item2.name][0] = True # marked as world used BLOCK + + key_list = blocksmap.keys() + key_list.reverse() + for key in key_list: + if blocksmap[key][0]: #if used + for child in blocksmap[key][1]: + if not layersmap or (layersmap and not layersmap[child[1]][1]): #if insert_layer is not frozen + blocksmap[child[0]][0] = True # marked as used BLOCK + + blocksmap_str = '#list of BLOCKs: name:(unused)(xref) -[child_name, layer, color, scale, space]-------\n' key_list = blocksmap.keys() key_list.sort() for key in key_list: #for block_name, block_data in blocksmap.iteritems(): block_name, block_data = key, blocksmap[key] - block_str = '\''+block_name + '\':\n' #------------- - blocksmap_str += block_str + block_str = '\'%s\': ' %(block_name) #------------- + used = '(unused)' + if block_data[0]: used = '' +# else: used = '(unused)' + xref = '' + if block_data[2]: xref = '(xref)' + blocksmap_str += block_str + used + xref +'\n' if block_data: - for block_item in block_data: + for block_item in block_data[1]: block_data_str = ' - %s\n' %block_item blocksmap_str += block_data_str #print 'deb:analyzeDXF: blocksmap_str=\n' , blocksmap_str #------------- else: + blocksmap_str = '#File contains no section:blocks!' print "File contains no section:blocks!" - output_str = '%s\n%s' %(layersmap_str, blocksmap_str) - infFile = dxfFile[:-4] + '_DXF.inf' # replace last char:'.dxf' with '.INF' + Window.WaitCursor(False) + output_str = '%s\n%s\n%s\n%s' %(viewsmap_str, vportsmap_str, layersmap_str, blocksmap_str) + infFile = dxfFile[:-4] + '_DXF.INF' # replace last char:'.dxf' with '_DXF.inf' try: f = file(infFile, 'w') - f.write(INFFILE_HEADER + '\n# this is a comment line\n') + f.write(INFFILE_HEADER + '\n# this is a comment line\n\n') f.write(output_str) f.close() - Draw.PupMenu('DXF importer: INF-file: Done!%t|see listing of DXF-model saved in:|' + '\'%s\'' %infFile) + Draw.PupMenu('DXF importer: report saved in INF-file:%t|' + '\'%s\'' %infFile) except: - Draw.PupMenu('DXF importer: INF-file: Error!%t|failure by writing to ' + '\'%s\'|no listings saved!' %infFile) - + Draw.PupMenu('DXF importer: ERROR by writing report in INF-file:%t|' + '\'%s\'' %infFile) + finally: + f.close() @@ -3467,17 +4159,9 @@ def main(dxfFile): #---------------#############################----------- cur_COUNTER = 0 try: - print "Getting settings..." - global GUI_A, GUI_B - if GUI_A['g_scale_on'].val: - if GUI_A['g_scale_as'].val == 6: #scale inches to meters - GUI_A['g_scale'].val = 0.02540 - elif GUI_A['g_scale_as'].val == 7: #scale feets to meters - GUI_A['g_scale'].val = 0.30480 - elif GUI_A['g_scale_as'].val == 8: #scale yards to meters - GUI_A['g_scale'].val = 0.91440 - else: GUI_A['g_scale'].val = 10.0 ** int(GUI_A['g_scale_as'].val) - else: + #print "Getting settings..." + global GUI_A, GUI_B, g_scale_as + if not GUI_A['g_scale_on'].val: GUI_A['g_scale'].val = 1.0 keywords = {} @@ -3505,45 +4189,51 @@ def main(dxfFile): #---------------#############################----------- #print 'deb: dxfFile file: ', dxfFile #---------------------- if dxfFile.lower().endswith('.dxf') and sys.exists(dxfFile): Window.WaitCursor(True) # Let the user know we are thinking - print 'start reading DXF file: %s.' % dxfFile + print 'reading file: %s.' % dxfFile time1 = Blender.sys.time() #time marker1 drawing = readDXF(dxfFile, objectify) - print 'finished reading DXF file in %.4f sec.' % (Blender.sys.time()-time1) + print 'reading finished in %.4f sec.' % (Blender.sys.time()-time1) Window.WaitCursor(False) else: - if UI_MODE: Draw.PupMenu('DXF importer: EXIT----------!%t| no valid DXF-file selected!') - print "DXF importer: error, no DXF-file selected. Abort!" + if UI_MODE: Draw.PupMenu('DXF importer: Alert!%t| no valid DXF-file selected!') + print "DXF importer: Alert! - no valid DXF-file selected." Window.WaitCursor(False) if editmode: Window.EditMode(1) # and put things back how we fond them return None - settings.validate(drawing) - - Window.WaitCursor(True) # Let the user know we are thinking - settings.write("\n\nDrawing entities...") - # Draw all the know entity types in the current scene global oblist oblist = [] # a list of all created AND linked objects for final f_globalScale time2 = Blender.sys.time() #time marker2 + Window.WaitCursor(True) # Let the user know we are thinking + settings.write("\n\nDrawing entities...") + + settings.validate(drawing) + + global activObjectLayer, activObjectName + activObjectLayer, activObjectName = None, None + drawEntities(drawing.entities, settings) #print 'deb:drawEntities after: oblist:', oblist #----------------------- if oblist: # and settings.var['g_scale'] != 1: globalScale(oblist, settings.var['g_scale']) - # Set the visable layers + # Set visibility for all layers on all View3d + #Window.ViewLayers([i+1 for i in range(18)]) # for 2.45 SCENE.setLayers([i+1 for i in range(18)]) SCENE.update(1) - #Blender.Redraw(-1) SCENE.objects.selected = [i[0] for i in oblist] #select only the imported objects #SCENE.objects.selected = SCENE.objects #select all objects in current scene Blender.Redraw() time_text = Blender.sys.time() - time2 Window.WaitCursor(False) - message = 'DXF Import to Blender: done in %.4f sec. --------------------' % time_text + if settings.var['paper_space_on']: space = 'from paper space' + else: space = 'from model space' + ob_len = len(oblist) + message = ' %s objects imported %s in %.4f sec. -----DONE-----' % (ob_len, space, time_text) settings.progress(1.0/settings.obj_number, 'DXF import done!') print message #settings.write(message) @@ -3561,16 +4251,15 @@ def getOCS(az): #-------------------------------------------------------------- """An implimentation of the Arbitrary Axis Algorithm. """ #decide if we need to transform our coords - if az[0] == 0 and az[1] == 0: - if az[2] == 1.0: + #if az[0] == 0 and az[1] == 0: + if abs(az[0]) < 0.00001 and abs(az[1]) < 0.00001: + if az[2] > 0.0: return False - elif az[2] == -1.0: + elif az[2] < 0.0: ax = Mathutils.Vector(-1.0, 0, 0) ay = Mathutils.Vector(0, 1.0, 0) az = Mathutils.Vector(0, 0, -1.0) return ax, ay, az - #elif abs(az[0]) < 0.0001 and abs(az[1]) < 0.0001: - # return False az = Mathutils.Vector(az) @@ -3625,14 +4314,9 @@ def rotXY_Vec(rotation, vec): #------------------------------------------------ -def getLayersmap(drawing): #------------------------------------------------------ - """Build two dictionaries: 1.layername:layer pairs and 2.layername:layername_short +def getLayersmap(layers): #------------------------------------------------------ + """Build two dictionaries: 1.layername:layer object, and 2.layername:layername_short """ - tables = drawing.tables - for table in tables.data: - if table.name == 'layer': - layers = table - break layersmap = {} layernamesmap = {} for item in layers.data: @@ -3645,39 +4329,77 @@ def getLayersmap(drawing): #--------------------------------------------------- suffix = str(i) layername_short = layername_short[:-2] + suffix layernamesmap[item.name] = layername_short + + #print 'deb:getLayersmap layersmap:\n', layersmap #------------ + #print 'deb:getLayersmap layernamesmap:\n', layernamesmap #------------ return layersmap, layernamesmap - -def getBlocksmap(drawing): #-------------------------------------------------------- - """Build a dictionary of blockname:block_data pairs and 2.blockname:blockname_short pairs + +def getBlocksmap(drawing, layersmap, layFrozen_on=False): #-------------------------------------------------------- + """Build a dictionary of blockname:block_data pairs """ - blocksmap = {} - blocksmap_short = {} - blocknamesmap = {} - obj_number = 0 + usedblocks = {} for item in drawing.blocks.data: - #print 'deb:getBlocksmap item=' ,item #-------- - #print 'deb:getBlocksmap item.entities=' ,item.entities #-------- - #print 'deb:getBlocksmap item.entities.data=' ,item.entities.data #-------- + #print 'deb:getBlocksmap item=%s\n i.entities=%s\n i.data=%s' %(item,item.entities,item.entities.data) if type(item) != list and item.type == 'block': + childList = [] + used = False + for item2 in item.entities.data: + if type(item2) != list and item2.type == 'insert': + #print 'deb:getBlocksmap dir(item2)=', dir(item2) #---------- + item2str = [item2.name, item2.layer] + childList.append(item2str) + try: usedblocks[item.name] = [used, childList] + except KeyError: print 'Cannot map "%s" - "%s" as Block!' %(item.name, item) + #print 'deb:getBlocksmap: usedblocks=' , usedblocks #------------- + print 'deb:getBlocksmap: layersmap=' , layersmap #------------- + + for item in drawing.entities.data: + if type(item) != list and item.type == 'insert': + if not layersmap or (not layersmap[item.layer].frozen or layFrozen_on): #if insert_layer is not frozen + try: usedblocks[item.name][0] = True + except: pass + + key_list = usedblocks.keys() + key_list.reverse() + for key in key_list: + if usedblocks[key][0]: #if parent used, then set used also all child blocks + for child in usedblocks[key][1]: + if not layersmap or (layersmap and not layersmap[child[1]].frozen): #if insert_layer is not frozen + usedblocks[child[0]][0] = True # marked as used BLOCK + + usedblocks = [i for i in usedblocks.keys() if usedblocks[i][0]] + #print 'deb:getBlocksmap: usedblocks=' , usedblocks #------------- + obj_number = 0 + blocksmap = {} + for item in drawing.blocks.data: + if type(item) != list and item.type == 'block' and item.name in usedblocks: + #if item.name.startswith('*X'): #--todo-- obj_number += len(item.entities.data) - try: - blocksmap[item.name] = item - except KeyError: - # annon block - print 'Cannot map "%s" - "%s" as Block!' %(item.name, item) + try: blocksmap[item.name] = item + except KeyError: print 'Cannot map "%s" - "%s" as Block!' %(item.name, item) + - blockname_short = item.name[:MAX_NAMELENGTH-1] - i = 0 #sufix for blockname cause Blender-objectnamelength-limit - while blockname_short in blocknamesmap.keys(): - i += 1 - suffix = str(i) - blockname_short = blockname_short[:-2] + suffix - blocknamesmap[item.name] = blockname_short + #print 'deb:getBlocksmap: blocksmap:\n', blocksmap #------------ + return blocksmap, obj_number - return blocksmap, blocknamesmap, obj_number +def getBlocknamesmap(blocksmap): #-------------------------------------------------------- + """Build a dictionary of blockname:blockname_short pairs + """ + #print 'deb:getBlocknamesmap blocksmap:\n', blocksmap #------------ + blocknamesmap = {} + for n in blocksmap.keys(): + blockname_short = n[:MAX_NAMELENGTH-1] + i = 0 #sufix for blockname cause Blender-objectnamelength-limit + while blockname_short in blocknamesmap.keys(): + i += 1 + suffix = str(i) + blockname_short = blockname_short[:-2] + suffix + blocknamesmap[n] = blockname_short + #print 'deb:getBlocknamesmap blocknamesmap:\n', blocknamesmap #------------ + return blocknamesmap def drawEntities(entities, settings, block_def=None): #---------------------------------------- @@ -3688,7 +4410,8 @@ def drawEntities(entities, settings, block_def=None): #------------------------ for _type in type_map.keys(): #print 'deb:drawEntities_type:', _type #------------------ # for each known type get a list of that type and call the associated draw function - drawer(_type, entities.get_type(_type), settings, block_def) + entities_type = entities.get_type(_type) + if entities_type: drawer(_type, entities_type, settings, block_def) def drawer(_type, entities, settings, block_def): #------------------------------------------ @@ -3756,14 +4479,21 @@ def drawer(_type, entities, settings, block_def): #---------------------------- if cur_temp == show_progress: settings.progress(cur_COUNTER, message) cur_temp = 0 - #print 'deb:drawer show_progress=',show_progress #----------------------- + #print 'deb:drawer show_progress=',show_progress #---------------- # get the layer group (just to make things a little cleaner) if settings.var['group_bylayer_on'] and not block_def: group = getGroup('l:%s' % layernamesmap[entity.layer]) - if _type == 'insert': #---- INSERT and MINSERT=array ------------------------ + if _type == 'insert': #---- INSERT and MINSERT=array -------------------- + if not settings.var['block_nn'] and entity.name.startswith('*X'): #---- support for noname BLOCKs + #print 'deb:drawer entity.name:', entity.name #------------ + continue + elif settings.var['blockFilter_on'] and not settings.accepted_block(entity.name): + continue + #print 'deb:insert entity.loc:', entity.loc #---------------- + insertFlag = True columns = entity.columns[0] coldist = entity.columns[1] rows = entity.rows[0] @@ -3776,22 +4506,35 @@ def drawer(_type, entities, settings, block_def): #---------------------------- deltaloc[1] = row * rowdist #print 'deb:insert col=%s, row=%s,deltaloc=%s' %(col, row, deltaloc) #------ ob = entity.draw(settings, deltaloc) #-----draw BLOCK---------- + if block_def: + blockFlag = True + bl_loc = block_def[1] + ob.loc = [ob.loc[0]-bl_loc[0],ob.loc[1]-bl_loc[1],ob.loc[2]-bl_loc[2]] + else: blockFlag = False setObjectProperties(ob, group, entity, settings, block_def) if ob: if settings.var['optimization'] <= settings.MIN: - if settings.var['g_scale'] != 1: globalScaleOne(ob, True, settings.var['g_scale']) + #if settings.var['g_origin_on'] and not block_def: ob.loc = Mathutils.Vector(ob.loc) + settings.g_origin + if settings.var['g_scale_on']: globalScaleOne(ob, insertFlag, blockFlag, settings.var['g_scale']) settings.redraw() - else: oblist.append((ob, True)) + else: oblist.append((ob, insertFlag, blockFlag)) else: #---draw entities except BLOCKs/INSERTs--------------------- + insertFlag = False alt_obname = activObjectName ob = entity.draw(settings) if ob and ob.name != alt_obname: + if block_def: + blockFlag = True + bl_loc = block_def[1] + ob.loc = [ob.loc[0]-bl_loc[0],ob.loc[1]-bl_loc[1],ob.loc[2]-bl_loc[2]] + else: blockFlag = False setObjectProperties(ob, group, entity, settings, block_def) if settings.var['optimization'] <= settings.MIN: - if settings.var['g_scale'] != 1: globalScaleOne(ob, False, settings.var['g_scale']) + #if settings.var['g_origin_on'] and not block_def: ob.loc = Mathutils.Vector(ob.loc) + settings.g_origin + if settings.var['g_scale_on']: globalScaleOne(ob, insertFlag, blockFlag, settings.var['g_scale']) settings.redraw() - else: oblist.append((ob, False)) + else: oblist.append((ob, insertFlag, blockFlag)) #print 'deb:Finished drawing:', entities[0].type #------------------------ message = "\nDrawing dxf\'%ss\' done!" % _type @@ -3806,20 +4549,31 @@ def globalScale(oblist, SCALE): #---------------------------------------------- """ #print 'deb:globalScale.oblist: ---------%\n', oblist #--------------------- for l in oblist: - ob, insertFlag = l[0], l[1] - globalScaleOne(ob, insertFlag, SCALE) + ob, insertFlag, blockFlag = l[0], l[1], l[2] + globalScaleOne(ob, insertFlag, blockFlag, SCALE) -def globalScaleOne(ob, insertFlag, SCALE): #--------------------------------------------------------- +def globalScaleOne(ob, insertFlag, blockFlag, SCALE): #--------------------------------------------------------- """Global_scale imported object. """ #print 'deb:globalScaleOne ob: ', ob #--------------------- + if settings.var['g_origin_on'] and not blockFlag: + ob.loc = Mathutils.Vector(ob.loc) + settings.g_origin + SCALE_MAT= Mathutils.Matrix([SCALE,0,0,0],[0,SCALE,0,0],[0,0,SCALE,0],[0,0,0,1]) - if insertFlag: # by BLOCKs/INSERTs only insert-point must be scaled------------ + if insertFlag: # by BLOCKs/INSERTs only insert-point coords must be scaled------------ ob.loc = Mathutils.Vector(ob.loc) * SCALE_MAT else: # entire scaling for all other imported objects ------------ - ob.setMatrix(ob.matrixWorld*SCALE_MAT) - + if ob.type == 'Mesh': + me = Mesh.Get(ob.name) + # set centers of all objects in (0,0,0) + #me.transform(ob.matrixWorld*SCALE_MAT) + #ob.loc = Mathutils.Vector([0,0,0]) + # preseve centers of all objects + me.transform(SCALE_MAT) + ob.loc = Mathutils.Vector(ob.loc) * SCALE_MAT + else: #--todo-- also for curves: neutral scale factor after import + ob.setMatrix(ob.matrixWorld*SCALE_MAT) def setObjectProperties(ob, group, entity, settings, block_def): #----------------------- @@ -3835,7 +4589,7 @@ def setObjectProperties(ob, group, entity, settings, block_def): #------------- setGroup(group, ob) # if object belongs to group if block_def: # if object belongs to BLOCK_def - Move it to layer nr19 - setGroup(block_def, ob) + setGroup(block_def[0], ob) #print 'deb:setObjectProperties \'%s\' set to block_def_group!' %ob.name #--------- ob.layers = [19] else: @@ -3843,7 +4597,7 @@ def setObjectProperties(ob, group, entity, settings, block_def): #------------- ob.layers = [settings.var['target_layer']] # Set material for any objects except empties - if ob.type != 'Empty': + if ob.type != 'Empty' and settings.var['material_on']: setMaterial_from(entity, ob, settings, block_def) # Set the visibility @@ -3884,17 +4638,18 @@ def setMaterial_from(entity, ob, settings, block_def): #----------------------- - controlled by settings.var['material_from'] """ if settings.var['material_from'] == 1: # 1= material from color - if entity.color_index == BYLAYER: + if entity.color_index == BYLAYER or entity.color_index == 256: mat = settings.colMaterials(entity.layer) - elif entity.color_index == BYBLOCK: + elif entity.color_index == BYBLOCK or entity.color_index == 0: #--todo-- looking for block.color_index #mat = settings.colMaterials(block.color_index) - mat = settings.colMaterials(entity.color_index) + #if block_def: mat = settings.colMaterials(block_def[2]) + mat = settings.colMaterials(3) else: mat = settings.colMaterials(entity.color_index) elif settings.var['material_from'] == 2: # 2= material from layer_name - mat = settings.layMaterials(layername=entity.layer) + mat = settings.layMaterials(layername = entity.layer) elif settings.var['material_from'] == 3: # 3= material from layer+color mat = settings.layMaterials(layername=entity.layer, color=entity.color_index) @@ -3910,10 +4665,11 @@ def setMaterial_from(entity, ob, settings, block_def): #----------------------- mat = Material.Get('dxf-neutral') except: mat = Material.New('dxf-neutral') - mat.mode |= Material.Modes.SHADELESS - mat.mode |= Material.Modes.WIRE -# try:mat.setMode('Shadeless', 'Wire') #work-around for 2.45rc1-bug -# except: pass + mat.setRGBCol(color_map[3]) + try:mat.setMode('Shadeless', 'Wire') #work-around for 2.45rc1-bug + except: + mat.mode |= Material.Modes.SHADELESS # + mat.mode |= Material.Modes.WIRE try: #print 'deb:material mat:', mat #----------- ob.setMaterials([mat]) #assigns Blender-material to object @@ -4205,15 +4961,19 @@ EVENT_START = 2 EVENT_REDRAW = 3 EVENT_LOAD_INI = 4 EVENT_SAVE_INI = 5 -EVENT_PRESET = 6 +EVENT_RESET = 6 EVENT_CHOOSE_INI = 7 EVENT_CHOOSE_DXF = 8 EVENT_HELP = 9 -EVENT_CONFIG = 10 +EVENT_PRESETCURV = 10 EVENT_PRESETS = 11 EVENT_DXF_DIR = 12 -EVENT_LIST = 13 +EVENT_DXF_NAME = 13 +EVENT_LIST = 14 +EVENT_ORIGIN = 15 +EVENT_SCALE = 16 EVENT_PRESET2D = 20 +EVENT_PRESET3D = 21 EVENT_EXIT = 100 GUI_EVENT = EVENT_NONE @@ -4222,22 +4982,40 @@ GUI_B = {} # GUI-buttons dictionary for drawingTypes # settings default, initialize ------------------------ -points_as_menu = "convert to: %t|empty %x1|mesh.vertex %x2|thin sphere %x3|thin box %x4" -lines_as_menu = "convert to: %t|*edge %x1|mesh %x2|*thin cylinder %x3|*thin box %x4" -mlines_as_menu = "convert to: %t|*edge %x1|*mesh %x2|*thin cylinder %x3|*thin box %x4" -plines_as_menu = "convert to: %t|*edge %x1|mesh %x2|*thin cylinder %x3|*thin box %x4" -plines3_as_menu = "convert to: %t|*edge %x1|mesh %x2|*thin cylinder %x3|*thin box %x4" -plmesh_as_menu = "convert to: %t|mesh %x1" -solids_as_menu = "convert to: %t|mesh %x1" -blocks_as_menu = "convert to: %t|dupl.group %x1|*real.group %x2|*exploded %x3" -texts_as_menu = "convert to: %t|text %x1|*mesh %x2" +points_as_menu = "convert to: %t|empty %x1|mesh.vertex %x2|thin sphere %x3|thin box %x4|*curve.vertex %x5" +lines_as_menu = "convert to: %t|*edge %x1|mesh %x2|*thin cylinder %x3|thin box %x4|curve %x5" +mlines_as_menu = "convert to: %t|*edge %x1|*mesh %x2|*thin cylinder %x3|*thin box %x|*curve %x5" +plines_as_menu = "convert to: %t|*edge %x1|mesh %x2|*thin cylinder %x3|*thin box %x4|curve %x5" +plines3_as_menu = "convert to: %t|*edge %x1|mesh %x2|*thin cylinder %x3|*thin box %x4|curve %x5" +plmesh_as_menu = "convert to: %t|*edge %x1|mesh %x2" +solids_as_menu = "convert to: %t|*edge %x1|mesh %x2" +blocks_as_menu = "convert to: %t|dupliGroup %x1|*real.Group %x2|*exploded %x3" +texts_as_menu = "convert to: %t|text %x1|*mesh %x2|*curve %x5" material_from_menu= "material from: %t|*LINESTYLE %x7|COLOR %x1|LAYER %x2|*LAYER+COLOR %x3|*BLOCK %x4|*XDATA %x5|*INI-File %x6" -g_scale_list = "scale factor: %t|yard to m %x8|feet to m %x7|inch to m %x6|x 1000 %x3|x 100 %x2|x 10 %x1|x 1 %x0|x 0.1 %x-1|cm to m %x-2|mm to m %x-3|x 0.0001 %x-4|x 0.00001 %x-5" +g_scale_list = ''.join(( + 'scale factor: %t', + '|user def. %x12', + '|yard to m %x8', + '|feet to m %x7', + '|inch to m %x6', + '| x 1000 %x3', + '| x 100 %x2', + '| x 10 %x1', + '| x 1 %x0', + '| x 0.1 %x-1', + '| x 0.01 %x-2', + '| x 0.001 %x-3', + '| x 0.0001 %x-4', + '| x 0.00001 %x-5')) + +#print 'deb: g_scale_list', g_scale_list #----------- dxfFileName = Draw.Create("") iniFileName = Draw.Create(INIFILE_DEFAULT_NAME + INIFILE_EXTENSION) user_preset = 0 config_UI = Draw.Create(0) #switch_on/off extended config_UI +g_scale_as = Draw.Create(int(log10(G_SCALE))) + keywords_org = { 'curves_on' : 0, @@ -4245,12 +5023,22 @@ keywords_org = { 'one_mesh_on': 1, 'vGroup_on' : 1, 'dummy_on' : 0, + 'views_on' : 0, + 'cams_on' : 0, + 'lights_on' : 0, + 'xref_on' : 1, + 'block_nn': 0, + 'blockFilter_on': 0, 'newScene_on' : 1, 'target_layer' : TARGET_LAYER, 'group_bylayer_on' : GROUP_BYLAYER, + 'g_originX' : G_ORIGIN_X, + 'g_originY' : G_ORIGIN_Y, + 'g_originZ' : G_ORIGIN_Z, + 'g_origin_on': 0, 'g_scale' : float(G_SCALE), - 'g_scale_as': int(log10(G_SCALE)), # 0, - 'g_scale_on': 1, +# 'g_scale_as': int(log10(G_SCALE)), # 0, + 'g_scale_on': 0, 'thick_on' : 1, 'thick_min' : float(MIN_THICK), 'thick_force': 0, @@ -4281,8 +5069,8 @@ keywords_org = { 'mlines_as' : 2, 'plines_as' : 2, 'plines3_as': 2, - 'plmesh_as' : 1, - 'solids_as' : 1, + 'plmesh_as' : 2, + 'solids_as' : 2, 'blocks_as' : 1, 'texts_as' : 1 } @@ -4292,7 +5080,7 @@ drawTypes_org = { 'line' : 1, 'arc' : 1, 'circle': 1, - 'ellipse': 0, + 'ellipse': 1, 'mline' : 0, 'polyline': 1, 'plmesh': 1, @@ -4302,9 +5090,10 @@ drawTypes_org = { 'mtext' : 0, 'block' : 1, 'insert': 1, - 'face' : 1, 'solid' : 1, - 'trace' : 1 + 'trace' : 1, + 'face' : 1, +# 'view' : 0, } # creating of GUI-buttons @@ -4320,8 +5109,33 @@ for k, v in drawTypes_org.iteritems(): settings = Settings(keywords_org, drawTypes_org) +def update_RegistryKey(key, item): # + """updates key in Blender.Registry + """ + cache = True # data is also saved to a file + rdict = Registry.GetKey('DXF_Importer', cache) + if not rdict: rdict = {} + if item: + rdict[key] = item + Registry.SetKey('DXF_Importer', rdict, cache) + #print 'deb:update_RegistryKey rdict', rdict #--------------- -def saveConfig(): #remi--todo----------------------------------------------- + +def check_RegistryKey(key): + """ check if the key is already there (saved on a previous execution of this script) + """ + cache = True # data is also saved to a file + rdict = Registry.GetKey('DXF_Importer', cache) + #print 'deb:check_RegistryKey rdict:', rdict #---------------- + if rdict: # if found, get the values saved there + try: + item = rdict[key] + return item + except: + #update_RegistryKey() # if data isn't valid rewrite it + pass + +def saveConfig(): #--todo----------------------------------------------- """Save settings/config/materials from GUI to INI-file. Write all config data to INI-file. @@ -4331,18 +5145,31 @@ def saveConfig(): #remi--todo----------------------------------------------- iniFile = iniFileName.val #print 'deb:saveConfig inifFile: ', inifFile #---------------------- if iniFile.lower().endswith(INIFILE_EXTENSION): + + #--todo-- sort key.list for output + #key_list = GUI_A.keys().val + #key_list.sort() + #for key in key_list: + # l_name, l_data = key, GUI_A[key].val + # list_A + output_str = '[%s,%s]' %(GUI_A, GUI_B) if output_str =='None': Draw.PupMenu('DXF importer: INI-file: Alert!%t|no config-data present to save!') else: #if BPyMessages.Warning_SaveOver(iniFile): #<- remi find it too abstarct if sys.exists(iniFile): - f = file(iniFile, 'r'); header_str = f.readline(); f.close() - if header_str.startswith(INIFILE_HEADER[0:12]): + try: + f = file(iniFile, 'r') + try: header_str = f.readline() + finally: f.close() + except: pass + if header_str.startswith(INIFILE_HEADER[0:13]): if Draw.PupMenu(' OK ? %t|SAVE OVER: ' + '\'%s\'' %iniFile) == 1: save_ok = True + else: save_ok = False elif Draw.PupMenu(' OK ? %t|SAVE OVER: ' + '\'%s\'' %iniFile + - '|Alert: this file has no valid ImportDXF-format| ! it may belong to another aplication !') == 1: + '|Alert: this file has no valid ImportDXF-header| ! it may belong to another aplication !') == 1: save_ok = True else: save_ok = False else: save_ok = True @@ -4356,10 +5183,11 @@ def saveConfig(): #remi--todo----------------------------------------------- output_str = '{\n'.join(output_str.split('{')) try: f = file(iniFile, 'w') - f.write(INIFILE_HEADER + '\n# this is a comment line\n') - f.write(output_str) - f.close() - Draw.PupMenu('DXF importer: INI-file: Done!%t|config-data saved in ' + '\'%s\'' %iniFile) + try: + f.write(INIFILE_HEADER + '\n# this is a comment line\n') + f.write(output_str) + finally: f.close() + #Draw.PupMenu('DXF importer: INI-file: Done!%t|config-data saved in ' + '\'%s\'' %iniFile) except: Draw.PupMenu('DXF importer: INI-file: Error!%t|failure by writing to ' + '\'%s\'|no config-data saved!' %iniFile) @@ -4380,28 +5208,28 @@ def loadConfig(): #remi--todo----------------------------------------------- global iniFileName, GUI_A, GUI_B iniFile = iniFileName.val + update_RegistryKey('iniFileName', iniFile) #print 'deb:loadConfig iniFile: ', iniFile #---------------------- if iniFile.lower().endswith(INIFILE_EXTENSION) and sys.exists(iniFile): - f = file(iniFile, 'r') - header_str = f.readline() - if not header_str.startswith(INIFILE_HEADER): - f.close() - Draw.PupMenu('DXF importer: INI-file: Alert!%t|no valid header in INI-file: ' + '\'%s\'' %iniFile) - else: - data_str = f.read() - f.close() - print 'deb:loadConfig data_str from %s: \n' %iniFile , data_str #-------------------------- - data = eval(data_str) - for k, v in data[0].iteritems(): - try: - GUI_A[k].val = v - except: - GUI_A[k] = Draw.Create(v) - for k, v in data[1].iteritems(): - try: - GUI_B[k].val = v - except: - GUI_B[k] = Draw.Create(v) + try: + f = file(iniFile, 'r') + try: + header_str = f.readline() + if header_str.startswith(INIFILE_HEADER): + data_str = f.read() + f.close() + #print 'deb:loadConfig data_str from %s: \n' %iniFile , data_str #----------------- + data = eval(data_str) + for k, v in data[0].iteritems(): + try: GUI_A[k].val = v + except: GUI_A[k] = Draw.Create(v) + for k, v in data[1].iteritems(): + try: GUI_B[k].val = v + except: GUI_B[k] = Draw.Create(v) + else: + Draw.PupMenu('DXF importer: INI-file: Alert!%t|no valid header in INI-file: ' + '\'%s\'' %iniFile) + finally: f.close() + except: pass else: Draw.PupMenu('DXF importer: INI-file: Alert!%t|no valid INI-file selected!') print "DXF importer: Alert!: no valid INI-file selected." @@ -4411,27 +5239,53 @@ def loadConfig(): #remi--todo----------------------------------------------- -def resetDefaultConfig(): #----------------------------------------------- - """Resets settings/config/materials to defaults. +def updateConfig(keywords, drawTypes): #----------------------------------------------- + """updates GUI_settings with given dictionaries """ global GUI_A, GUI_B #print 'deb:lresetDefaultConfig keywords_org: \n', keywords_org #--------- - for k, v in keywords_org.iteritems(): + for k, v in keywords.iteritems(): GUI_A[k].val = v - for k, v in drawTypes_org.iteritems(): + for k, v in drawTypes.iteritems(): GUI_B[k].val = v +def resetDefaultConfig(): #----------------------------------------------- + """Resets settings/config/materials to defaults. + """ + #print 'deb:lresetDefaultConfig keywords_org: \n', keywords_org #--------- + updateConfig(keywords_org, drawTypes_org) + + +def presetConfig_curv(): #----------------------------------------------- + """Sets settings/config/materials for curve representation. + + """ + global GUI_A + if GUI_A['curves_on'].val == 1: + GUI_A['points_as'].val = 5 + GUI_A['lines_as'].val = 5 + GUI_A['mlines_as'].val = 5 + GUI_A['plines_as'].val = 5 + GUI_A['plines3_as'].val = 5 + else: + GUI_A['points_as'].val = 2 + GUI_A['lines_as'].val = 2 + GUI_A['mlines_as'].val = 2 + GUI_A['plines_as'].val = 2 + GUI_A['plines3_as'].val = 2 + + def resetDefaultConfig_2D(): #----------------------------------------------- """Sets settings/config/materials to defaults 2D. """ - resetDefaultConfig() - global GUI_A, GUI_B +# presetConfig_curv() keywords2d = { - 'curves_on' : 0, - 'one_mesh_on': 1, + 'views_on' : 0, + 'cams_on' : 0, + 'lights_on' : 0, 'vGroup_on' : 1, 'thick_on' : 0, 'thick_force': 0, @@ -4444,11 +5298,7 @@ def resetDefaultConfig_2D(): #----------------------------------------------- 'pl_trim_on': 1, 'Z_force_on': 0, 'meshSmooth_on': 0, - 'points_as' : 2, - 'lines_as' : 2, - 'mlines_as' : 2, - 'plines_as' : 2, - 'solids_as' : 1, + 'solids_as' : 2, 'blocks_as' : 1, 'texts_as' : 1 } @@ -4458,7 +5308,7 @@ def resetDefaultConfig_2D(): #----------------------------------------------- 'line' : 1, 'arc' : 1, 'circle': 1, - 'ellipse': 0, + 'ellipse': 1, 'mline' : 0, 'polyline': 1, 'plmesh': 0, @@ -4468,23 +5318,102 @@ def resetDefaultConfig_2D(): #----------------------------------------------- 'mtext' : 0, 'block' : 1, 'insert': 1, - 'face' : 0, 'solid' : 1, - 'trace' : 1 + 'trace' : 1, + 'face' : 0, +# 'view' : 0, } - for k, v in keywords2d.iteritems(): - GUI_A[k].val = v - for k, v in drawTypes2d.iteritems(): - GUI_B[k].val = v + updateConfig(keywords2d, drawTypes2d) +def resetDefaultConfig_3D(): #----------------------------------------------- + """Sets settings/config/materials to defaults 3D. + + """ +# presetConfig_curv() + keywords3d = { + 'vGroup_on' : 1, + 'thick_on' : 1, + 'thick_force': 0, + 'width_on' : 1, + 'width_force': 0, + 'dist_on' : 1, + 'dist_force': 0, + 'pl_3d' : 0, + 'fill_on' : 1, + 'pl_trim_on': 1, + 'Z_force_on': 0, + 'meshSmooth_on': 1, + 'solids_as' : 2, + 'blocks_as' : 1, + 'texts_as' : 1 + } + + drawTypes3d = { + 'point' : 1, + 'line' : 1, + 'arc' : 1, + 'circle': 1, + 'ellipse': 1, + 'mline' : 0, + 'polyline': 1, + 'plmesh': 1, + 'pline3': 1, + 'lwpolyline': 1, + 'text' : 1, + 'mtext' : 0, + 'block' : 1, + 'insert': 1, + 'solid' : 1, + 'trace' : 1, + 'face' : 1, +# 'view' : 0, + } + + updateConfig(keywords3d, drawTypes3d) + + +def inputGlobalScale(): + """Pop-up UI-Block for global scale factor + """ + global GUI_A + #print 'deb:inputGlobalScale ##########' #------------ + x_scale = Draw.Create(GUI_A['g_scale'].val) + block = [] + #block.append("global translation vector:") + block.append(("", x_scale, 0.0, 10000000.0)) + + retval = Draw.PupBlock("set global scale factor:", block) + + GUI_A['g_scale'].val = float(x_scale.val) + + +def inputOriginVector(): + """Pop-up UI-Block for global translation vector + """ + global GUI_A + #print 'deb:inputOriginVector ##########' #------------ + x_origin = Draw.Create(GUI_A['g_originX'].val) + y_origin = Draw.Create(GUI_A['g_originY'].val) + z_origin = Draw.Create(GUI_A['g_originZ'].val) + block = [] + #block.append("global translation vector:") + block.append(("X: ", x_origin, -100000000.0, 100000000.0)) + block.append(("Y: ", y_origin, -100000000.0, 100000000.0)) + block.append(("Z: ", z_origin, -100000000.0, 100000000.0)) + + retval = Draw.PupBlock("set global translation vector:", block) + + GUI_A['g_originX'].val = x_origin.val + GUI_A['g_originY'].val = y_origin.val + GUI_A['g_originZ'].val = z_origin.val def draw_UI(): #----------------------------------------------------------------- """ Draw startUI and setup Settings. """ global GUI_A, GUI_B #__version__ - global user_preset, iniFileName, dxfFileName, config_UI + global user_preset, iniFileName, dxfFileName, config_UI, g_scale_as # This is for easy layout changes but_0c = 70 #button 1.column width @@ -4495,8 +5424,8 @@ def draw_UI(): #--------------------------------------------------------------- butt_margin = 10 menu_w = (3 * butt_margin) + but_0c + but_1c + but_2c + but_3c #menu width - simple_menu_h = 110 - extend_menu_h = 400 + simple_menu_h = 80 + extend_menu_h = 350 y = simple_menu_h # y is menu upper.y if config_UI.val: y += extend_menu_h x = 20 #menu left.x @@ -4504,160 +5433,228 @@ def draw_UI(): #--------------------------------------------------------------- but1c = but0c + but_0c + butt_margin but2c = but1c + but_1c + butt_margin but3c = but2c + but_2c + butt_margin + but4c = but3c + but_3c # Here starts menu ----------------------------------------------------- #glClear(GL_COLOR_BUFFER_BIT) #glRasterPos2d(8, 125) + y += 30 colorbox(x, y+20, x+menu_w+menu_margin*2, menu_margin) - Draw.Label("DXF Importer ver." + __version__, but0c, y, menu_w, 20) + Draw.Label("DXF-Importer ver." + __version__, but0c, y, menu_w, 20) if config_UI.val: + b0, b0_ = but0c, but_0c + butt_margin + b1, b1_ = but1c, but_1c + y -= 10 + + y -= 20 + Draw.BeginAlign() + GUI_B['point'] = Draw.Toggle('POINT', EVENT_REDRAW, b0, y, b0_, 20, GUI_B['point'].val, "support dxf-POINT on/off") + if GUI_B['point'].val: + GUI_A['points_as'] = Draw.Menu(points_as_menu, EVENT_NONE, b1, y, b1_, 20, GUI_A['points_as'].val, "select target Blender-object") +# Draw.Label('-->', but2c, y, but_2c, 20) + Draw.EndAlign() + + y -= 20 + Draw.BeginAlign() + GUI_B['line'] = Draw.Toggle('LINE...etc', EVENT_REDRAW, b0, y, b0_, 20, GUI_B['line'].val, "support dxf-LINE,ARC,CIRCLE,ELLIPSE on/off") + if GUI_B['line'].val: + GUI_A['lines_as'] = Draw.Menu(lines_as_menu, EVENT_NONE, but1c, y, but_1c, 20, GUI_A['lines_as'].val, "select target Blender-object") + Draw.EndAlign() + + y -= 20 + Draw.BeginAlign() + GUI_B['mline'] = Draw.Toggle('*MLINE', EVENT_REDRAW, b0, y, b0_, 20, GUI_B['mline'].val, "(*wip)support dxf-MLINE on/off") + if GUI_B['mline'].val: + GUI_A['mlines_as'] = Draw.Menu(mlines_as_menu, EVENT_NONE, but1c, y, but_1c, 20, GUI_A['mlines_as'].val, "select target Blender-object") + Draw.EndAlign() + + y -= 20 + Draw.BeginAlign() + GUI_B['polyline'] = Draw.Toggle('2D-PLINE', EVENT_REDRAW, b0, y, b0_, 20, GUI_B['polyline'].val, "support dxf-2D-POLYLINE on/off") + if GUI_B['polyline'].val: + GUI_A['plines_as'] = Draw.Menu(plines_as_menu, EVENT_NONE, but1c, y, but_1c, 20, GUI_A['plines_as'].val, "select target Blender-object") + Draw.EndAlign() + + y -= 20 + Draw.BeginAlign() + GUI_B['pline3'] = Draw.Toggle('3D-PLINE', EVENT_REDRAW, b0, y, b0_, 20, GUI_B['pline3'].val, "support dxf-3D-POLYLINE on/off") + if GUI_B['pline3'].val: + GUI_A['plines3_as'] = Draw.Menu(plines3_as_menu, EVENT_NONE, but1c, y, but_1c, 20, GUI_A['plines3_as'].val, "select target Blender-object") + Draw.EndAlign() + + y -= 10 + y -= 20 + Draw.BeginAlign() + GUI_A['material_on'] = Draw.Toggle('material', EVENT_REDRAW, b0, y, b0_-20, 20, GUI_A['material_on'].val, "support for material assignment on/off") + if GUI_A['material_on'].val: + GUI_A['material_from'] = Draw.Menu(material_from_menu, EVENT_NONE, b1-20, y, b1_+20, 20, GUI_A['material_from'].val, "material assignment from?") + Draw.EndAlign() + + y -= 20 + Draw.BeginAlign() + GUI_A['g_origin_on'] = Draw.Toggle('glob.reLoc', EVENT_REDRAW, b0, y, b0_, 20, GUI_A['g_origin_on'].val, "global relocate all DXF objects on/off") + if GUI_A['g_origin_on'].val: + tmp = Draw.PushButton('=', EVENT_ORIGIN, b1, y, 20, 20, "edit relocation-vector (x,y,z in DXF units)") + origin_str = '(%.4f, %.4f, %.4f)' % ( + GUI_A['g_originX'].val, + GUI_A['g_originY'].val, + GUI_A['g_originZ'].val + ) + tmp = Draw.Label(origin_str, b1+20, y, 300, 20) + #GUI_A['g_origin'] = Draw.String('', EVENT_ORIGIN, b1, y, b1_, 20, GUI_A['g_origin'].val, "global translation-vector (x,y,z) in DXF units") + Draw.EndAlign() + + y -= 20 + Draw.BeginAlign() + GUI_A['g_scale_on'] = Draw.Toggle('glob.Scale', EVENT_REDRAW, b0, y, b0_, 20, GUI_A['g_scale_on'].val, "global scale all DXF objects on/off") + if GUI_A['g_scale_on'].val: + g_scale_as = Draw.Menu(g_scale_list, EVENT_SCALE, b1, y, 45, 20, g_scale_as.val, "factor for scaling the DXFdata") + if g_scale_as.val == 12: + pass + else: + if g_scale_as.val == 6: #scale inches to meters + GUI_A['g_scale'].val = 0.0254000 + elif g_scale_as.val == 7: #scale feets to meters + GUI_A['g_scale'].val = 0.3048000 + elif g_scale_as.val == 8: #scale yards to meters + GUI_A['g_scale'].val = 0.9144000 + else: + GUI_A['g_scale'].val = 10.0 ** int(g_scale_as.val) + scale_float = GUI_A['g_scale'].val + if scale_float < 0.000001 or scale_float > 1000000: + scale_str = ' = %s' % GUI_A['g_scale'].val + else: + scale_str = ' = %.6f' % GUI_A['g_scale'].val + Draw.Label(scale_str, b1+45, y, 200, 20) + Draw.EndAlign() + + y -= 10 + y -= 20 + Draw.BeginAlign() + GUI_A['meshSmooth_on'] = Draw.Toggle('smooth', EVENT_NONE, b0, y, b0_-20, 20, GUI_A['meshSmooth_on'].val, "mesh smooth for circles/arcsegments on/off") + GUI_A['pl_trim_on'] = Draw.Toggle('trim', EVENT_NONE, b1-20, y, 32, 20, GUI_A['pl_trim_on'].val, "intersection of POLYLINE-wide-segments on/off") + GUI_A['pl_trim_max'] = Draw.Number('', EVENT_NONE, b1+12, y, b1_-12, 20, GUI_A['pl_trim_max'].val, 0, 5, "limit for intersection of POLYLINE-wide-segments: 0.0-5.0") + Draw.EndAlign() + + y -= 20 + Draw.BeginAlign() +# GUI_A['thin_res'] = Draw.Number('thin:', EVENT_NONE, but0c, y, but_0c, 20, GUI_A['thin_res'].val, 4, 64, "thin cylinder resolution - number of segments (4-64)") + GUI_A['arc_rad'] = Draw.Number('bR:', EVENT_NONE, b0, y, b0_, 20, GUI_A['arc_rad'].val, 0.01, 100, "basis radius for arc/circle resolution (0.01-100)") + GUI_A['arc_res'] = Draw.Number('', EVENT_NONE, b1, y, b1_/2, 20, GUI_A['arc_res'].val, 3, 500, "arc/circle resolution - number of segments (3-500)") + GUI_A['fill_on'] = Draw.Toggle('caps', EVENT_NONE, b1+b1_/2, y, b1_/2, 20, GUI_A['fill_on'].val, "draws top and bottom caps of CYLINDERs/closed curves on/off") + Draw.EndAlign() + + y -= 20 + Draw.BeginAlign() + GUI_A['curves_on'] = Draw.Toggle('to Curves', EVENT_PRESETCURV, b0, y, b0_, 20, GUI_A['curves_on'].val, "import into curves instead into meshes on/off") + GUI_A['curve_arc'] = Draw.Number('', EVENT_NONE, b1, y, b1_/2, 20, GUI_A['curve_arc'].val, 3, 32, "Bezier circle: amount of segments: 3-32") + GUI_A['curve_res'] = Draw.Number('', EVENT_NONE, b1+b1_/2, y, b1_/2, 20, GUI_A['curve_res'].val, 1, 128, "Set the Curve's U-resolution value: 1-128") + Draw.EndAlign() + + y -= 20 + GUI_A['group_bylayer_on'] = Draw.Toggle('Lay', EVENT_NONE, b0, y, 30, 20, GUI_A['group_bylayer_on'].val, "grouping entities from the same layer on/off") + GUI_A['vGroup_on'] = Draw.Toggle('vGroups', EVENT_NONE, b0+30, y, b1_-10, 20, GUI_A['vGroup_on'].val, "support Blender-VertexGroups on/off") + GUI_A['one_mesh_on'] = Draw.Toggle('oneMesh', EVENT_NONE, b1+10, y, b1_-10, 20, GUI_A['one_mesh_on'].val, "draw DXF-entities into one mesh-object. Recommended for big DXF-files. on/off") + y -= 30 Draw.BeginAlign() - GUI_B['point'] = Draw.Toggle('POINT', EVENT_NONE, but0c, y, but_0c+but_1c, 20, GUI_B['point'].val, "support dxf-POINT on/off") - Draw.Label('-->', but2c, y, but_2c, 20) - GUI_A['points_as'] = Draw.Menu(points_as_menu, EVENT_NONE, but3c, y, but_3c, 20, GUI_A['points_as'].val, "select target Blender-object") - Draw.EndAlign() - - y -= 20 - Draw.BeginAlign() - GUI_B['line'] = Draw.Toggle('LINE.ARC.CIRCLE', EVENT_NONE, but0c, y, but_0c+but_1c, 20, GUI_B['line'].val, "support dxf-LINE,ARC,CIRCLE,ELLIPSE on/off") - Draw.Label('-->', but2c, y, but_2c, 20) - GUI_A['lines_as'] = Draw.Menu(lines_as_menu, EVENT_NONE, but3c, y, but_3c, 20, GUI_A['lines_as'].val, "select target Blender-object") - Draw.EndAlign() - - y -= 20 - Draw.BeginAlign() - GUI_B['mline'] = Draw.Toggle('*MLINE', EVENT_NONE, but0c, y, but_0c+but_1c, 20, GUI_B['mline'].val, "(*wip)support dxf-MLINE on/off") - Draw.Label('-->', but2c, y, but_2c, 20) - GUI_A['mlines_as'] = Draw.Menu(mlines_as_menu, EVENT_NONE, but3c, y, but_3c, 20, GUI_A['mlines_as'].val, "select target Blender-object") - Draw.EndAlign() - - y -= 20 - Draw.BeginAlign() - GUI_B['polyline'] = Draw.Toggle('2D-POLYLINE', EVENT_NONE, but0c, y, but_0c+but_1c, 20, GUI_B['polyline'].val, "support dxf-2D-POLYLINE on/off") - Draw.Label('-->', but2c, y, but_2c, 20) - GUI_A['plines_as'] = Draw.Menu(plines_as_menu, EVENT_NONE, but3c, y, but_3c, 20, GUI_A['plines_as'].val, "select target Blender-object") - Draw.EndAlign() - - y -= 20 - Draw.BeginAlign() - GUI_B['pline3'] = Draw.Toggle('3D-POLYLINE', EVENT_NONE, but0c, y, but_0c+but_1c, 20, GUI_B['pline3'].val, "support dxf-3D-POLYLINE on/off") - Draw.Label('-->', but2c, y, but_2c, 20) - GUI_A['plines3_as'] = Draw.Menu(plines3_as_menu, EVENT_NONE, but3c, y, but_3c, 20, GUI_A['plines3_as'].val, "select target Blender-object") - Draw.EndAlign() - - y -= 20 - Draw.BeginAlign() - GUI_B['plmesh'] = Draw.Toggle('POLYMESH/-FACE', EVENT_NONE, but0c, y, but_0c+but_1c, 20, GUI_B['plmesh'].val, "support dxf-POLYMESH/POLYFACE on/off") - Draw.Label('-->', but2c, y, but_2c, 20) - GUI_A['plmesh_as'] = Draw.Menu(plmesh_as_menu, EVENT_NONE, but3c, y, but_3c, 20, GUI_A['plmesh_as'].val, "select target Blender-object") - Draw.EndAlign() - - y -= 20 - Draw.BeginAlign() - GUI_B['solid'] = Draw.Toggle('3DFACE.SOLID.TRACE', EVENT_NONE, but0c, y, but_0c+but_1c, 20, GUI_B['solid'].val, "support dxf-3DFACE, SOLID and TRACE on/off") - Draw.Label('-->', but2c, y, but_2c, 20) - GUI_A['solids_as'] = Draw.Menu(solids_as_menu, EVENT_NONE, but3c, y, but_3c, 20, GUI_A['solids_as'].val, "select target Blender-object") - Draw.EndAlign() - - y -= 20 - Draw.BeginAlign() - GUI_B['text'] = Draw.Toggle('TEXT', EVENT_NONE, but0c, y, but_0c, 20, GUI_B['text'].val, "support dxf-TEXT on/off") - GUI_B['mtext'] = Draw.Toggle('*MTEXT', EVENT_NONE, but1c, y, but_1c-butt_margin, 20, GUI_B['mtext'].val, "(*wip)support dxf-MTEXT on/off") - Draw.Label('-->', but2c, y, but_2c, 20) - GUI_A['texts_as'] = Draw.Menu(texts_as_menu, EVENT_NONE, but3c, y, but_3c, 20, GUI_A['texts_as'].val, "select target Blender-object") - Draw.EndAlign() - - y -= 20 - Draw.BeginAlign() - GUI_B['block'] = Draw.Toggle('BLOCK', EVENT_NONE, but0c, y, but_0c, 20, GUI_B['block'].val, "support dxf-BLOCK and ARRAY on/off") - GUI_A['dummy_on'] = Draw.Toggle('*XREF', EVENT_NONE, but1c, y, but_1c-butt_margin, 20, GUI_A['dummy_on'].val, "(*wip)support XREF-BLOCK on/off") - Draw.Label('-->', but2c, y, but_2c, 20) - GUI_A['blocks_as'] = Draw.Menu(blocks_as_menu, EVENT_NONE, but3c, y, but_3c, 20, GUI_A['blocks_as'].val, "select target Blender-object") - Draw.EndAlign() - - - y -= 20 - Draw.BeginAlign() - GUI_A['dummy_on'] = Draw.Toggle('*views', EVENT_NONE, but0c, y, but_0c-25, 20, GUI_A['dummy_on'].val, "(*wip)support VIEWPORTs on/off") - GUI_A['dummy_on'] = Draw.Toggle('*cams', EVENT_NONE, but1c-25, y, but_1c-25, 20, GUI_A['dummy_on'].val, "(*wip)support CAMERAs on/off") - GUI_A['dummy_on'] = Draw.Toggle('*lights', EVENT_NONE, but1c+25, y, but_1c-25, 20, GUI_A['dummy_on'].val, "(*wip)support LIGHTs on/off") - Draw.EndAlign() - Draw.BeginAlign() - GUI_A['material_on'] = Draw.Toggle('material', EVENT_NONE, but2c, y, but_2c-20, 20, GUI_A['material_on'].val, "support for material assignment on/off") - GUI_A['material_from'] = Draw.Menu(material_from_menu, EVENT_NONE, but3c-20, y, but_3c+20, 20, GUI_A['material_from'].val, "material assignment from?") - Draw.EndAlign() - - - y -= 20 - Draw.BeginAlign() - GUI_A['paper_space_on'] = Draw.Toggle('paperSpace', EVENT_NONE, but0c, y, but_0c+20, 20, GUI_A['paper_space_on'].val, "import from paper space only on/off") - GUI_A['layFrozen_on'] = Draw.Toggle('frozen', EVENT_NONE, but1c+20, y, but_1c-20, 20, GUI_A['layFrozen_on'].val, "import also from frozen layers on/off") + GUI_A['paper_space_on'] = Draw.Toggle('paper space', EVENT_NONE, b0, y, b0_+20, 20, GUI_A['paper_space_on'].val, "import only layout (paper space) on/off") + GUI_A['layFrozen_on'] = Draw.Toggle('frozen', EVENT_NONE, b1+20, y, b1_-20, 20, GUI_A['layFrozen_on'].val, "import also from frozen layers on/off") #GUI_A['dummy_on'] = Draw.Toggle('-', EVENT_NONE, but3c, y, but_3c, 20, GUI_A['dummy_on'].val, "dummy on/off") Draw.EndAlign() + + y_down = y + # ----------------------------------------------- + y = simple_menu_h + extend_menu_h +20 + b0, b0_ = but2c, but_2c + butt_margin + b1, b1_ = but3c, but_3c + + y -= 20 Draw.BeginAlign() - GUI_A['g_scale_on'] = Draw.Toggle('glob.Scale', EVENT_NONE, but2c, y, but_2c, 20, GUI_A['g_scale_on'].val, "scaling all DXF objects on/off") - GUI_A['g_scale_as'] = Draw.Menu(g_scale_list, EVENT_NONE, but3c, y, but_3c, 20, GUI_A['g_scale_as'].val, "10^ factor for scaling the DXFdata") + GUI_B['plmesh'] = Draw.Toggle('POLY-MESH/FACE', EVENT_NONE, b0, y, b0_+b1_, 20, GUI_B['plmesh'].val, "support dxf-POLYMESH/POLYFACE on/off") +# GUI_A['plmesh_as'] = Draw.Menu(plmesh_as_menu, EVENT_NONE, but1c, y, but_1c, 20, GUI_A['plmesh_as'].val, "select target Blender-object") Draw.EndAlign() - - y -= 30 - GUI_A['group_bylayer_on'] = Draw.Toggle('oneGroup', EVENT_NONE, but0c, y, but_0c, 20, GUI_A['group_bylayer_on'].val, "grouping entities from the same layer on/off") - GUI_A['vGroup_on'] = Draw.Toggle('vGroups', EVENT_NONE, but1c, y, but_1c, 20, GUI_A['vGroup_on'].val, "support Blender-VertexGroups on/off") + y -= 20 Draw.BeginAlign() - GUI_A['Z_force_on'] = Draw.Toggle('*elevation', EVENT_NONE, but2c, y, but_2c, 20, GUI_A['Z_force_on'].val, "*set objects Z-coordinates to elevation on/off") - GUI_A['Z_elev'] = Draw.Number('', EVENT_NONE, but3c, y, but_3c, 20, GUI_A['Z_elev'].val, -1000, 1000, "set default elevation(Z)") + GUI_B['solid'] = Draw.Toggle('SOLID', EVENT_NONE, b0, y, b0_, 20, GUI_B['solid'].val, "support dxf-SOLID and TRACE on/off") + GUI_B['face'] = Draw.Toggle('3DFACE', EVENT_NONE, b1, y, b1_, 20, GUI_B['face'].val, "support dxf-3DFACE on/off") +# GUI_A['solids_as'] = Draw.Menu(solids_as_menu, EVENT_NONE, but3c, y, but_3c, 20, GUI_A['solids_as'].val, "select target Blender-object") + Draw.EndAlign() + #print 'deb:support solid, trace', GUI_B['trace'].val, GUI_B['solid'].val # ------------ + + + y -= 20 + Draw.BeginAlign() + GUI_B['text'] = Draw.Toggle('TEXT', EVENT_NONE, b0, y, b0_, 20, GUI_B['text'].val, "support dxf-TEXT on/off") + GUI_B['mtext'] = Draw.Toggle('*MTEXT', EVENT_NONE, b1, y, b1_, 20, GUI_B['mtext'].val, "(*wip)support dxf-MTEXT on/off") +# GUI_A['texts_as'] = Draw.Menu(texts_as_menu, EVENT_NONE, but3c, y, but_3c, 20, GUI_A['texts_as'].val, "select target Blender-object") + Draw.EndAlign() + + y -= 20 + Draw.BeginAlign() + GUI_B['block'] = Draw.Toggle('BLOCK', EVENT_REDRAW, b0, y, b0_-30, 20, GUI_B['block'].val, "support dxf-BLOCK and ARRAY on/off") + GUI_B['insert'].val = GUI_B['block'].val + if GUI_B['block'].val: + GUI_A['block_nn'] = Draw.Toggle('n', EVENT_NONE, b1-30, y, 15, 20, GUI_A['block_nn'].val, "support hatch/noname BLOCKs *X... on/off") + GUI_A['blockFilter_on'] = Draw.Toggle('F', EVENT_NONE, b1-15, y, 15, 20, GUI_A['blockFilter_on'].val, "(*wip) support name filtering of BLOCKs on/off") + GUI_A['xref_on'] = Draw.Toggle('Xref', EVENT_NONE, b1, y, 20, 20, GUI_A['xref_on'].val, "support place holder for XREF-BLOCKs on/off") + GUI_A['blocks_as'] = Draw.Menu(blocks_as_menu, EVENT_NONE, b1+20, y, b1_-20, 20, GUI_A['blocks_as'].val, "select target representation for imported BLOCKs") Draw.EndAlign() y -= 20 Draw.BeginAlign() - GUI_A['meshSmooth_on'] = Draw.Toggle('smooth', EVENT_NONE, but0c, y, but_0c-20, 20, GUI_A['meshSmooth_on'].val, "mesh smooth for circles/arcsegments on/off") - GUI_A['pl_trim_on'] = Draw.Toggle('trim', EVENT_NONE, but1c-20, y, 32, 20, GUI_A['pl_trim_on'].val, "intersection of POLYLINE-wide-segments on/off") - GUI_A['pl_trim_max'] = Draw.Number('', EVENT_NONE, but1c+12, y, but_1c-12, 20, GUI_A['pl_trim_max'].val, 0, 5, "limit for intersection of POLYLINE-wide-segments: 0.0-5.0") + GUI_A['views_on'] = Draw.Toggle('views', EVENT_NONE, b0, y, b0_-25, 20, GUI_A['views_on'].val, "imports VIEWs and VIEWPORTs as cameras on/off") + GUI_A['cams_on'] = Draw.Toggle('*cams', EVENT_NONE, b1-25, y, b1_-25, 20, GUI_A['cams_on'].val, "(*wip) support ASHADE cameras on/off") + GUI_A['lights_on'] = Draw.Toggle('*lights', EVENT_NONE, b1+25, y, b1_-25, 20, GUI_A['lights_on'].val, "(*wip) support AVE_RENDER lights on/off") Draw.EndAlign() + + y -= 10 + y -= 20 + y -= 20 + y -= 20 + + y -= 10 + y -= 20 Draw.BeginAlign() - GUI_A['dist_on'] = Draw.Toggle('dist.:', EVENT_NONE, but2c, y, but_2c-20, 20, GUI_A['dist_on'].val, "support distance on/off") - GUI_A['dist_force'] = Draw.Toggle('F', EVENT_NONE, but2c+but_2c-20, y, 20, 20, GUI_A['dist_force'].val, "force minimal distance on/off") - GUI_A['dist_min'] = Draw.Number('', EVENT_NONE, but3c, y, but_3c, 20, GUI_A['dist_min'].val, 0, 10, "minimal length/distance (double.vertex removing)") + GUI_A['Z_force_on'] = Draw.Toggle('*elevation', EVENT_REDRAW, b0, y, b0_, 20, GUI_A['Z_force_on'].val, "*set objects Z-coordinates to elevation on/off") + if GUI_A['Z_force_on'].val: + GUI_A['Z_elev'] = Draw.Number('', EVENT_NONE, b1, y, b1_, 20, GUI_A['Z_elev'].val, -1000, 1000, "set default elevation(Z-coordinate)") Draw.EndAlign() y -= 20 Draw.BeginAlign() -# GUI_A['thin_res'] = Draw.Number('thin:', EVENT_NONE, but0c, y, but_0c, 20, GUI_A['thin_res'].val, 4, 64, "thin cylinder resolution - number of segments (4-64)") - GUI_A['arc_rad'] = Draw.Number('bR:', EVENT_NONE, but0c, y, but_0c, 20, GUI_A['arc_rad'].val, 0.01, 100, "basis radius for arc/circle resolution (0.01-100)") - GUI_A['arc_res'] = Draw.Number('', EVENT_NONE, but1c, y, but_1c/2, 20, GUI_A['arc_res'].val, 3, 500, "arc/circle resolution - number of segments (3-500)") - GUI_A['fill_on'] = Draw.Toggle('caps', EVENT_NONE, but1c+but_1c/2, y, but_1c/2, 20, GUI_A['fill_on'].val, "draws top and bottom caps of CYLINDERs/closed curves on/off") + GUI_A['dist_on'] = Draw.Toggle('dist.:', EVENT_NONE, b0, y, b0_-20, 20, GUI_A['dist_on'].val, "support distance on/off") + GUI_A['dist_force'] = Draw.Toggle('F', EVENT_NONE, b0+b0_-20, y, 20, 20, GUI_A['dist_force'].val, "force minimal distance on/off") + GUI_A['dist_min'] = Draw.Number('', EVENT_NONE, b1, y, b1_, 20, GUI_A['dist_min'].val, 0, 10, "minimal length/distance (double.vertex removing)") Draw.EndAlign() - Draw.BeginAlign() - GUI_A['thick_on'] = Draw.Toggle('thick:', EVENT_NONE, but2c, y, but_2c-20, 20, GUI_A['thick_on'].val, "support thickness on/off") - GUI_A['thick_force'] = Draw.Toggle('F', EVENT_NONE, but2c+but_2c-20, y, 20, 20, GUI_A['thick_force'].val, "force minimal thickness on/off") - GUI_A['thick_min'] = Draw.Number('', EVENT_NONE, but3c, y, but_3c, 20, GUI_A['thick_min'].val, 0, 10, "minimal thickness") - Draw.EndAlign() - y -= 20 Draw.BeginAlign() - #GUI_A['group_bylayer_on'] = Draw.Toggle('oneGroup', EVENT_NONE, but0c, y, but_0c, 20, GUI_A['group_bylayer_on'].val, "grouping entities from the same layer on/off") - GUI_A['curves_on'] = Draw.Toggle('to Curves', EVENT_NONE, but0c, y, but_0c, 20, GUI_A['curves_on'].val, "drawing LINE/ARC/POLYLINE into Blender-Curves instead of Meshes on/off") - GUI_A['curve_arc'] = Draw.Number('', EVENT_NONE, but1c, y, but_1c/2, 20, GUI_A['curve_arc'].val, 3, 32, "Bezier circle resolution - number of segments: 3-32") - GUI_A['curve_res'] = Draw.Number('', EVENT_NONE, but1c+but_1c/2, y, but_1c/2, 20, GUI_A['curve_res'].val, 3, 50, "Bezier curve resolution: 3-50") + GUI_A['thick_on'] = Draw.Toggle('thick:', EVENT_NONE, b0, y, b0_-20, 20, GUI_A['thick_on'].val, "support thickness on/off") + GUI_A['thick_force'] = Draw.Toggle('F', EVENT_REDRAW, b0+b0_-20, y, 20, 20, GUI_A['thick_force'].val, "force for thickness at least limiter value on/off") + if GUI_A['thick_force'].val: + GUI_A['thick_min'] = Draw.Number('', EVENT_NONE, b1, y, b1_, 20, GUI_A['thick_min'].val, 0, 10, "minimal value for thickness") Draw.EndAlign() + + y -= 20 Draw.BeginAlign() - GUI_A['width_on'] = Draw.Toggle('width:', EVENT_NONE, but2c, y, but_2c-20, 20, GUI_A['width_on'].val, "support width on/off") - GUI_A['width_force'] = Draw.Toggle('F', EVENT_NONE, but2c+but_2c-20, y, 20, 20, GUI_A['width_force'].val, "force minimal width on/off") - GUI_A['width_min'] = Draw.Number('', EVENT_NONE, but3c, y, but_3c, 20, GUI_A['width_min'].val, 0, 10, "minimal width") + GUI_A['width_on'] = Draw.Toggle('width:', EVENT_NONE, b0, y, b0_-20, 20, GUI_A['width_on'].val, "support width on/off") + GUI_A['width_force'] = Draw.Toggle('F', EVENT_REDRAW, b0+b0_-20, y, 20, 20, GUI_A['width_force'].val, "force for width at least limiter value on/off") + if GUI_A['width_force'].val: + GUI_A['width_min'] = Draw.Number('', EVENT_NONE, b1, y, b1_, 20, GUI_A['width_min'].val, 0, 10, "minimal value for width") Draw.EndAlign() y -= 30 + GUI_A['newScene_on'] = Draw.Toggle('newScene', EVENT_NONE, b0, y, b0_, 20, GUI_A['newScene_on'].val, "creates new Blender-Scene for each import on/off") + GUI_A['target_layer'] = Draw.Number('layer', EVENT_NONE, b1, y, b1_, 20, GUI_A['target_layer'].val, 1, 18, "imports into this Blender-layer (<19> reserved for block_definitions)") + + #-------------------------------------- + if y > y_down: y = y_down #GUI_A['dummy_on'] = Draw.Toggle(' - ', EVENT_NONE, but0c, y, but_0c, 20, GUI_A['dummy_on'].val, "reserved") - GUI_A['one_mesh_on'] = Draw.Toggle('oneMesh', EVENT_NONE, but0c, y, but_0c, 20, GUI_A['one_mesh_on'].val, "draw DXF-entities into one mesh-object. Recommended for big DXF-files. on/off") - GUI_A['newScene_on'] = Draw.Toggle('newScene', EVENT_NONE, but1c, y, but_1c, 20, GUI_A['newScene_on'].val, "creates new Blender-Scene for each import on/off") - GUI_A['target_layer'] = Draw.Number('layer', EVENT_NONE, but2c, y, but_2c, 20, GUI_A['target_layer'].val, 1, 18, "imports into this Blender-layer (<19> reserved for block_definitions)") - GUI_A['optimization'] = Draw.Number('optim:', EVENT_NONE, but3c, y, but_3c, 20, GUI_A['optimization'].val, 0, 3, "Optimization Level: 0=Debug/directDrawing, 1=Verbose, 2=ProgressBar, 3=silentMode/fastest") - y -= 30 Draw.BeginAlign() Draw.PushButton('INI file >', EVENT_CHOOSE_INI, but0c, y, but_0c, 20, 'Select INI-file from project directory') @@ -4666,19 +5663,22 @@ def draw_UI(): #--------------------------------------------------------------- y -= 20 Draw.BeginAlign() - Draw.PushButton('Presets', EVENT_PRESETS, but0c, y, but_0c, 20, "tipist for Preset-INI-files") - Draw.PushButton('Load', EVENT_LOAD_INI, but1c, y, but_1c, 20, ' Loads configuration from ini-file: %s' % iniFileName.val) - Draw.PushButton('Save', EVENT_SAVE_INI, but2c, y, but_2c, 20, 'Saves configuration to ini-file: %s' % iniFileName.val) -# user_preset = Draw.Number('preset:', EVENT_PRESETS, but2c, y, but_2c, 20, user_preset.val, 0, 5, "call user Preset-INI-files") - Draw.PushButton('2D', EVENT_PRESET2D, but3c, y, but_3c/2, 20, 'resets configuration to 2D-defaults') - Draw.PushButton('3D', EVENT_PRESET, but3c+but_3c/2, y, but_3c/2, 20, 'resets configuration to 3D-defaults') + Draw.PushButton('#', EVENT_PRESETS, but0c, y, 20, 20, "tipist for Preset-INI-files") + Draw.PushButton('Load', EVENT_LOAD_INI, but0c+20, y, but_0c-20, 20, '.Loads configuration from ini-file: %s' % iniFileName.val) + Draw.PushButton('Save', EVENT_SAVE_INI, but1c, y, but_1c-20, 20, 'Saves configuration to ini-file: %s' % iniFileName.val) Draw.EndAlign() + but_ = (but_2c+but_3c)/4 + but = but2c + Draw.PushButton('reset', EVENT_RESET, but, y, but_, 20, "reset configuration to defaults") + Draw.PushButton('2D', EVENT_PRESET2D, but+but_, y, but_, 20, 'set configuration for 2D import') + Draw.PushButton('3D', EVENT_PRESET3D, but+but_*2, y, but_, 20, 'set configuration for 3D import') + GUI_A['optimization'] = Draw.Number('', EVENT_NONE, but4c-35, y, 35, 20, GUI_A['optimization'].val, 0, 3, "Optimization Level: 0=Debug/directDrawing, 1=Verbose, 2=ProgressBar, 3=silentMode/fastest") - y -= 30 + y = simple_menu_h Draw.BeginAlign() Draw.PushButton('DXFfile >', EVENT_CHOOSE_DXF, but0c, y, but_0c, 20, 'Select DXF-file from project directory') - dxfFileName = Draw.String(' :', EVENT_NONE, but1c, y, but_1c+but_2c+but_3c-20, 20, dxfFileName.val, FILENAME_MAX, "type the name of DXF-file or * for multi-import") + dxfFileName = Draw.String(' :', EVENT_NONE, but1c, y, but_1c+but_2c+but_3c-20, 20, dxfFileName.val, FILENAME_MAX, "type the name of DXF-file or type *.dxf for multi-import") Draw.PushButton('*.*', EVENT_DXF_DIR, but3c+but_3c-20, y, 20, 20, 'Set asterisk * as filter') Draw.EndAlign() @@ -4687,11 +5687,11 @@ def draw_UI(): #--------------------------------------------------------------- Draw.BeginAlign() Draw.PushButton('EXIT', EVENT_EXIT, but0c, y, but_0c, 40, '' ) Draw.PushButton('HELP', EVENT_HELP, but1c, y, but_1c-20, 20, 'calls BlenderWiki for Manual, Updates and Support.') - Draw.PushButton('?', EVENT_LIST, but1c+but_1c-20, y, 20, 20, 'analyze DXF-file: print listing of LAYERs and BLOCKs into the text-file.INF') + Draw.PushButton('?', EVENT_LIST, but1c+but_1c-20, y, 20, 20, 'DXF analyze tool: print listing of LAYERs and BLOCKs into the text file .INF') Draw.PushButton('START IMPORT', EVENT_START, but2c, y, but_2c+but_3c+butt_margin, 40, 'Start the import procedure') Draw.EndAlign() - config_UI = Draw.Toggle('CONFIG', EVENT_CONFIG, but1c-butt_margin/2, y+20, but_1c+butt_margin, 20, config_UI.val, 'Advanced configuration on/off' ) + config_UI = Draw.Toggle('CONFIG', EVENT_REDRAW, but1c-butt_margin/2, y+20, but_1c+butt_margin, 20, config_UI.val, 'Advanced configuration on/off' ) y -= 20 Draw.BeginAlign() @@ -4709,10 +5709,13 @@ def colorbox(x,y,xright,bottom): def dxf_callback(input_filename): global dxfFileName dxfFileName.val=input_filename +# dirname == Blender.sys.dirname(Blender.Get('filename')) +# update_RegistryKey('DirName', dirname) +# update_RegistryKey('dxfFileName', input_filename) -def ini_callback(input_texture): +def ini_callback(input_filename): global iniFileName - iniFileName.val=input_texture + iniFileName.val=input_filename def event(evt, val): if evt in (Draw.QKEY, Draw.ESCKEY) and not val: @@ -4721,27 +5724,46 @@ def event(evt, val): def bevent(evt): # global EVENT_NONE,EVENT_LOAD_DXF,EVENT_LOAD_INI,EVENT_SAVE_INI,EVENT_EXIT global config_UI, user_preset + global GUI_A ######### Manages GUI events if (evt==EVENT_EXIT): Blender.Draw.Exit() + print 'DXF-Importer *** exit ***' #--------------------- elif (evt==EVENT_CHOOSE_INI): Window.FileSelector(ini_callback, "INI-file Selection", '*.ini') - elif (evt==EVENT_CONFIG): + elif (evt==EVENT_REDRAW): Draw.Redraw() - elif (evt==EVENT_PRESET): + elif (evt==EVENT_RESET): resetDefaultConfig() Draw.Redraw() elif (evt==EVENT_PRESET2D): resetDefaultConfig_2D() Draw.Redraw() + elif (evt==EVENT_SCALE): + if g_scale_as.val == 12: + inputGlobalScale() + if GUI_A['g_scale'].val < 0.00000001: + GUI_A['g_scale'].val = 0.00000001 + Draw.Redraw() + elif (evt==EVENT_ORIGIN): + inputOriginVector() + Draw.Redraw() + elif (evt==EVENT_PRESET3D): + resetDefaultConfig_3D() + Draw.Redraw() + elif (evt==EVENT_PRESETCURV): + presetConfig_curv() + Draw.Redraw() elif (evt==EVENT_PRESETS): user_preset += 1 - if user_preset > 5: user_preset = 1 - iniFileName.val = INIFILE_DEFAULT_NAME + str(user_preset) + INIFILE_EXTENSION + index = str(user_preset) + if user_preset > 5: user_preset = 0; index = '' + iniFileName.val = INIFILE_DEFAULT_NAME + index + INIFILE_EXTENSION Draw.Redraw() elif (evt==EVENT_LIST): dxfFile = dxfFileName.val + update_RegistryKey('dxfFileName', dxfFileName.val) if dxfFile.lower().endswith('.dxf') and sys.exists(dxfFile): analyzeDXF(dxfFile) else: @@ -4770,20 +5792,31 @@ http://wiki.blender.org/index.php?title=Scripts/Manual/Import/DXF-3D') elif '\\' in dxfFile: dxfPathName = '\\'.join(dxfFile.split('\\')[:-1]) + '\\' dxfFileName.val = dxfPathName + '*.dxf' - global GUI_A +# dirname == Blender.sys.dirname(Blender.Get('filename')) +# update_RegistryKey('DirName', dirname) +# update_RegistryKey('dxfFileName', dxfFileName.val) GUI_A['newScene_on'].val = 1 Draw.Redraw() +# elif (evt==EVENT_DXF_NAME): +# dirname == Blender.sys.dirname(Blender.Get('filename')) +# update_RegistryKey('DirName', dirname) +# #print 'deb:EVENT_DXF_NAME dxfFileName.val:', dxfFileName.val #-------------- +# update_RegistryKey('dxfFileName', dxfFileName.val) elif (evt==EVENT_CHOOSE_DXF): - Window.FileSelector(dxf_callback, "DXF-file Selection", '*.dxf') + filename = '' # '*.dxf' + if dxfFileName.val: filename = dxfFileName.val + Window.FileSelector(dxf_callback, "DXF-file Selection", filename) elif (evt==EVENT_START): dxfFile = dxfFileName.val #print 'deb: dxfFile file: ', dxfFile #---------------------- + update_RegistryKey('dxfFileName', dxfFileName.val) if dxfFile.lower().endswith('*.dxf'): if Draw.PupMenu('DXF importer: OK?|will import all DXF-files from:|%s' % dxfFile) == 1: global UI_MODE UI_MODE = False - multi_import(dxfFile[:-5]) # cut last char:'*.dxf' - Draw.Exit() + multi_import(dxfFile[:-5]) # cut last 5 characters '*.dxf' + Draw.Redraw() + #Draw.Exit() else: Draw.Redraw() elif dxfFile.lower().endswith('.dxf') and sys.exists(dxfFile): @@ -4795,6 +5828,7 @@ http://wiki.blender.org/index.php?title=Scripts/Manual/Import/DXF-3D') global SCENE SCENE = Blender.Scene.New(_dxf_file) SCENE.makeCurrent() + Blender.Redraw() #or so? Blender.Scene.makeCurrent(_dxf_file) #sce = bpy.data.scenes.new(_dxf_file) #bpy.data.scenes.active = sce @@ -4822,7 +5856,7 @@ def multi_import(DIR): batchTIME = Blender.sys.time() #if #DIR == "": DIR = os.path.curdir if DIR == "": DIR = Blender.sys.dirname(Blender.Get('filename')) - print 'Multifile Mode: searching for DXF-files in %s' %DIR + print 'Multifiles Import from %s' %DIR files = \ [sys.join(DIR, f) for f in os.listdir(DIR) if f.lower().endswith('.dxf')] if not files: @@ -4832,7 +5866,7 @@ def multi_import(DIR): i = 0 for dxfFile in files: i += 1 - print '\nImporting', dxfFile, ' NUMBER', i, 'of', len(files) + print '\nDXF-file', i, 'of', len(files) #,'\nImporting', dxfFile if GUI_A['newScene_on'].val: _dxf_file = dxfFile.split('/')[-1].split('\\')[-1] _dxf_file = _dxf_file[:-4] # cut last char:'.dxf' @@ -4849,12 +5883,24 @@ def multi_import(DIR): #Blender.Redraw() print 'TOTAL TIME: %.6f' % (Blender.sys.time() - batchTIME) + print '\a\r', # beep when done if __name__ == "__main__": UI_MODE = True + # recall last used DXF-file and INI-file names + dxffilename = check_RegistryKey('dxfFileName') + #print 'deb:start dxffilename:', dxffilename #---------------- + if dxffilename: dxfFileName.val = dxffilename + else: + dirname = Blender.sys.dirname(Blender.Get('filename')) + #print 'deb:start dirname:', dirname #---------------- + dxfFileName.val = sys.join(dirname, '') + inifilename = check_RegistryKey('iniFileName') + if inifilename: iniFileName.val = inifilename + Draw.Register(draw_UI, event, bevent) @@ -4892,4 +5938,4 @@ if 1: main(_dxf) print 'TOTAL TIME: %.6f' % (Blender.sys.time() - TIME) -""" +""" \ No newline at end of file diff --git a/release/scripts/x3d_export.py b/release/scripts/x3d_export.py index 36359f1d122..bf9610fee04 100644 --- a/release/scripts/x3d_export.py +++ b/release/scripts/x3d_export.py @@ -162,8 +162,10 @@ class VRML2Export: ########################################################## def writeHeader(self): - bfile = sys.expandpath(Blender.Get('filename')) + #bfile = sys.expandpath( Blender.Get('filename') ).replace('<', '<').replace('>', '>') + bfile = self.filename.replace('<', '<').replace('>', '>') # use outfile name self.file.write("\n") + print "fooe" self.file.write("\n") self.file.write("\n") self.file.write("\n") @@ -256,7 +258,7 @@ class VRML2Export: headlight = "FALSE" self.file.write("\n\n") + self.file.write("type=\"EXAMINE\", \"ANY\" avatarSize=\"0.25, 1.75, 0.75\" />\n\n") def writeSpotLight(self, ob, lamp): safeName = self.cleanStr(ob.name) @@ -404,7 +406,7 @@ class VRML2Export: self.writeIndented("\n", 1) # right now this script can only handle a single material per mesh. if len(maters) >= 1: - mat=Blender.Material.Get(maters[0].name) + mat=maters[0] matFlags = mat.getMode() if not matFlags & Blender.Material.Modes['TEXFACE']: self.writeMaterial(mat, self.cleanStr(maters[0].name,'')) @@ -452,6 +454,7 @@ class VRML2Export: for face in mesh.faces: if face.smooth: issmooth=1 + break if issmooth==1 and self.wire == 0: creaseAngle=(mesh.getMaxSmoothAngle())*(math.pi/180.0) self.file.write("creaseAngle=\"%s\" " % (round(creaseAngle,self.cp))) diff --git a/source/Makefile b/source/Makefile index 0a7ef2102ca..ef5e4ab52fb 100644 --- a/source/Makefile +++ b/source/Makefile @@ -175,6 +175,10 @@ ifeq ($(WITH_DDS), true) COMLIB += $(OCGDIR)/blender/imbuf/dds/$(DEBUG_DIR)libdds.a endif +ifeq ($(WITH_BINRELOC), true) + COMLIB += $(OCGDIR)/extern/binreloc/$(DEBUG_DIR)libbinreloc.a +endif + ifeq ($(WITH_FREETYPE2), true) COMLIB += $(OCGDIR)/blender/ftfont/$(DEBUG_DIR)libftfont.a ifeq ($(OS), windows) diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h index cbec4cf04fb..1e1c3c110e8 100644 --- a/source/blender/blenkernel/BKE_action.h +++ b/source/blender/blenkernel/BKE_action.h @@ -60,6 +60,11 @@ extern "C" { */ void free_pose_channels(struct bPose *pose); +/** + * Removes and deallocates all data from a pose, and also frees the pose. + */ +void free_pose(struct bPose *pose); + /** * Allocate a new pose on the heap, and copy the src pose and it's channels * into the new pose. *dst is set to the newly allocated structure, and assumed to be NULL. diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index 243425db139..f856b870289 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -44,7 +44,7 @@ struct ListBase; struct MemFile; #define BLENDER_VERSION 245 -#define BLENDER_SUBVERSION 12 +#define BLENDER_SUBVERSION 13 #define BLENDER_MINVERSION 240 #define BLENDER_MINSUBVERSION 0 diff --git a/source/blender/blenkernel/BKE_group.h b/source/blender/blenkernel/BKE_group.h index 9038422795d..1c301bb255c 100644 --- a/source/blender/blenkernel/BKE_group.h +++ b/source/blender/blenkernel/BKE_group.h @@ -45,7 +45,7 @@ void unlink_group(struct Group *group); struct Group *add_group(char *name); void add_to_group(struct Group *group, struct Object *ob); void rem_from_group(struct Group *group, struct Object *ob); -struct Group *find_group(struct Object *ob); +struct Group *find_group(struct Object *ob, struct Group *group); int object_in_group(struct Object *ob, struct Group *group); void group_tag_recalc(struct Group *group); diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h index 47716e66077..ca34240cf27 100644 --- a/source/blender/blenkernel/BKE_image.h +++ b/source/blender/blenkernel/BKE_image.h @@ -47,7 +47,7 @@ struct anim; void free_image(struct Image *me); void BKE_stamp_info(struct ImBuf *ibuf); -void BKE_stamp_buf(unsigned char *rect, float *rectf, int width, int height); +void BKE_stamp_buf(unsigned char *rect, float *rectf, int width, int height, int channels); int BKE_write_ibuf(struct ImBuf *ibuf, char *name, int imtype, int subimtype, int quality); void BKE_makepicstring(char *string, char *base, int frame, int imtype); void BKE_add_image_extension(char *string, int imtype); diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 2008b18b5ed..f324c5d693c 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -236,21 +236,22 @@ void set_node_shader_lamp_loop(void (*lamp_loop_func)(struct ShadeInput *, str /* ************** COMPOSITE NODES *************** */ /* output socket defines */ -#define RRES_OUT_IMAGE 0 -#define RRES_OUT_ALPHA 1 -#define RRES_OUT_Z 2 -#define RRES_OUT_NORMAL 3 -#define RRES_OUT_UV 4 -#define RRES_OUT_VEC 5 -#define RRES_OUT_RGBA 6 -#define RRES_OUT_DIFF 7 -#define RRES_OUT_SPEC 8 -#define RRES_OUT_SHADOW 9 -#define RRES_OUT_AO 10 -#define RRES_OUT_REFLECT 11 -#define RRES_OUT_REFRACT 12 -#define RRES_OUT_RADIO 13 -#define RRES_OUT_INDEXOB 14 +#define RRES_OUT_IMAGE 0 +#define RRES_OUT_ALPHA 1 +#define RRES_OUT_Z 2 +#define RRES_OUT_NORMAL 3 +#define RRES_OUT_UV 4 +#define RRES_OUT_VEC 5 +#define RRES_OUT_RGBA 6 +#define RRES_OUT_DIFF 7 +#define RRES_OUT_SPEC 8 +#define RRES_OUT_SHADOW 9 +#define RRES_OUT_AO 10 +#define RRES_OUT_REFLECT 11 +#define RRES_OUT_REFRACT 12 +#define RRES_OUT_RADIO 13 +#define RRES_OUT_INDEXOB 14 +#define RRES_OUT_MIST 15 /* note: types are needed to restore callbacks, don't change values */ #define CMP_NODE_VIEWER 201 diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index 6e363515f41..0a4c9a04815 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -110,9 +110,10 @@ void solve_tracking (struct Object *ob, float targetmat[][4]); void object_handle_update(struct Object *ob); +float give_timeoffset(struct Object *ob); + #ifdef __cplusplus } #endif #endif - diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index d92e8bad1f9..399f67b7288 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -289,6 +289,8 @@ void psys_particle_on_dm(struct Object *ob, struct DerivedMesh *dm, int from, in void initialize_particle(struct ParticleData *pa, int p, struct Object *ob, struct ParticleSystem *psys, struct ParticleSystemModifierData *psmd); void reset_particle(struct ParticleData *pa, struct ParticleSystem *psys, struct ParticleSystemModifierData *psmd, struct Object *ob, float dtime, float cfra, float *vg_vel, float *vg_tan, float *vg_rot); +void do_effectors(int pa_no, struct ParticleData *pa, struct ParticleKey *state, struct Object *ob, struct ParticleSystem *psys, float *force_field, float *vel,float framestep, float cfra); + void psys_calc_dmfaces(struct Object *ob, struct DerivedMesh *dm, struct ParticleSystem *psys); int psys_particle_dm_face_lookup(struct Object *ob, struct DerivedMesh *dm, int index, float *fw, struct LinkNode *node); diff --git a/source/blender/blenkernel/BKE_sculpt.h b/source/blender/blenkernel/BKE_sculpt.h index d539bcf5e8c..e03e38bab75 100644 --- a/source/blender/blenkernel/BKE_sculpt.h +++ b/source/blender/blenkernel/BKE_sculpt.h @@ -31,30 +31,11 @@ #define BKE_SCULPT_H struct NumInput; +struct RadialControl; 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; @@ -76,7 +57,7 @@ typedef struct SculptSession { /* Used to cache the render of the active texture */ unsigned int texcache_w, texcache_h, *texcache; - struct PropsetData *propset; + struct RadialControl *radialcontrol; /* For rotating around a pivot point */ vec3f pivot; diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index 61668ddb0eb..b8c05f3bb7b 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -178,7 +178,11 @@ void free_action (bAction *act) if (act->chanbase.first) BLI_freelistN(&act->chanbase); - /* Free pose-references */ + /* Free groups */ + if (act->groups.first) + BLI_freelistN(&act->groups); + + /* Free pose-references (aka local markers) */ if (act->markers.first) BLI_freelistN(&act->markers); } @@ -187,19 +191,37 @@ bAction *copy_action (bAction *src) { bAction *dst = NULL; bActionChannel *dchan, *schan; + bActionGroup *dgrp, *sgrp; if (!src) return NULL; dst= copy_libblock(src); + duplicatelist(&(dst->chanbase), &(src->chanbase)); + duplicatelist(&(dst->groups), &(src->groups)); duplicatelist(&(dst->markers), &(src->markers)); - for (dchan=dst->chanbase.first, schan=src->chanbase.first; dchan; dchan=dchan->next, schan=schan->next){ + for (dchan=dst->chanbase.first, schan=src->chanbase.first; dchan; dchan=dchan->next, schan=schan->next) { + for (dgrp=dst->groups.first, sgrp=src->groups.first; dgrp && sgrp; dgrp=dgrp->next, sgrp=sgrp->next) { + if (dchan->grp == sgrp) { + dchan->grp= dgrp; + + if (dgrp->channels.first == schan) + dgrp->channels.first= dchan; + if (dgrp->channels.last == schan) + dgrp->channels.last= dchan; + + break; + } + } + dchan->ipo = copy_ipo(dchan->ipo); copy_constraint_channels(&dchan->constraintChannels, &schan->constraintChannels); } + dst->id.flag |= LIB_FAKEUSER; dst->id.us++; + return dst; } @@ -290,7 +312,7 @@ void free_pose_channels(bPose *pose) { bPoseChannel *pchan; - if (pose->chanbase.first){ + if (pose->chanbase.first) { for (pchan = pose->chanbase.first; pchan; pchan=pchan->next){ if(pchan->path) MEM_freeN(pchan->path); @@ -300,6 +322,21 @@ void free_pose_channels(bPose *pose) } } +void free_pose(bPose *pose) +{ + if (pose) { + /* free pose-channels */ + free_pose_channels(pose); + + /* free pose-groups */ + if (pose->agroups.first) + BLI_freelistN(&pose->agroups); + + /* free pose */ + MEM_freeN(pose); + } +} + static void copy_pose_channel_data(bPoseChannel *pchan, const bPoseChannel *chan) { bConstraint *pcon, *con; @@ -393,7 +430,7 @@ bActionChannel *get_action_channel(bAction *act, const char *name) if (!act || !name) return NULL; - for (chan = act->chanbase.first; chan; chan=chan->next){ + for (chan = act->chanbase.first; chan; chan=chan->next) { if (!strcmp (chan->name, name)) return chan; } @@ -401,18 +438,16 @@ bActionChannel *get_action_channel(bAction *act, const char *name) return NULL; } -/* returns existing channel, or adds new one. In latter case it doesnt activate it, context is required for that*/ +/* returns existing channel, or adds new one. In latter case it doesnt activate it, context is required for that */ bActionChannel *verify_action_channel(bAction *act, const char *name) { bActionChannel *chan; chan= get_action_channel(act, name); - if(chan==NULL) { - if (!chan) { - chan = MEM_callocN (sizeof(bActionChannel), "actionChannel"); - strncpy (chan->name, name, 31); - BLI_addtail (&act->chanbase, chan); - } + if (chan == NULL) { + chan = MEM_callocN (sizeof(bActionChannel), "actionChannel"); + strncpy(chan->name, name, 31); + BLI_addtail(&act->chanbase, chan); } return chan; } @@ -1318,10 +1353,8 @@ static void do_nla(Object *ob, int blocktype) } /* free */ - if (tpose){ - free_pose_channels(tpose); - MEM_freeN(tpose); - } + if (tpose) + free_pose(tpose); if(chanbase.first) BLI_freelistN(&chanbase); } diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index 933cf1f2e3b..a776f2eab80 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -65,6 +65,7 @@ #include "BKE_key.h" #include "BKE_lattice.h" #include "BKE_main.h" +#include "BKE_mesh.h" #include "BKE_object.h" #include "BKE_particle.h" #include "BKE_utildefines.h" @@ -423,6 +424,7 @@ static void vertex_dupli__mapFunc(void *userData, int index, float *co, float *n static void vertex_duplilist(ListBase *lb, ID *id, Object *par, float par_space_mat[][4], int level) { Object *ob, *ob_iter; + Mesh *me; Base *base = NULL; float vec[3], no[3], pmat[4][4]; int lay, totvert, a, oblay; @@ -431,23 +433,22 @@ static void vertex_duplilist(ListBase *lb, ID *id, Object *par, float par_space_ Scene *sce = NULL; Group *group = NULL; GroupObject * go = NULL; - CustomDataMask dataMask = CD_MASK_BAREMESH; Mat4CpyMat4(pmat, par->obmat); /* simple preventing of too deep nested groups */ if(level>MAX_DUPLI_RECUR) return; - if(G.rendering) - dataMask |= CD_MASK_ORCO; - if(par==G.obedit) - dm= editmesh_get_derived_cage(dataMask); + dm= editmesh_get_derived_cage(CD_MASK_BAREMESH); else - dm= mesh_get_derived_deform(par, dataMask); + dm= mesh_get_derived_deform(par, CD_MASK_BAREMESH); - if(G.rendering) - vdd.orco= dm->getVertDataArray(dm, CD_ORCO); + if(G.rendering) { + me= par->data; + vdd.orco= (float(*)[3])get_mesh_orco_verts(par); + transform_mesh_orco_verts(me, vdd.orco, me->totvert, 0); + } else vdd.orco= NULL; @@ -521,6 +522,8 @@ static void vertex_duplilist(ListBase *lb, ID *id, Object *par, float par_space_ else go= go->next; /* group loop */ } + if(vdd.orco) + MEM_freeN(vdd.orco); dm->release(dm); } @@ -534,25 +537,21 @@ static void face_duplilist(ListBase *lb, ID *id, Object *par, float par_space_ma MTFace *mtface; MFace *mface; MVert *mvert; - float pmat[4][4], imat[3][3], (*orco)[3], w; + float pmat[4][4], imat[3][3], (*orco)[3] = NULL, w; int lay, oblay, totface, a; Scene *sce = NULL; Group *group = NULL; GroupObject *go = NULL; - CustomDataMask dataMask = CD_MASK_BAREMESH; float ob__obmat[4][4]; /* needed for groups where the object matrix needs to be modified */ /* simple preventing of too deep nested groups */ if(level>MAX_DUPLI_RECUR) return; - if(G.rendering) - dataMask |= CD_MASK_ORCO; - Mat4CpyMat4(pmat, par->obmat); if(par==G.obedit) { int totvert; - dm= editmesh_get_derived_cage(dataMask); + dm= editmesh_get_derived_cage(CD_MASK_BAREMESH); totface= dm->getNumFaces(dm); mface= MEM_mallocN(sizeof(MFace)*totface, "mface temp"); @@ -562,7 +561,7 @@ static void face_duplilist(ListBase *lb, ID *id, Object *par, float par_space_ma dm->copyVertArray(dm, mvert); } else { - dm = mesh_get_derived_deform(par, dataMask); + dm = mesh_get_derived_deform(par, CD_MASK_BAREMESH); totface= dm->getNumFaces(dm); mface= dm->getFaceArray(dm); @@ -571,7 +570,9 @@ static void face_duplilist(ListBase *lb, ID *id, Object *par, float par_space_ma if(G.rendering) { me= (Mesh*)par->data; - orco= dm->getVertDataArray(dm, CD_ORCO); + + orco= (float(*)[3])get_mesh_orco_verts(par); + transform_mesh_orco_verts(me, orco, me->totvert, 0); mtface= me->mtface; } else { @@ -711,6 +712,9 @@ static void face_duplilist(ListBase *lb, ID *id, Object *par, float par_space_ma MEM_freeN(mface); MEM_freeN(mvert); } + + if(orco) + MEM_freeN(orco); dm->release(dm); } diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index 13b48559f75..b15a5bb42ed 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -308,7 +308,6 @@ static void clean_paths(Main *main) } BLI_clean(scene->r.backbuf); BLI_clean(scene->r.pic); - BLI_clean(scene->r.ftype); scene= scene->id.next; } diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 295c52f1415..6300d882879 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -31,6 +31,7 @@ */ #include +#include #include #include @@ -226,55 +227,7 @@ void do_constraint_channels (ListBase *conbase, ListBase *chanbase, float ctime, /* Find the first available, non-duplicate name for a given constraint */ void unique_constraint_name (bConstraint *con, ListBase *list) { - bConstraint *curcon; - char tempname[64]; - int number = 1, exists = 0; - char *dot; - - /* See if we are given an empty string */ - if (con->name[0] == '\0') { - /* give it default name first */ - strcpy(con->name, "Const"); - } - - /* See if we even need to do this */ - if (list == NULL) - return; - - for (curcon = list->first; curcon; curcon=curcon->next) { - if (curcon != con) { - if (!strcmp(curcon->name, con->name)) { - exists = 1; - break; - } - } - } - - if (exists == 0) - return; - - /* Strip off the suffix */ - dot = strchr(con->name, '.'); - if (dot) - *dot=0; - - for (number = 1; number <= 999; number++) { - sprintf(tempname, "%s.%03d", con->name, number); - - exists = 0; - for (curcon=list->first; curcon; curcon=curcon->next) { - if (con != curcon) { - if (strcmp(curcon->name, tempname)==0) { - exists = 1; - break; - } - } - } - if (exists == 0) { - strcpy(con->name, tempname); - return; - } - } + BLI_uniquename(list, con, "Const", offsetof(bConstraint, name), 32); } /* ----------------- Evaluation Loop Preparation --------------- */ @@ -2036,8 +1989,7 @@ static void actcon_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraint Mat4CpyMat4(ct->matrix, tchan->chan_mat); /* Clean up */ - free_pose_channels(pose); - MEM_freeN(pose); + free_pose(pose); } else if (cob->type == CONSTRAINT_OBTYPE_OBJECT) { /* evaluate using workob */ diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index a963b877912..e1cecaa7a61 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -2064,8 +2064,8 @@ void DAG_object_update_flags(Scene *sce, Object *ob, unsigned int lay) /* object not in scene? then handle group exception. needs to be dagged once too */ if(node==NULL) { - Group *group= find_group(ob); - if(group) { + Group *group= NULL; + while( (group = find_group(ob, group)) ) { GroupObject *go; /* primitive; tag all... this call helps building groups for particles */ for(go= group->gobject.first; go; go= go->next) diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index 1b345616888..6e33805fbeb 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -1552,14 +1552,14 @@ static pMatrixCache *cache_object_matrices(Object *ob, int start, int end) /* object can be linked in group... stupid exception */ if(NULL==object_in_scene(ob, G.scene)) - group= find_group(ob); + group= find_group(ob, NULL); /* TODO - dont just use the first group! - Campbell */ mcache= mc= MEM_mallocN( (end-start+1)*sizeof(pMatrixCache), "ob matrix cache"); framelenold= G.scene->r.framelen; G.scene->r.framelen= 1.0f; cfrao= G.scene->r.cfra; - sfo= ob->sf; + sfo= ob->sf; /* warning, dont use sfo, value should be from give_timeoffset if used for anything */ ob->sf= 0.0f; /* clear storage, copy recalc tag (bad loop) */ diff --git a/source/blender/blenkernel/intern/group.c b/source/blender/blenkernel/intern/group.c index 201d93220f9..b29cf63ab0b 100644 --- a/source/blender/blenkernel/intern/group.c +++ b/source/blender/blenkernel/intern/group.c @@ -164,9 +164,12 @@ int object_in_group(Object *ob, Group *group) return 0; } -Group *find_group(Object *ob) +Group *find_group(Object *ob, Group *group) { - Group *group= G.main->group.first; + if (group) + group= group->id.next; + else + group= G.main->group.first; while(group) { if(object_in_group(ob, group)) @@ -238,12 +241,12 @@ void group_handle_recalc_and_update(Object *parent, Group *group) GroupObject *go; /* if animated group... */ - if(parent->sf != 0.0f || parent->nlastrips.first) { + if(give_timeoffset(parent) != 0.0f || parent->nlastrips.first) { int cfrao; /* switch to local time */ cfrao= G.scene->r.cfra; - G.scene->r.cfra -= (int)parent->sf; + G.scene->r.cfra -= (int)give_timeoffset(parent); /* we need a DAG per group... */ for(go= group->gobject.first; go; go= go->next) { diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 57370688e15..0c45356eb0b 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -969,7 +969,7 @@ static void stampdata(StampData *stamp_data, int do_prefix) } } -void BKE_stamp_buf(unsigned char *rect, float *rectf, int width, int height) +void BKE_stamp_buf(unsigned char *rect, float *rectf, int width, int height, int channels) { struct StampData stamp_data; @@ -1017,7 +1017,7 @@ void BKE_stamp_buf(unsigned char *rect, float *rectf, int width, int height) /* Top left corner */ text_width = BMF_GetStringWidth(font, stamp_data.file); buf_rectfill_area(rect, rectf, width, height, G.scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1); - BMF_DrawStringBuf(font, stamp_data.file, x+(text_pad/2), y, G.scene->r.fg_stamp, rect, rectf, width, height); + BMF_DrawStringBuf(font, stamp_data.file, x+(text_pad/2), y, G.scene->r.fg_stamp, rect, rectf, width, height, channels); y -= font_height+2; /* Top and bottom 1 pix padding each */ } @@ -1025,7 +1025,7 @@ void BKE_stamp_buf(unsigned char *rect, float *rectf, int width, int height) if (stamp_data.note[0]) { text_width = BMF_GetStringWidth(font, stamp_data.note); buf_rectfill_area(rect, rectf, width, height, G.scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1); - BMF_DrawStringBuf(font, stamp_data.note, x+(text_pad/2), y, G.scene->r.fg_stamp, rect, rectf, width, height); + BMF_DrawStringBuf(font, stamp_data.note, x+(text_pad/2), y, G.scene->r.fg_stamp, rect, rectf, width, height, channels); y -= font_height+2; /* Top and bottom 1 pix padding each */ } @@ -1033,7 +1033,7 @@ void BKE_stamp_buf(unsigned char *rect, float *rectf, int width, int height) if (stamp_data.date[0]) { text_width = BMF_GetStringWidth(font, stamp_data.date); buf_rectfill_area(rect, rectf, width, height, G.scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1); - BMF_DrawStringBuf(font, stamp_data.date, x+(text_pad/2), y, G.scene->r.fg_stamp, rect, rectf, width, height); + BMF_DrawStringBuf(font, stamp_data.date, x+(text_pad/2), y, G.scene->r.fg_stamp, rect, rectf, width, height, channels); } /* Bottom left corner, leaving space for timing */ @@ -1042,7 +1042,7 @@ void BKE_stamp_buf(unsigned char *rect, float *rectf, int width, int height) y = font_height+2+1; /* 2 for padding in TIME|FRAME fields below and 1 for padding in this one */ text_width = BMF_GetStringWidth(font, stamp_data.marker); buf_rectfill_area(rect, rectf, width, height, G.scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1); - BMF_DrawStringBuf(font, stamp_data.marker, x+(text_pad/2), y, G.scene->r.fg_stamp, rect, rectf, width, height); + BMF_DrawStringBuf(font, stamp_data.marker, x+(text_pad/2), y, G.scene->r.fg_stamp, rect, rectf, width, height, channels); } /* Left bottom corner */ @@ -1051,7 +1051,7 @@ void BKE_stamp_buf(unsigned char *rect, float *rectf, int width, int height) y = 1; text_width = BMF_GetStringWidth(font, stamp_data.time); buf_rectfill_area(rect, rectf, width, height, G.scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1); - BMF_DrawStringBuf(font, stamp_data.time, x+(text_pad/2), y, G.scene->r.fg_stamp, rect, rectf, width, height); + BMF_DrawStringBuf(font, stamp_data.time, x+(text_pad/2), y, G.scene->r.fg_stamp, rect, rectf, width, height, channels); x += text_width+text_pad+2; /* Both sides have 1 pix additional padding each */ } @@ -1061,7 +1061,7 @@ void BKE_stamp_buf(unsigned char *rect, float *rectf, int width, int height) if (!stamp_data.time[0]) x = 1; y = 1; buf_rectfill_area(rect, rectf, width, height, G.scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1); - BMF_DrawStringBuf(font, stamp_data.frame, x+(text_pad/2), y, G.scene->r.fg_stamp, rect, rectf, width, height); + BMF_DrawStringBuf(font, stamp_data.frame, x+(text_pad/2), y, G.scene->r.fg_stamp, rect, rectf, width, height, channels); } if (stamp_data.camera[0]) { @@ -1070,7 +1070,7 @@ void BKE_stamp_buf(unsigned char *rect, float *rectf, int width, int height) x = (width/2) - (BMF_GetStringWidth(font, stamp_data.camera)/2); y = 1; buf_rectfill_area(rect, rectf, width, height, G.scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1); - BMF_DrawStringBuf(font, stamp_data.camera, x+(text_pad/2), y, G.scene->r.fg_stamp, rect, rectf, width, height); + BMF_DrawStringBuf(font, stamp_data.camera, x+(text_pad/2), y, G.scene->r.fg_stamp, rect, rectf, width, height, channels); } if (stamp_data.scene[0]) { @@ -1079,7 +1079,7 @@ void BKE_stamp_buf(unsigned char *rect, float *rectf, int width, int height) x = width - (text_width+1+text_pad); y = 1; buf_rectfill_area(rect, rectf, width, height, G.scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1); - BMF_DrawStringBuf(font, stamp_data.scene, x+(text_pad/2), y, G.scene->r.fg_stamp, rect, rectf, width, height); + BMF_DrawStringBuf(font, stamp_data.scene, x+(text_pad/2), y, G.scene->r.fg_stamp, rect, rectf, width, height, channels); } if (stamp_data.strip[0]) { @@ -1088,7 +1088,7 @@ void BKE_stamp_buf(unsigned char *rect, float *rectf, int width, int height) x = width - (text_width+1+text_pad); y = height - font_height - 1; buf_rectfill_area(rect, rectf, width, height, G.scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1); - BMF_DrawStringBuf(font, stamp_data.strip, x+(text_pad/2), y, G.scene->r.fg_stamp, rect, rectf, width, height); + BMF_DrawStringBuf(font, stamp_data.strip, x+(text_pad/2), y, G.scene->r.fg_stamp, rect, rectf, width, height, channels); } } diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 8fdfbb71dc9..ed86e1ae17f 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -2727,9 +2727,9 @@ static void displaceModifier_foreachIDLink(ModifierData *md, Object *ob, { DisplaceModifierData *dmd = (DisplaceModifierData*) md; - walk(userData, ob, &dmd->texture); + walk(userData, ob, (ID **)&dmd->texture); - displaceModifier_foreachObjectLink(md, ob, (ObjectWalkFunc) walk, userData); + displaceModifier_foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData); } static int displaceModifier_isDisabled(ModifierData *md) diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index ce14165a499..43a6f2091de 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -2211,6 +2211,8 @@ static void force_hidden_passes(bNode *node, int passflag) if(!(passflag & SCE_PASS_RADIO)) sock->flag |= SOCK_UNAVAIL; sock= BLI_findlink(&node->outputs, RRES_OUT_INDEXOB); if(!(passflag & SCE_PASS_INDEXOB)) sock->flag |= SOCK_UNAVAIL; + sock= BLI_findlink(&node->outputs, RRES_OUT_MIST); + if(!(passflag & SCE_PASS_MIST)) sock->flag |= SOCK_UNAVAIL; } diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index de2875c91f4..94190f9753b 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -229,10 +229,8 @@ void free_object(Object *ob) if(ob->dup_group) ob->dup_group->id.us--; if(ob->defbase.first) BLI_freelistN(&ob->defbase); - if(ob->pose) { - free_pose_channels(ob->pose); - MEM_freeN(ob->pose); - } + if(ob->pose) + free_pose(ob->pose); free_effects(&ob->effect); free_properties(&ob->prop); object_free_modifiers(ob); @@ -1367,7 +1365,7 @@ float bsystem_time(Object *ob, float cfra, float ofs) /* ofset frames */ if ((ob->ipoflag & OB_OFFS_PARENT) && (ob->partype & PARSLOW)==0) - cfra-= ob->sf; + cfra-= give_timeoffset(ob); } cfra-= ofs; @@ -1438,7 +1436,7 @@ static void ob_parcurve(Object *ob, Object *par, float mat[][4]) { Curve *cu; float q[4], vec[4], dir[3], *quat, x1, ctime; - float timeoffs= 0.0; + float timeoffs = 0.0, sf_orig = 0.0; Mat4One(mat); @@ -1449,7 +1447,8 @@ static void ob_parcurve(Object *ob, Object *par, float mat[][4]) /* exception, timeoffset is regarded as distance offset */ if(cu->flag & CU_OFFS_PATHDIST) { - SWAP(float, timeoffs, ob->sf); + timeoffs = give_timeoffset(ob); + SWAP(float, sf_orig, ob->sf); } /* catch exceptions: feature for nla stride editing */ @@ -1466,7 +1465,7 @@ static void ob_parcurve(Object *ob, Object *par, float mat[][4]) } } else { - ctime= G.scene->r.cfra - ob->sf; + ctime= G.scene->r.cfra - give_timeoffset(ob); ctime /= cu->pathlen; CLAMP(ctime, 0.0, 1.0); @@ -1477,7 +1476,7 @@ static void ob_parcurve(Object *ob, Object *par, float mat[][4]) ctime += timeoffs/cu->path->totdist; /* restore */ - SWAP(float, timeoffs, ob->sf); + SWAP(float, sf_orig, ob->sf); } @@ -1735,7 +1734,7 @@ void where_is_object_time(Object *ob, float ctime) if(ob->parent) { Object *par= ob->parent; - if(ob->ipoflag & OB_OFFS_PARENT) ctime-= ob->sf; + if(ob->ipoflag & OB_OFFS_PARENT) ctime-= give_timeoffset(ob); /* hurms, code below conflicts with depgraph... (ton) */ /* and even worse, it gives bad effects for NLA stride too (try ctime != par->ctime, with MBlur) */ @@ -1759,7 +1758,7 @@ void where_is_object_time(Object *ob, float ctime) if(ob->partype & PARSLOW) { // include framerate - fac1= (1.0f/(1.0f+ fabs(ob->sf))); + fac1= (1.0f/(1.0f+ fabs(give_timeoffset(ob)))); if(fac1>=1.0) return; fac2= 1.0f-fac1; @@ -1942,7 +1941,7 @@ for a lamp that is the child of another object */ if(ob->partype & PARSLOW) { - fac1= (float)(1.0/(1.0+ fabs(ob->sf))); + fac1= (float)(1.0/(1.0+ fabs(give_timeoffset(ob)))); fac2= 1.0f-fac1; fp1= ob->obmat[0]; fp2= slowmat[0]; @@ -2199,6 +2198,7 @@ void object_handle_update(Object *ob) if(ob->particlesystem.first) { ParticleSystem *tpsys, *psys; + DerivedMesh *dm; psys= ob->particlesystem.first; while(psys) { @@ -2215,6 +2215,17 @@ void object_handle_update(Object *ob) else psys= psys->next; } + + if(G.rendering && ob->transflag & OB_DUPLIPARTS) { + /* this is to make sure we get render level duplis in groups: + * the derivedmesh must be created before init_render_mesh, + * since object_duplilist does dupliparticles before that */ + dm = mesh_create_derived_render(ob, CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL); + dm->release(dm); + + for(psys=ob->particlesystem.first; psys; psys=psys->next) + psys_get_modifier(ob, psys)->flag &= ~eParticleSystemFlag_psys_updated; + } } } @@ -2235,3 +2246,11 @@ void object_handle_update(Object *ob) // printf("set proxy pointer for later group stuff %s\n", ob->id.name); } } + +float give_timeoffset(Object *ob) { + if ((ob->ipoflag & OB_OFFS_PARENTADD) && ob->parent) { + return ob->sf + give_timeoffset(ob->parent); + } else { + return ob->sf; + } +} diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 0ac60e6da4e..bf8d1e9d8aa 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -2240,7 +2240,7 @@ void psys_cache_paths(Object *ob, ParticleSystem *psys, float cfra, int editupda Material *ma; float birthtime = 0.0, dietime = 0.0; - float t, time, keytime, dfra = 1.0, frs_sec = G.scene->r.frs_sec; + float t, time = 0.0, keytime = 0.0, dfra = 1.0, frs_sec = G.scene->r.frs_sec; float col[3] = {0.5f, 0.5f, 0.5f}; float prev_tangent[3], hairmat[4][4]; int k,i; @@ -2249,6 +2249,7 @@ void psys_cache_paths(Object *ob, ParticleSystem *psys, float cfra, int editupda char nosel[4], sel[4]; float sel_col[3]; float nosel_col[3]; + float length, vec[3]; /* we don't have anything valid to create paths from so let's quit here */ if((psys->flag & PSYS_HAIR_DONE)==0 && (psys->flag & PSYS_KEYED)==0) @@ -2417,7 +2418,6 @@ void psys_cache_paths(Object *ob, ParticleSystem *psys, float cfra, int editupda : ((psys->part->flag & PART_HAIR_BSPLINE) ? KEY_BSPLINE : KEY_CARDINAL) ,keys, keytime, &result); - /* the velocity needs to be converted back from cubic interpolation */ if(psys->flag & PSYS_KEYED){ VecMulf(result.vel, frs_sec / dfra); @@ -2425,12 +2425,49 @@ void psys_cache_paths(Object *ob, ParticleSystem *psys, float cfra, int editupda else if(soft==NULL) { /* softbody and keyed are allready in global space */ Mat4MulVecfl(hairmat, result.co); } - + + VECCOPY(ca->co, result.co); + } + + /*--modify paths--*/ + + VecSubf(vec,(cache[i]+1)->co,cache[i]->co); + length = VecLength(vec); + + for(k=0, ca=cache[i]; k<=steps; k++, ca++) { + /* apply effectors */ + if(edit==0 && k) { + float force[3] = {0.0f,0.0f,0.0f}, vel[3] = {0.0f,0.0f,0.0f}; + ParticleKey eff_key; + + VECCOPY(eff_key.co,(ca-1)->co); + VECCOPY(eff_key.vel,(ca-1)->vel); + QUATCOPY(eff_key.rot,(ca-1)->rot); + + do_effectors(i, pa, &eff_key, ob, psys, force, vel, dfra, cfra); + + VecMulf(force, pow((float)k / (float)steps, 100.0f * psys->part->eff_hair) / (float)steps); + + VecAddf(force, force, vec); + + Normalize(force); + + if(k < steps) { + VecSubf(vec, (ca+1)->co, ca->co); + length = VecLength(vec); + } + + VECADDFAC(ca->co, (ca-1)->co, force, length); + } /* apply guide curves to path data */ if(edit==0 && psys->effectors.first && (psys->part->flag & PART_CHILD_GUIDE)==0) do_guide(&result, i, time, &psys->effectors); + /* apply lattice */ + if(psys->lattice && edit==0) + calc_latt_deform(ca->co, 1.0f); + /* figure out rotation */ if(k) { @@ -2439,7 +2476,7 @@ void psys_cache_paths(Object *ob, ParticleSystem *psys, float cfra, int editupda if(k == 1) { float *q2; - VECSUB(tangent, result.co, (ca - 1)->co); + VECSUB(tangent, ca->co, (ca - 1)->co); q2 = vectoquat(tangent, OB_POSX, OB_POSZ); @@ -2449,7 +2486,7 @@ void psys_cache_paths(Object *ob, ParticleSystem *psys, float cfra, int editupda Normalize(prev_tangent); } else { - VECSUB(tangent, result.co, (ca - 1)->co); + VECSUB(tangent, ca->co, (ca - 1)->co); Normalize(tangent); angle = saacos(Inpf(tangent, prev_tangent)); @@ -2470,8 +2507,9 @@ void psys_cache_paths(Object *ob, ParticleSystem *psys, float cfra, int editupda } } - VECCOPY(ca->co, result.co); + /* set velocity */ + if(k){ VECSUB(ca->vel, ca->co, (ca-1)->co); @@ -2512,9 +2550,6 @@ void psys_cache_paths(Object *ob, ParticleSystem *psys, float cfra, int editupda else{ VECCOPY(ca->col, col); } - - if(psys->lattice && edit==0) - calc_latt_deform(ca->co, 1.0f); } } @@ -3200,13 +3235,13 @@ void psys_get_particle_on_path(Object *ob, ParticleSystem *psys, int p, Particle ParticleData *pa; ChildParticle *cpa; ParticleTexture ptex; - ParticleKey tstate; + ParticleKey *kkey[2] = {NULL, NULL}; HairKey *hkey[2]; ParticleKey *par=0, keys[4]; - float t, real_t, dfra, keytime; + float t, real_t, dfra, keytime, frs_sec = G.scene->r.frs_sec; float co[3], orco[3]; - float imat[4][4], hairmat[4][4], cpa_1st[3]; + float hairmat[4][4]; float pa_clump = 0.0, pa_kink = 0.0; int totparent = 0; int totpart = psys->totpart; @@ -3239,19 +3274,39 @@ void psys_get_particle_on_path(Object *ob, ParticleSystem *psys, int p, Particle return; } - hkey[0] = pa->hair; - hkey[1] = pa->hair + 1; + if(psys->flag & PSYS_KEYED) { + kkey[0] = pa->keys; + kkey[1] = kkey[0] + 1; - real_t = hkey[0]->time + (hkey[0][pa->totkey-1].time - hkey[0]->time) * t; + real_t = kkey[0]->time + t * (kkey[0][pa->totkey-1].time - kkey[0]->time); + } + else { + hkey[0] = pa->hair; + hkey[1] = pa->hair + 1; - while(hkey[1]->time < real_t) - hkey[1]++; + real_t = hkey[0]->time + (hkey[0][pa->totkey-1].time - hkey[0]->time) * t; + } - hkey[0] = hkey[1] - 1; + if(psys->flag & PSYS_KEYED) { + while(kkey[1]->time < real_t) { + kkey[1]++; + } + kkey[0] = kkey[1] - 1; - hair_to_particle(keys + 1, hkey[0]); - hair_to_particle(keys + 2, hkey[1]); + memcpy(keys + 1, kkey[0], sizeof(ParticleKey)); + memcpy(keys + 2, kkey[1], sizeof(ParticleKey)); + } + else { + while(hkey[1]->time < real_t) + hkey[1]++; + hkey[0] = hkey[1] - 1; + + hair_to_particle(keys + 1, hkey[0]); + hair_to_particle(keys + 2, hkey[1]); + } + + if((psys->flag & PSYS_KEYED)==0) { //if(soft){ // if(key[0] != sbel.keys) // DB_copy_key(&k1,key[0]-1); @@ -3276,6 +3331,7 @@ void psys_get_particle_on_path(Object *ob, ParticleSystem *psys, int p, Particle hair_to_particle(keys + 3, hkey[1] + 1); else hair_to_particle(keys + 3, hkey[1]); + } //} //psys_get_particle_on_path(bsys,p,t,bkey,ckey[0]); @@ -3296,24 +3352,38 @@ void psys_get_particle_on_path(Object *ob, ParticleSystem *psys, int p, Particle keytime = (real_t - keys[1].time) / dfra; - interpolate_particle((psys->part->flag & PART_HAIR_BSPLINE) ? KEY_BSPLINE : KEY_CARDINAL + /* convert velocity to timestep size */ + if(psys->flag & PSYS_KEYED){ + VecMulf(keys[1].vel, dfra / frs_sec); + VecMulf(keys[2].vel, dfra / frs_sec); + QuatInterpol(state->rot,keys[1].rot,keys[2].rot,keytime); + } + + interpolate_particle((psys->flag & PSYS_KEYED) ? -1 /* signal for cubic interpolation */ + : ((psys->part->flag & PART_HAIR_BSPLINE) ? KEY_BSPLINE : KEY_CARDINAL) ,keys, keytime, state); - if((pa->flag & PARS_REKEY)==0) { - psys_mat_hair_to_global(ob, psmd->dm, part->from, pa, hairmat); - Mat4MulVecfl(hairmat, state->co); + /* the velocity needs to be converted back from cubic interpolation */ + if(psys->flag & PSYS_KEYED){ + VecMulf(state->vel, frs_sec / dfra); + } + else { + if((pa->flag & PARS_REKEY)==0) { + psys_mat_hair_to_global(ob, psmd->dm, part->from, pa, hairmat); + Mat4MulVecfl(hairmat, state->co); - if(psys->effectors.first && (part->flag & PART_CHILD_GUIDE)==0) { - do_guide(state, p, state->time, &psys->effectors); - /* TODO: proper velocity handling */ + if(psys->effectors.first && (part->flag & PART_CHILD_GUIDE)==0) { + do_guide(state, p, state->time, &psys->effectors); + /* TODO: proper velocity handling */ + } + + if(psys->lattice && edit==0) + calc_latt_deform(state->co,1.0f); } - - if(psys->lattice && edit==0) - calc_latt_deform(state->co,1.0f); } } else if(totchild){ - Mat4Invert(imat,ob->obmat); + //Mat4Invert(imat,ob->obmat); cpa=psys->child+p-totpart; @@ -3345,19 +3415,9 @@ void psys_get_particle_on_path(Object *ob, ParticleSystem *psys, int p, Particle psys_particle_on_emitter(ob,psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa->fuv,foffset,co,0,0,0,orco,0); /* we need to save the actual root position of the child for positioning it accurately to the surface of the emitter */ - VECCOPY(cpa_1st,co); + //VECCOPY(cpa_1st,co); - //w=0; - //while(w<4 && cpa->pa[w]>=0){ - // pa=psys->particles+cpa->pa[w]; - // psys_particle_on_emitter(ob,psmd,part->from,pa->num,pa->fuv,pa->foffset,vec,0,0,0); - // cpa_1st[0] -= cpa->w[w]*vec[0]; - // cpa_1st[1] -= cpa->w[w]*vec[1]; - // cpa_1st[2] -= cpa->w[w]*vec[2]; - // w++; - //} - - Mat4MulVecfl(ob->obmat,cpa_1st); + //Mat4MulVecfl(ob->obmat,cpa_1st); pa=0; } @@ -3412,7 +3472,7 @@ void psys_get_particle_on_path(Object *ob, ParticleSystem *psys, int p, Particle w++; } /* apply offset for correct positioning */ - VECADD(state->co,state->co,cpa_1st); + //VECADD(state->co,state->co,cpa_1st); } else{ /* offset the child from the parent position */ @@ -3452,19 +3512,18 @@ void psys_get_particle_on_path(Object *ob, ParticleSystem *psys, int p, Particle if(part->rough_end != 0.0) do_rough_end(cpa->rand, t, part->rough_end, part->rough_end_shape, state, par); - if(vel){ - if(t>=0.001f){ - tstate.time=t-0.001f; - psys_get_particle_on_path(ob,psys,p,&tstate,0); - VECSUB(state->vel,state->co,tstate.co); - } - else{ - tstate.time=t+0.001f; - psys_get_particle_on_path(ob,psys,p,&tstate,0); - VECSUB(state->vel,tstate.co,state->co); - } - } - + //if(vel){ + // if(t>=0.001f){ + // tstate.time=t-0.001f; + // psys_get_particle_on_path(ob,psys,p,&tstate,0); + // VECSUB(state->vel,state->co,tstate.co); + // } + // else{ + // tstate.time=t+0.001f; + // psys_get_particle_on_path(ob,psys,p,&tstate,0); + // VECSUB(state->vel,tstate.co,state->co); + // } + //} } } /* gets particle's state at a time, returns 1 if particle exists and can be seen and 0 if not */ @@ -3505,18 +3564,18 @@ int psys_get_particle_state(Object *ob, ParticleSystem *psys, int p, ParticleKey return 0; } - //if(bsys->flag & (BSYS_DONE|BSYS_KEYED)){ - // if(between){ - // //ChildParticle *cpa=psys->child+p-totpart; - // //state->time= (cfra-(part->sta+(part->end-part->sta)*cpa->rand[0]))/(part->lifetime*cpa->rand[1]); - // } - // else - // state->time= (cfra-pa->time)/(pa->dietime-pa->time);//pa->lifetime; + if(psys->flag & PSYS_KEYED){ + if(between){ + ChildParticle *cpa=psys->child+p-totpart; + state->time= (cfra-(part->sta+(part->end-part->sta)*cpa->rand[0]))/(part->lifetime*cpa->rand[1]); + } + else + state->time= (cfra-pa->time)/(pa->dietime-pa->time); - // psys_get_particle_on_path(ob,psys,p,state,1); - // return 1; - //} - //else{ + psys_get_particle_on_path(ob,psys,p,state,1); + return 1; + } + else{ //if(psys->totchild && p>=psys->totpart){ // ChildParticle *cpa=psys->child+p-psys->totpart; // ParticleKey *key1, skey; @@ -3560,7 +3619,7 @@ int psys_get_particle_state(Object *ob, ParticleSystem *psys, int p, ParticleKey //} return 1; - //} + } } void psys_get_dupli_texture(Object *ob, ParticleSettings *part, ParticleSystemModifierData *psmd, ParticleData *pa, ChildParticle *cpa, float *uv, float *orco) diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index f69e7bcd05f..94cfdadbb16 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -2607,7 +2607,7 @@ static void precalc_effectors(Object *ob, ParticleSystem *psys, ParticleSystemMo /* calculate forces that all effectors apply to a particle*/ -static void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Object *ob, ParticleSystem *psys, float *force_field, float *vel,float framestep, float cfra) +void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Object *ob, ParticleSystem *psys, float *force_field, float *vel,float framestep, float cfra) { Object *eob; ParticleSystem *epsys; @@ -4050,12 +4050,16 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi pa->alive=PARS_UNBORN; } else{ - pa->loop=0; - if(cfra<=pa->time) - pa->alive=PARS_UNBORN; + pa->loop = 0; + if(cfra <= pa->time) + pa->alive = PARS_UNBORN; /* without dynamics the state is allways known so no need to kill */ - else if(ELEM(part->phystype,PART_PHYS_NO,PART_PHYS_KEYED)==0) - pa->alive=PARS_KILLED; + else if(ELEM(part->phystype, PART_PHYS_NO, PART_PHYS_KEYED)){ + if(cfra < pa->dietime) + pa->alive = PARS_ALIVE; + } + else + pa->alive = PARS_KILLED; } } @@ -4398,7 +4402,9 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier return; } } - else if(part->phystype != PART_PHYS_NO) { /* cache shouldn't be used for none physics */ + else if(ELEM(part->phystype, PART_PHYS_NO, PART_PHYS_KEYED)) + ; /* cache shouldn't be used for "none" or "keyed" physics */ + else { 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)) { @@ -4500,9 +4506,12 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier dynamics_step(ob,psys,psmd,cfra,vg_vel,vg_tan,vg_rot,vg_size); psys->recalc = 0; - psys->cfra=cfra; + psys->cfra = cfra; - if(part->type!=PART_HAIR) + if(part->type == PART_HAIR || part->phystype == PART_PHYS_NO + || (part->phystype == PART_PHYS_KEYED && psys->flag & PSYS_FIRST_KEYED)) + ; /* cache shouldn't be used for hair or "none" or "first keyed" physics */ + else write_particles_to_cache(ob, psys, cfra); /* for keyed particles the path is allways known so it can be drawn */ diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 357b3c1bf54..23aca38463b 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -257,7 +257,6 @@ Scene *add_scene(char *name) strcpy(sce->r.backbuf, "//backbuf"); strcpy(sce->r.pic, U.renderdir); - strcpy(sce->r.ftype, "//ftype"); BLI_init_rctf(&sce->r.safety, 0.1f, 0.9f, 0.1f, 0.9f); sce->r.osa= 8; @@ -661,13 +660,8 @@ void sculptsession_free(Scene *sce) 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); - } + if(ss->radialcontrol) + MEM_freeN(ss->radialcontrol); sculpt_vertexusers_free(ss); if(ss->texcache) diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c index 625ca57dbf3..8d3234475a4 100644 --- a/source/blender/blenkernel/intern/world.c +++ b/source/blender/blenkernel/intern/world.c @@ -98,12 +98,12 @@ World *add_world(char *name) wrld->exp= 0.0f; wrld->exposure=wrld->range= 1.0f; - wrld->aodist= 5.0; + wrld->aodist= 5.0f; wrld->aosamp= 5; - wrld->aoenergy= 1.0; - wrld->aobias= 0.05; + wrld->aoenergy= 1.0f; + wrld->aobias= 0.05f; wrld->ao_samp_method = WO_AOSAMP_HAMMERSLEY; - + wrld->ao_approx_error= 0.25f; wrld->physicsEngine= WOPHY_BULLET;//WOPHY_SUMO; Bullet by default wrld->preview = NULL; diff --git a/source/blender/blenlib/BLI_blenlib.h b/source/blender/blenlib/BLI_blenlib.h index eb13ddc318c..fed513d3279 100644 --- a/source/blender/blenlib/BLI_blenlib.h +++ b/source/blender/blenlib/BLI_blenlib.h @@ -107,6 +107,7 @@ int BLI_findindex(struct ListBase *listbase, void *vlink); void BLI_freelistN(struct ListBase *listbase); void BLI_addtail(struct ListBase *listbase, void *vlink); void BLI_remlink(struct ListBase *listbase, void *vlink); +void BLI_uniquename(struct ListBase *list, void *vlink, char defname[], short name_offs, short len); void BLI_newname(char * name, int add); int BLI_stringdec(char *string, char *kop, char *start, unsigned short *numlen); void BLI_stringenc(char *string, char *kop, char *start, unsigned short numlen, int pic); @@ -254,7 +255,7 @@ void BLI_free_file_lines(struct LinkNode *lines); * @param fullname The full path and full name of the executable * @param name The name of the executable (usually argv[0]) to be checked */ -void BLI_where_am_i(char *fullname, char *name); +void BLI_where_am_i(char *fullname, const char *name); /** * determines the full path to the application bundle on OS X @@ -296,8 +297,8 @@ int BLI_rename(char *from, char *to); int BLI_gzip(char *from, char *to); int BLI_delete(char *file, int dir, int recursive); int BLI_move(char *file, char *to); -int BLI_touch(char *file); -char *BLI_last_slash(char *string); +int BLI_touch(const char *file); +char *BLI_last_slash(const char *string); /* BLI_rct.c */ /** diff --git a/source/blender/blenlib/SConscript b/source/blender/blenlib/SConscript index e11934d968e..649d3cb5659 100644 --- a/source/blender/blenlib/SConscript +++ b/source/blender/blenlib/SConscript @@ -19,6 +19,7 @@ if env['WITH_BF_VERSE']: if env['OURPLATFORM'] == 'linux2': cflags='-pthread' + incs += ' ../../../extern/binreloc/include' if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw'): incs += ' ' + env['BF_PTHREADS_INC'] diff --git a/source/blender/blenlib/intern/Makefile b/source/blender/blenlib/intern/Makefile index 68148a1eb37..9f40710209d 100644 --- a/source/blender/blenlib/intern/Makefile +++ b/source/blender/blenlib/intern/Makefile @@ -59,3 +59,6 @@ endif ifeq ($(WITH_FREETYPE2), true) CPPFLAGS += -DWITH_FREETYPE2 endif +ifeq ($(OS),linux) + CPPFLAGS += -I$(OCGDIR)/extern/binreloc/include +endif \ No newline at end of file diff --git a/source/blender/blenlib/intern/fileops.c b/source/blender/blenlib/intern/fileops.c index fcea30982bd..2ee42d16176 100644 --- a/source/blender/blenlib/intern/fileops.c +++ b/source/blender/blenlib/intern/fileops.c @@ -79,7 +79,7 @@ char *first_slash(char *string) { else return fbslash; } -char *BLI_last_slash(char *string) { +char *BLI_last_slash(const char *string) { char *lfslash, *lbslash; lfslash= strrchr(string, '/'); @@ -140,6 +140,23 @@ int BLI_is_writable(char *filename) } } +int BLI_touch(const char *file) +{ + FILE *f = fopen(file,"r+b"); + if (f != NULL) { + char c = getc(f); + rewind(f); + putc(c,f); + } else { + f = fopen(file,"wb"); + } + if (f) { + fclose(f); + return 1; + } + return 0; +} + #ifdef WIN32 static char str[MAXPATHLEN+12]; @@ -161,12 +178,6 @@ int BLI_delete(char *file, int dir, int recursive) { return err; } -int BLI_touch(char *file) { - callLocalErrorCallBack("Touching files is unsupported on Windows"); - - return 1; -} - int BLI_move(char *file, char *to) { int err; @@ -296,17 +307,6 @@ int BLI_delete(char *file, int dir, int recursive) return -1; } -int BLI_touch(char *file) -{ - - if( BLI_exists("/bin/touch") ) - sprintf(str, "/bin/touch %s", file); - else - sprintf(str, "/usr/bin/touch %s", file); - - return system(str); -} - int BLI_move(char *file, char *to) { sprintf(str, "/bin/mv -f \"%s\" \"%s\"", file, to); diff --git a/source/blender/blenlib/intern/util.c b/source/blender/blenlib/intern/util.c index d1b2efa28c7..d0f58a50eb9 100644 --- a/source/blender/blenlib/intern/util.c +++ b/source/blender/blenlib/intern/util.c @@ -84,6 +84,10 @@ #include #endif +#ifdef __linux__ +#include "binreloc.h" +#endif + /* local */ static int add_win32_extension(char *name); @@ -216,6 +220,79 @@ void BLI_newname(char *name, int add) BLI_stringenc(name, head, tail, digits, pic); } +/* little helper macro for BLI_uniquename */ +#ifndef GIVE_STRADDR + #define GIVE_STRADDR(data, offset) ( ((char *)data) + offset ) +#endif + +/* Generic function to set a unique name. It is only designed to be used in situations + * where the name is part of the struct, and also that the name is at most 128 chars long. + * + * For places where this is used, see constraint.c for example... + * + * name_offs: should be calculated using offsetof(structname, membername) macro from stddef.h + * len: maximum length of string (to prevent overflows, etc.) + * defname: the name that should be used by default if none is specified already + */ +void BLI_uniquename(ListBase *list, void *vlink, char defname[], short name_offs, short len) +{ + Link *link; + char tempname[128]; + int number = 1, exists = 0; + char *dot; + + /* Make sure length can be handled */ + if ((len < 0) || (len > 128)) + return; + + /* See if we are given an empty string */ + if (ELEM(NULL, vlink, defname)) + return; + + if (GIVE_STRADDR(vlink, name_offs) == '\0') { + /* give it default name first */ + BLI_strncpy(GIVE_STRADDR(vlink, name_offs), defname, len); + } + + /* See if we even need to do this */ + if (list == NULL) + return; + + for (link = list->first; link; link= link->next) { + if (link != vlink) { + if (!strcmp(GIVE_STRADDR(link, name_offs), GIVE_STRADDR(vlink, name_offs))) { + exists = 1; + break; + } + } + } + if (exists == 0) + return; + + /* Strip off the suffix */ + dot = strchr(GIVE_STRADDR(vlink, name_offs), '.'); + if (dot) + *dot=0; + + for (number = 1; number <= 999; number++) { + BLI_snprintf(tempname, 128, "%s.%03d", GIVE_STRADDR(vlink, name_offs), number); + + exists = 0; + for (link= list->first; link; link= link->next) { + if (vlink != link) { + if (!strcmp(GIVE_STRADDR(link, name_offs), tempname)) { + exists = 1; + break; + } + } + } + if (exists == 0) { + BLI_strncpy(GIVE_STRADDR(vlink, name_offs), tempname, len); + return; + } + } +} + void BLI_addhead(ListBase *listbase, void *vlink) { @@ -1444,10 +1521,10 @@ static int add_win32_extension(char *name) return (retval); } -void BLI_where_am_i(char *fullname, char *name) +void BLI_where_am_i(char *fullname, const char *name) { char filename[FILE_MAXDIR+FILE_MAXFILE]; - char *path, *temp; + char *path = NULL, *temp; int len; #ifdef _WIN32 char *seperator = ";"; @@ -1457,6 +1534,17 @@ void BLI_where_am_i(char *fullname, char *name) char *slash = "/"; #endif + +#ifdef __linux__ + /* linux uses binreloc since argv[0] is not relyable, call br_init( NULL ) first */ + path = br_find_exe( NULL ); + if (path) { + strcpy(fullname, path); + return; + } +#endif + + /* unix and non linux */ if (name && fullname && strlen(name)) { strcpy(fullname, name); if (name[0] == '.') { diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index dbc2a658ea9..af75e9490d5 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -1861,12 +1861,24 @@ static void direct_link_bones(FileData *fd, Bone* bone) static void direct_link_action(FileData *fd, bAction *act) { bActionChannel *achan; + bActionGroup *agrp; link_list(fd, &act->chanbase); + link_list(fd, &act->groups); link_list(fd, &act->markers); - for (achan = act->chanbase.first; achan; achan=achan->next) + for (achan = act->chanbase.first; achan; achan=achan->next) { + achan->grp= newdataadr(fd, achan->grp); + link_list(fd, &achan->constraintChannels); + } + + for (agrp = act->groups.first; agrp; agrp= agrp->next) { + if (agrp->channels.first) { + agrp->channels.first= newdataadr(fd, agrp->channels.first); + agrp->channels.last= newdataadr(fd, agrp->channels.last); + } + } } static void direct_link_armature(FileData *fd, bArmature *arm) @@ -2528,6 +2540,11 @@ static void direct_link_particlesystems(FileData *fd, ListBase *particles) for(a=0; atotpart; a++, pa++) pa->hair=newdataadr(fd,pa->hair); } + if(psys->particles && psys->particles->keys){ + ParticleData *pa = psys->particles; + for(a=0; atotpart; a++, pa++) + pa->keys=newdataadr(fd,pa->keys); + } psys->child=newdataadr(fd,psys->child); psys->effectors.first=psys->effectors.last=0; @@ -2815,8 +2832,7 @@ static void lib_link_object(FileData *fd, Main *main) else printf("Object %s lost data.", ob->id.name+2); if(ob->pose) { - free_pose_channels(ob->pose); - MEM_freeN(ob->pose); + free_pose(ob->pose); ob->pose= NULL; ob->flag &= ~OB_POSEMODE; } @@ -2953,6 +2969,7 @@ static void direct_link_pose(FileData *fd, bPose *pose) { return; link_list(fd, &pose->chanbase); + link_list(fd, &pose->agroups); for (pchan = pose->chanbase.first; pchan; pchan=pchan->next) { pchan->bone= NULL; @@ -6718,6 +6735,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) Lamp *la; Material *ma; ParticleSettings *part; + World *wrld; Mesh *me; /* unless the file was created 2.44.3 but not 2.45, update the constraints */ @@ -6898,6 +6916,11 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } } + for(wrld=main->world.first; wrld; wrld= wrld->id.next) { + if(wrld->ao_approx_error == 0.0f) + wrld->ao_approx_error= 0.25f; + } + if (main->versionfile < 245 || main->subversionfile < 12) { /* initialize skeleton generation toolsettings */ @@ -7531,6 +7554,14 @@ static void expand_doit(FileData *fd, Main *mainvar, void *old) } } +static void expand_particlesettings(FileData *fd, Main *mainvar, ParticleSettings *part) +{ + expand_doit(fd, mainvar, part->dup_ob); + expand_doit(fd, mainvar, part->dup_group); + expand_doit(fd, mainvar, part->eff_group); + expand_doit(fd, mainvar, part->bb_ob); +} + static void expand_ipo(FileData *fd, Main *mainvar, Ipo *ipo) { IpoCurve *icu; @@ -8123,6 +8154,8 @@ static void expand_main(FileData *fd, Main *mainvar) case ID_IP: expand_ipo(fd, mainvar, (Ipo *)id); break; + case ID_PA: + expand_particlesettings(fd, mainvar, (ParticleSettings *)id); } doit= 1; @@ -8146,34 +8179,42 @@ static int object_in_any_scene(Object *ob) } /* when *lib set, it also does objects that were in the appended group */ -static void give_base_to_objects(Scene *sce, ListBase *lb, Library *lib) +static void give_base_to_objects(Scene *sce, ListBase *lb, Library *lib, int is_group_append) { Object *ob; Base *base; /* give all objects which are LIB_INDIRECT a base, or for a group when *lib has been set */ for(ob= lb->first; ob; ob= ob->id.next) { - + if( ob->id.flag & LIB_INDIRECT ) { - int do_it= 0; - if(ob->id.us==0) - do_it= 1; - else if(ob->id.us==1 && lib) - if(ob->id.lib==lib && (ob->flag & OB_FROMGROUP) && object_in_any_scene(ob)==0) - do_it= 1; - - if(do_it) { - base= MEM_callocN( sizeof(Base), "add_ext_base"); - BLI_addtail(&(sce->base), base); - base->lay= ob->lay; - base->object= ob; - base->flag= ob->flag; - ob->id.us= 1; + /* IF below is quite confusing! + if we are appending, but this object wasnt just added allong with a group, + then this is alredy used indirectly in the scene somewhere else and we didnt just append it. - ob->id.flag -= LIB_INDIRECT; - ob->id.flag |= LIB_EXTERN; - + (ob->id.flag & LIB_APPEND_TAG)==0 means that this is a newly appended object - Campbell */ + if (is_group_append==0 || (ob->id.flag & LIB_APPEND_TAG)==0) { + + int do_it= 0; + + if(ob->id.us==0) + do_it= 1; + else if(ob->id.us==1 && lib) + if(ob->id.lib==lib && (ob->flag & OB_FROMGROUP) && object_in_any_scene(ob)==0) + do_it= 1; + + if(do_it) { + base= MEM_callocN( sizeof(Base), "add_ext_base"); + BLI_addtail(&(sce->base), base); + base->lay= ob->lay; + base->object= ob; + base->flag= ob->flag; + ob->id.us= 1; + + ob->id.flag -= LIB_INDIRECT; + ob->id.flag |= LIB_EXTERN; + } } } } @@ -8312,11 +8353,15 @@ static Library* library_append( Scene *scene, char* file, char *dir, int idcode, lib_verify_nodetree(G.main); /* give a base to loose objects. If group append, do it for objects too */ - if(idcode==ID_GR) - give_base_to_objects(scene, &(G.main->object), (flag & FILE_LINK)?NULL:curlib); - else - give_base_to_objects(scene, &(G.main->object), NULL); - + if(idcode==ID_GR) { + if (flag & FILE_LINK) { + give_base_to_objects(scene, &(G.main->object), NULL, 0); + } else { + give_base_to_objects(scene, &(G.main->object), curlib, 1); + } + } else { + give_base_to_objects(scene, &(G.main->object), NULL, 0); + } /* has been removed... erm, why? s..ton) */ /* 20040907: looks like they are give base already in append_named_part(); -Nathan L */ /* 20041208: put back. It only linked direct, not indirect objects (ton) */ diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 9d766b1e22e..3ac4160b105 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -560,6 +560,13 @@ static void write_particlesystems(WriteData *wd, ListBase *particles) for(a=0; atotpart; a++, pa++) writestruct(wd, DATA, "HairKey", pa->totkey, pa->hair); } + + if(psys->particles->keys) { + ParticleData *pa = psys->particles; + + for(a=0; atotpart; a++, pa++) + writestruct(wd, DATA, "ParticleKey", pa->totkey, pa->keys); + } } if(psys->child) writestruct(wd, DATA, "ChildParticle", psys->totchild ,psys->child); writestruct(wd, DATA, "SoftBody", 1, psys->soft); @@ -772,6 +779,7 @@ static void write_constraints(WriteData *wd, ListBase *conlist) static void write_pose(WriteData *wd, bPose *pose) { bPoseChannel *chan; + bActionGroup *grp; /* Write each channel */ if (!pose) @@ -787,6 +795,10 @@ static void write_pose(WriteData *wd, bPose *pose) writestruct(wd, DATA, "bPoseChannel", 1, chan); } + + /* Write groups */ + for (grp=pose->agroups.first; grp; grp=grp->next) + writestruct(wd, DATA, "bActionGroup", 1, grp); /* Write this pose */ writestruct(wd, DATA, "bPose", 1, pose); @@ -1752,6 +1764,7 @@ static void write_actions(WriteData *wd, ListBase *idbase) { bAction *act; bActionChannel *chan; + bActionGroup *grp; TimeMarker *marker; for(act=idbase->first; act; act= act->id.next) { @@ -1764,6 +1777,10 @@ static void write_actions(WriteData *wd, ListBase *idbase) write_constraint_channels(wd, &chan->constraintChannels); } + for (grp=act->groups.first; grp; grp=grp->next) { + writestruct(wd, DATA, "bActionGroup", 1, grp); + } + for (marker=act->markers.first; marker; marker=marker->next) { writestruct(wd, DATA, "TimeMarker", 1, marker); } diff --git a/source/blender/imbuf/intern/allocimbuf.c b/source/blender/imbuf/intern/allocimbuf.c index a5d404740cf..bc750e455a6 100644 --- a/source/blender/imbuf/intern/allocimbuf.c +++ b/source/blender/imbuf/intern/allocimbuf.c @@ -280,6 +280,7 @@ short imb_addrectfloatImBuf(struct ImBuf * ibuf) size = ibuf->x * ibuf->y; size = size * 4 * sizeof(float); + ibuf->channels= 4; if ( (ibuf->rect_float = MEM_mapallocN(size, "imb_addrectfloatImBuf")) ){ ibuf->mall |= IB_rectfloat; @@ -445,7 +446,7 @@ struct ImBuf *IMB_dupImBuf(struct ImBuf *ibuf1) memcpy(ibuf2->rect, ibuf1->rect, x * y * sizeof(int)); if (flags & IB_rectfloat) - memcpy(ibuf2->rect_float, ibuf1->rect_float, 4 * x * y * sizeof(float)); + memcpy(ibuf2->rect_float, ibuf1->rect_float, ibuf1->channels * x * y * sizeof(float)); if (flags & IB_planes) memcpy(*(ibuf2->planes),*(ibuf1->planes),ibuf1->depth * ibuf1->skipx * y * sizeof(int)); diff --git a/source/blender/imbuf/intern/anim.c b/source/blender/imbuf/intern/anim.c index e72d535815e..1700790c4fa 100644 --- a/source/blender/imbuf/intern/anim.c +++ b/source/blender/imbuf/intern/anim.c @@ -594,7 +594,7 @@ static int startffmpeg(struct anim * anim) { anim->pFrame = avcodec_alloc_frame(); anim->pFrameRGB = avcodec_alloc_frame(); - if (avpicture_get_size(PIX_FMT_RGBA32, anim->x, anim->y) + if (avpicture_get_size(PIX_FMT_BGR32, anim->x, anim->y) != anim->x * anim->y * 4) { fprintf (stderr, "ffmpeg has changed alloc scheme ... ARGHHH!\n"); @@ -617,7 +617,7 @@ static int startffmpeg(struct anim * anim) { anim->pCodecCtx->pix_fmt, anim->pCodecCtx->width, anim->pCodecCtx->height, - PIX_FMT_RGBA, + PIX_FMT_BGR32, SWS_FAST_BILINEAR | SWS_PRINT_INFO, NULL, NULL, NULL); @@ -637,7 +637,7 @@ static ImBuf * ffmpeg_fetchibuf(struct anim * anim, int position) { avpicture_fill((AVPicture *)anim->pFrameRGB, (unsigned char*) ibuf->rect, - PIX_FMT_RGBA32, anim->x, anim->y); + PIX_FMT_BGR32, anim->x, anim->y); if (position != anim->curposition + 1) { if (position > anim->curposition + 1 @@ -714,34 +714,98 @@ static ImBuf * ffmpeg_fetchibuf(struct anim * anim, int position) { } if(frameFinished && pos_found == 1) { - int * dstStride = anim->pFrameRGB->linesize; - uint8_t** dst = anim->pFrameRGB->data; - int dstStride2[4]= { -dstStride[0], 0, 0, 0 }; - uint8_t* dst2[4]= { - dst[0] + (anim->y - 1)*dstStride[0], - 0, 0, 0 }; - int i; - unsigned char* r; + if (G.order == B_ENDIAN) { + int * dstStride + = anim->pFrameRGB->linesize; + uint8_t** dst = anim->pFrameRGB->data; + int dstStride2[4] + = { dstStride[0], 0, 0, 0 }; + uint8_t* dst2[4]= { + dst[0], 0, 0, 0 }; + int x,y,h,w; + unsigned char* bottom; + unsigned char* top; - sws_scale(anim->img_convert_ctx, - anim->pFrame->data, - anim->pFrame->linesize, - 0, - anim->pCodecCtx->height, - dst2, - dstStride2); + sws_scale(anim->img_convert_ctx, + anim->pFrame->data, + anim->pFrame->linesize, + 0, + anim->pCodecCtx->height, + dst2, + dstStride2); - /* workaround: sws_scale sets alpha = 0... */ + /* workaround: sws_scale + sets alpha = 0 and compensate + for altivec-bugs and flipy... */ - r = (unsigned char*) ibuf->rect; + bottom = (unsigned char*) ibuf->rect; + top = bottom + + ibuf->x * (ibuf->y-1) * 4; - for (i = 0; i < ibuf->x * ibuf->y; i++) { - r[3] = 0xff; - r+=4; + h = (ibuf->y + 1) / 2; + w = ibuf->x; + + for (y = 0; y < h; y++) { + unsigned char tmp[4]; + unsigned long * tmp_l = + (unsigned long*) tmp; + tmp[3] = 0xff; + + for (x = 0; x < w; x++) { + tmp[0] = bottom[3]; + tmp[1] = bottom[2]; + tmp[2] = bottom[1]; + + bottom[0] = top[3]; + bottom[1] = top[2]; + bottom[2] = top[1]; + bottom[3] = 0xff; + + *(unsigned long*) top + = *tmp_l; + + bottom +=4; + top += 4; + } + top -= 8 * w; + } + + av_free_packet(&packet); + break; + } else { + int * dstStride + = anim->pFrameRGB->linesize; + uint8_t** dst = anim->pFrameRGB->data; + int dstStride2[4] + = { -dstStride[0], 0, 0, 0 }; + 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, + anim->pFrame->linesize, + 0, + 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; } - - av_free_packet(&packet); - break; } } diff --git a/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp index dafe58a40a7..f842c756ce1 100644 --- a/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp +++ b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp @@ -61,6 +61,7 @@ #include // printf #include // sqrt +#include /*** declarations ***/ @@ -769,7 +770,7 @@ static Color32 buildNormal(uint8 x, uint8 y) float nx = 2 * (x / 255.0f) - 1; float ny = 2 * (y / 255.0f) - 1; float nz = 0.0f; - if (1 - nx*nx - ny*ny > 0) nz = sqrtf(1 - nx*nx - ny*ny); + if (1 - nx*nx - ny*ny > 0) nz = sqrt(1 - nx*nx - ny*ny); uint8 z = clamp(int(255.0f * (nz + 1) / 2.0f), 0, 255); return Color32(x, y, z); diff --git a/source/blender/imbuf/intern/imageprocess.c b/source/blender/imbuf/intern/imageprocess.c index 54e0ec94672..aa09fc3ee38 100644 --- a/source/blender/imbuf/intern/imageprocess.c +++ b/source/blender/imbuf/intern/imageprocess.c @@ -51,22 +51,28 @@ I stole it from util.h in the plugins api */ /* Only this one is used liberally here, and in imbuf */ void IMB_convert_rgba_to_abgr(struct ImBuf *ibuf) { - int size, do_float=0; + int size; unsigned char rt, *cp = (unsigned char *)ibuf->rect; float rtf, *cpf = ibuf->rect_float; - - if (ibuf->rect_float) do_float = 1; - size = ibuf->x * ibuf->y; - while(size-- > 0) { - rt= cp[0]; - cp[0]= cp[3]; - cp[3]= rt; - rt= cp[1]; - cp[1]= cp[2]; - cp[2]= rt; - cp+= 4; - if (do_float) { + if (ibuf->rect) { + size = ibuf->x * ibuf->y; + + while(size-- > 0) { + rt= cp[0]; + cp[0]= cp[3]; + cp[3]= rt; + rt= cp[1]; + cp[1]= cp[2]; + cp[2]= rt; + cp+= 4; + } + } + + if (ibuf->rect_float) { + size = ibuf->x * ibuf->y; + + while(size-- > 0) { rtf= cpf[0]; cpf[0]= cpf[3]; cpf[3]= rtf; diff --git a/source/blender/include/BDR_drawaction.h b/source/blender/include/BDR_drawaction.h index 673b13672c1..1753f4ecf42 100644 --- a/source/blender/include/BDR_drawaction.h +++ b/source/blender/include/BDR_drawaction.h @@ -38,6 +38,7 @@ struct Ipo; struct IpoCurve; struct gla2DDrawInfo; struct bAction; +struct bActionGroup; struct Object; struct ListBase; @@ -75,14 +76,16 @@ void draw_cfra_action(void); /* Channel Drawing */ void draw_icu_channel(struct gla2DDrawInfo *di, struct IpoCurve *icu, float ypos); void draw_ipo_channel(struct gla2DDrawInfo *di, struct Ipo *ipo, float ypos); -void draw_action_channel(struct gla2DDrawInfo *di, bAction *act, float ypos); -void draw_object_channel(struct gla2DDrawInfo *di, Object *ob, float ypos); +void draw_agroup_channel(struct gla2DDrawInfo *di, struct bActionGroup *agrp, float ypos); +void draw_action_channel(struct gla2DDrawInfo *di, struct bAction *act, float ypos); +void draw_object_channel(struct gla2DDrawInfo *di, struct Object *ob, float ypos); /* Keydata Generation */ void icu_to_keylist(struct IpoCurve *icu, ListBase *keys, ListBase *blocks); void ipo_to_keylist(struct Ipo *ipo, ListBase *keys, ListBase *blocks); -void action_to_keylist(bAction *act, ListBase *keys, ListBase *blocks); -void ob_to_keylist(Object *ob, ListBase *keys, ListBase *blocks); +void agroup_to_keylist(struct bActionGroup *agrp, ListBase *keys, ListBase *blocks); +void action_to_keylist(struct bAction *act, ListBase *keys, ListBase *blocks); +void ob_to_keylist(struct Object *ob, ListBase *keys, ListBase *blocks); #endif /* BDR_DRAWACTION_H */ diff --git a/source/blender/include/BDR_editobject.h b/source/blender/include/BDR_editobject.h index b38ee8d3939..9e65a049bfc 100644 --- a/source/blender/include/BDR_editobject.h +++ b/source/blender/include/BDR_editobject.h @@ -111,6 +111,8 @@ void set_ob_ipoflags(void); void select_select_keys(void); int vergbaseco(const void *a1, const void *a2); void auto_timeoffs(void); +void ofs_timeoffs(void); +void rand_timeoffs(void); void texspace_edit(void); void flip_subdivison(int); void mirrormenu(void); diff --git a/source/blender/include/BDR_sculptmode.h b/source/blender/include/BDR_sculptmode.h index e15c1fb7063..8b0b65be4de 100644 --- a/source/blender/include/BDR_sculptmode.h +++ b/source/blender/include/BDR_sculptmode.h @@ -33,7 +33,6 @@ #include "DNA_listBase.h" #include "DNA_vec_types.h" #include "BKE_sculpt.h" -#include "transform.h" struct uiBlock; struct BrushData; @@ -59,15 +58,13 @@ void sculptmode_draw_interface_tools(struct uiBlock *block,unsigned short cx, un void sculptmode_draw_interface_brush(struct uiBlock *block,unsigned short cx, unsigned short cy); void sculptmode_draw_interface_textures(struct uiBlock *block,unsigned short cx, unsigned short cy); void sculptmode_rem_tex(void*,void*); -void sculptmode_propset_init(PropsetMode mode); -void sculptmode_propset(const unsigned short event); void sculptmode_selectbrush_menu(void); void sculptmode_draw_mesh(int); void sculpt_paint_brush(char clear); void sculpt_stroke_draw(); +void sculpt_radialcontrol_start(int mode); struct BrushData *sculptmode_brush(void); -float tex_angle(void); void do_symmetrical_brush_actions(struct EditData *e, short *, short *); void sculptmode_update_tex(void); diff --git a/source/blender/include/BIF_editaction.h b/source/blender/include/BIF_editaction.h index 938d6d3d672..b3e402daa30 100644 --- a/source/blender/include/BIF_editaction.h +++ b/source/blender/include/BIF_editaction.h @@ -43,6 +43,7 @@ /* Some types for easier type-testing */ enum { ACTTYPE_NONE= 0, + ACTTYPE_GROUP, ACTTYPE_ACHAN, ACTTYPE_CONCHAN, ACTTYPE_ICU, @@ -53,6 +54,10 @@ enum { }; /* Macros for easier/more consistant state testing */ +#define EDITABLE_AGRP(agrp) ((agrp->flag & AGRP_PROTECTED)==0) +#define EXPANDED_AGRP(agrp) (agrp->flag & AGRP_EXPANDED) +#define SEL_AGRP(agrp) ((agrp->flag & AGRP_SELECTED) || (agrp->flag & AGRP_ACTIVE)) + #define VISIBLE_ACHAN(achan) ((achan->flag & ACHAN_HIDDEN)==0) #define EDITABLE_ACHAN(achan) ((VISIBLE_ACHAN(achan)) && ((achan->flag & ACHAN_PROTECTED)==0)) #define EXPANDED_ACHAN(achan) ((VISIBLE_ACHAN(achan)) && (achan->flag & ACHAN_EXPANDED)) @@ -81,7 +86,6 @@ enum { /* constants for setting ipo-extrapolation type */ enum { - SET_EXTEND_MENU = 9, SET_EXTEND_POPUP = 10, @@ -91,9 +95,19 @@ enum { SET_EXTEND_CYCLICEXTRAPOLATION }; +/* constants for channel rearranging */ +/* WARNING: don't change exising ones without modifying rearrange func accordingly */ +enum { + REARRANGE_ACTCHAN_TOP= -2, + REARRANGE_ACTCHAN_UP= -1, + REARRANGE_ACTCHAN_DOWN= 1, + REARRANGE_ACTCHAN_BOTTOM= 2 +}; + struct bAction; struct bActionChannel; +struct bActionGroup; struct bPoseChannel; struct Object; struct Ipo; @@ -125,11 +139,16 @@ void free_actcopybuf(void); void copy_actdata(void); void paste_actdata(void); -/* Channel/strip operations */ -void up_sel_action(void); -void down_sel_action(void); -void top_sel_action(void); -void bottom_sel_action(void); +/* Group/Channel Operations */ +struct bActionGroup *get_active_actiongroup(struct bAction *act); +void set_active_actiongroup(struct bAction *act, struct bActionGroup *agrp, short select); +void unique_name_actiongroup(struct ListBase *lb, struct bActionGroup *agrp); +// <--- add some func to add group for action-channel based on corresponding pchan's grouping +void action_groups_group(short add_group); +void action_groups_ungroup(void); + +/* Channel/Strip Operations */ +void rearrange_action_channels(short mode); void expand_all_action(void); void openclose_level_action(short mode); diff --git a/source/blender/include/BIF_editparticle.h b/source/blender/include/BIF_editparticle.h index 77fb091de37..6074dcd4fec 100644 --- a/source/blender/include/BIF_editparticle.h +++ b/source/blender/include/BIF_editparticle.h @@ -38,6 +38,7 @@ struct Object; struct ParticleSystem; struct ParticleEditSettings; +struct RadialControl; /* particle edit mode */ void PE_set_particle_edit(void); @@ -53,6 +54,7 @@ short PE_get_current_num(struct Object *ob); int PE_minmax(float *min, float *max); void PE_get_colors(char sel[4], char nosel[4]); struct ParticleEditSettings *PE_settings(void); +struct RadialControl **PE_radialcontrol(); /* update calls */ void PE_hide_keys_time(struct ParticleSystem *psys, float cfra); @@ -83,6 +85,7 @@ void PE_remove_doubles(void); void PE_mirror_x(int tagged); void PE_selectbrush_menu(void); void PE_remove_doubles(void); +void PE_radialcontrol_start(const int mode); /* undo */ void PE_undo_push(char *str); diff --git a/source/blender/include/BIF_editseq.h b/source/blender/include/BIF_editseq.h index 92046f74009..2874cade043 100644 --- a/source/blender/include/BIF_editseq.h +++ b/source/blender/include/BIF_editseq.h @@ -62,6 +62,7 @@ void mouse_select_seq(void); void no_gaps(void); void seq_snap(short event); void seq_snap_menu(void); +void seq_mute_sel( int mute ); void set_filter_seq(void); void swap_select_seq(void); void touch_seq_files(void); @@ -77,9 +78,18 @@ void select_surround_from_last(); void select_dir_from_last(int lr); void select_neighbor_from_last(int lr); void select_linked_seq(int mode); +int test_overlap_seq(struct Sequence *test); +void shuffle_seq(struct Sequence *test); struct Sequence* alloc_sequence(ListBase *lb, int cfra, int machine); /*used from python*/ int check_single_seq(struct Sequence *seq); +/* seq funcs for transform + notice the difference between start/end and left/right. + + left and right are the bounds at which the setuence is rendered, +start and end are from the start and fixed length of the sequence. +*/ + /* sequence transform functions, for internal used */ int seq_tx_get_start(struct Sequence *seq); int seq_tx_get_end(struct Sequence *seq); @@ -94,40 +104,9 @@ void seq_tx_set_final_right(struct Sequence *seq, int i); int seq_tx_check_left(struct Sequence *seq); int seq_tx_check_right(struct Sequence *seq); -#define SEQ_DEBUG_INFO(seq) printf("seq into '%s' -- len:%i start:%i startstill:%i endstill:%i startofs:%i endofs:%i\n",\ - seq->name, seq->len, seq->start, seq->startstill, seq->endstill, seq->startofs, seq->endofs) +#define SEQ_DEBUG_INFO(seq) printf("seq into '%s' -- len:%i start:%i startstill:%i endstill:%i startofs:%i endofs:%i depth:%i\n",\ + seq->name, seq->len, seq->start, seq->startstill, seq->endstill, seq->startofs, seq->endofs, seq->depth) -/* seq macro's for transform - notice the difference between start/end and left/right. - - left and right are the bounds at which the setuence is rendered, -start and end are from the start and fixed length of the sequence. -*/ -/* -#define SEQ_GET_START(seq) (seq->start) -#define SEQ_GET_END(seq) (seq->start+seq->len) - -#define SEQ_GET_FINAL_LEFT(seq) ((seq->start - seq->startstill) + seq->startofs) -#define SEQ_GET_FINAL_RIGHT(seq) (((seq->start+seq->len) + seq->endstill) - seq->endofs) - -#define SEQ_SET_FINAL_LEFT(seq, val) \ - if (val < (seq)->start) { \ - (seq)->startstill = abs(val - (seq)->start); \ - (seq)->startofs = 0; \ -} else { \ - (seq)->startofs = abs(val - (seq)->start); \ - (seq)->startstill = 0; \ -} - -#define SEQ_SET_FINAL_RIGHT(seq, val) \ - if (val > (seq)->start + (seq)->len) { \ - (seq)->endstill = abs(val - ((seq)->start + (seq)->len)); \ - (seq)->endofs = 0; \ -} else { \ - (seq)->endofs = abs(val - ((seq)->start + (seq)->len)); \ - (seq)->endstill = 0; \ -} -*/ #endif diff --git a/source/blender/include/BIF_radialcontrol.h b/source/blender/include/BIF_radialcontrol.h new file mode 100644 index 00000000000..81181a3a91e --- /dev/null +++ b/source/blender/include/BIF_radialcontrol.h @@ -0,0 +1,62 @@ +/* + * $Id: multires.h 13015 2007-12-27 07:27:03Z nicholasbishop $ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2008 by Nicholas Bishop + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef RADIALCONTROL_H +#define RADIALCONTROL_H + +struct NumInput; + +#define RADIALCONTROL_NONE 0 +#define RADIALCONTROL_SIZE 1 +#define RADIALCONTROL_STRENGTH 2 +#define RADIALCONTROL_ROTATION 3 + +typedef void (*RadialControlCallback)(const int, const int); + +typedef struct RadialControl { + int mode; + short origloc[2]; + + unsigned int tex; + + int new_value; + int original_value; + int max_value; + RadialControlCallback callback; + + struct NumInput *num; +} RadialControl; + +RadialControl *radialcontrol_start(const int mode, RadialControlCallback callback, + const int original_value, const int max_value, + const unsigned int tex); +void radialcontrol_do_events(RadialControl *rc, const unsigned short event); +void radialcontrol_draw(RadialControl *rc); + +#endif diff --git a/source/blender/include/BSE_editaction_types.h b/source/blender/include/BSE_editaction_types.h index 48f0bc39ffc..ae61b09a13a 100644 --- a/source/blender/include/BSE_editaction_types.h +++ b/source/blender/include/BSE_editaction_types.h @@ -37,9 +37,12 @@ /* FILTERED ACTION DATA - TYPES */ /* types of keyframe data in ActListElem */ -#define ALE_NONE 0 -#define ALE_IPO 1 -#define ALE_ICU 2 +typedef enum ALE_KEYTYPE { + ALE_NONE = 0, + ALE_IPO, + ALE_ICU, + ALE_GROUP +} ALE_KEYTYPE; /* This struct defines a structure used for quick access */ typedef struct bActListElem { @@ -53,6 +56,8 @@ typedef struct bActListElem { void *key_data; /* motion data - ipo or ipo-curve */ short datatype; /* type of motion data to expect */ + struct bActionGroup *grp; /* action group that owns the channel */ + void *owner; /* will either be an action channel or fake ipo-channel (for keys) */ short ownertype; /* type of owner */ } bActListElem; @@ -61,17 +66,21 @@ typedef struct bActListElem { /* FILTER ACTION DATA - METHODS/TYPES */ /* filtering flags - under what circumstances should a channel be added */ -#define ACTFILTER_VISIBLE 0x001 /* should channels be visible */ -#define ACTFILTER_SEL 0x002 /* should channels be selected */ -#define ACTFILTER_FOREDIT 0x004 /* does editable status matter */ -#define ACTFILTER_CHANNELS 0x008 /* do we only care that it is a channel */ -#define ACTFILTER_IPOKEYS 0x010 /* only channels referencing ipo's */ -#define ACTFILTER_ONLYICU 0x020 /* only reference ipo-curves */ -#define ACTFILTER_FORDRAWING 0x040 /* make list for interface drawing */ +typedef enum ACTFILTER_FLAGS { + ACTFILTER_VISIBLE = (1<<0), /* should channels be visible */ + ACTFILTER_SEL = (1<<1), /* should channels be selected */ + ACTFILTER_FOREDIT = (1<<2), /* does editable status matter */ + ACTFILTER_CHANNELS = (1<<3), /* do we only care that it is a channel */ + ACTFILTER_IPOKEYS = (1<<4), /* only channels referencing ipo's */ + ACTFILTER_ONLYICU = (1<<5), /* only reference ipo-curves */ + ACTFILTER_FORDRAWING = (1<<6) /* make list for interface drawing */ +} ACTFILTER_FLAGS; /* Action Editor - Main Data types */ -#define ACTCONT_NONE 0 -#define ACTCONT_ACTION 1 -#define ACTCONT_SHAPEKEY 2 +typedef enum ACTCONT_TYPES { + ACTCONT_NONE = 0, + ACTCONT_ACTION, + ACTCONT_SHAPEKEY +} ACTCONT_TYPES; #endif diff --git a/source/blender/include/butspace.h b/source/blender/include/butspace.h index b8d194802ac..c925a0689ef 100644 --- a/source/blender/include/butspace.h +++ b/source/blender/include/butspace.h @@ -315,7 +315,7 @@ void curvemap_buttons(struct uiBlock *block, struct CurveMapping *cumap, char la #define B_FS_PIC 1601 #define B_FS_BACKBUF 1602 -#define B_FS_FTYPE 1604 +#define B_FS_FTYPE 1604 /* FTYPE is no more */ #define B_DORENDER 1605 #define B_DOANIM 1606 #define B_PLAYANIM 1607 @@ -332,7 +332,7 @@ void curvemap_buttons(struct uiBlock *block, struct CurveMapping *cumap, char la #define B_PR_PANO 1619 #define B_PR_NTSC 1620 -#define B_IS_FTYPE 1622 +#define B_IS_FTYPE 1622 /* FTYPE is nomore */ #define B_IS_BACKBUF 1623 #define B_PR_PC 1624 @@ -531,6 +531,11 @@ void curvemap_buttons(struct uiBlock *block, struct CurveMapping *cumap, char la #define B_POSELIB_ALONE 2321 #define B_POSELIB_DELETE 2322 + +#define B_POSEGRP_RECALC 2330 +#define B_POSEGRP_ADD 2331 +#define B_POSEGRP_REMOVE 2332 + /* *********************** */ #define B_CAMBUTS 2500 @@ -732,7 +737,7 @@ enum { #define B_EFFECTSBUTS 3500 -#define B_AUTOTIMEOFS 3403 +#define B_AUTOTIMEOFS 3403 /* see B_OFSTIMEOFS, B_RANDTIMEOFS also */ #define B_FRAMEMAP 3404 #define B_NEWEFFECT 3405 #define B_PREVEFFECT 3406 @@ -767,6 +772,8 @@ enum { #define B_PART_EDITABLE 3435 #define B_PART_REKEY 3436 #define B_PART_ENABLE 3437 +#define B_OFSTIMEOFS 3438 /* see B_AUTOTIMEOFS too */ +#define B_RANDTIMEOFS 3439 #define B_MODIFIER_BUTS 3600 diff --git a/source/blender/include/transform.h b/source/blender/include/transform.h index e9e82612721..30b9bbf3f51 100644 --- a/source/blender/include/transform.h +++ b/source/blender/include/transform.h @@ -265,18 +265,19 @@ typedef struct TransInfo { /* transdata->flag */ #define TD_SELECTED 1 -#define TD_NOACTION 2 -#define TD_USEQUAT 4 -#define TD_NOTCONNECTED 8 -#define TD_SINGLESIZE 16 /* used for scaling of MetaElem->rad */ +#define TD_ACTIVE (1 << 1) +#define TD_NOACTION (1 << 2) +#define TD_USEQUAT (1 << 3) +#define TD_NOTCONNECTED (1 << 4) +#define TD_SINGLESIZE (1 << 5) /* used for scaling of MetaElem->rad */ #ifdef WITH_VERSE - #define TD_VERSE_OBJECT 32 - #define TD_VERSE_VERT 64 + #define TD_VERSE_OBJECT (1 << 6) + #define TD_VERSE_VERT (1 << 7) #endif -#define TD_TIMEONLY 128 -#define TD_NOCENTER 256 -#define TD_NO_EXT 512 /* ext abused for particle key timing */ -#define TD_SKIP 1024 /* don't transform this data */ +#define TD_TIMEONLY (1 << 8) +#define TD_NOCENTER (1 << 9) +#define TD_NO_EXT (1 << 10) /* ext abused for particle key timing */ +#define TD_SKIP (1 << 11) /* don't transform this data */ /* transsnap->status */ #define SNAP_ON 1 @@ -291,6 +292,7 @@ typedef struct TransInfo { #define SNAP_CLOSEST 0 #define SNAP_CENTER 1 #define SNAP_MEDIAN 2 +#define SNAP_ACTIVE 3 void checkFirstTime(void); diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h index 1f591894a90..977abaffeb4 100644 --- a/source/blender/makesdna/DNA_action_types.h +++ b/source/blender/makesdna/DNA_action_types.h @@ -37,6 +37,8 @@ struct SpaceLink; struct Object; +/* -------------- Poses ----------------- */ + /* PoseChannel stores the results of Actions (ipos) and transform information with respect to the restposition of Armature bones */ typedef struct bPoseChannel { @@ -49,7 +51,7 @@ typedef struct bPoseChannel { short ikflag; /* settings for IK bones */ short selectflag; /* copy of bone flag, so you can work with library armatures */ short protectflag; /* protect channels from being transformed */ - short customCol; /* index of custom color set to use (0=default - used for all old files) */ + short agrp_index; /* index of action-group this bone belongs to (0 = default/no group) */ int pathlen; /* for drawing paths, the amount of frames */ int pathsf; /* for drawing paths, the start frame number */ @@ -96,13 +98,45 @@ typedef struct bPose { float ctime; /* local action time of this pose */ float stride_offset[3]; /* applied to object */ float cyclic_offset[3]; /* result of match and cycles, applied in where_is_pose() */ + + + ListBase agroups; /* list of bActionGroups */ + + int active_group; /* index of active group (starts from 1) */ + int pad; } bPose; + +/* ------------- Action ---------------- */ + +/* Action-Channel Group. These are stored as a list per-Action, and are only used to + * group that Action's Action-Channels when displayed in the Action Editor. + * + * Even though all Action-Channels live in a big list per Action, each group they are in also + * holds references to the achans within that list which belong to it. Care must be taken to + * ensure that action-groups never end up being the sole 'owner' of a channel. + */ +typedef struct bActionGroup { + struct bActionGroup *next, *prev; + + int flag; /* settings for this action-group */ + int customCol; /* index of custom color set to use when used for bones (0=default - used for all old files) */ + char name[32]; /* name of the group */ + + ListBase channels; /* Note: this must not be touched by standard listbase functions */ +} bActionGroup; + /* Action Channels belong to Actions. They are linked with an IPO block, and can also own * Constraint Channels in certain situations. + * + * Action-Channels can only belong to one group at a time, but they still live the Action's + * list of achans (to preserve backwards compatability, and also minimise the code + * that would need to be recoded). Grouped achans are stored at the start of the list, according + * to the position of the group in the list, and their position within the group. */ typedef struct bActionChannel { struct bActionChannel *next, *prev; + bActionGroup *grp; /* Action Group this Action Channel belongs to */ struct Ipo *ipo; /* IPO block this action channel references */ ListBase constraintChannels; /* Constraint Channels (when Action Channel represents an Object or Bone) */ @@ -119,12 +153,16 @@ typedef struct bAction { ID id; ListBase chanbase; /* Action Channels in this Action */ + ListBase groups; /* Action Groups in the Action */ ListBase markers; /* TimeMarkers local to this Action for labelling 'poses' */ int active_marker; /* Index of active-marker (first marker = 1) */ int pad; } bAction; + +/* ------------- Action Editor --------------------- */ + /* Action Editor Space. This is defined here instead of in DNA_space_types.h */ typedef struct SpaceAction { struct SpaceLink *next, *prev; @@ -143,6 +181,9 @@ typedef struct SpaceAction { float timeslide; /* for Time-Slide transform mode drawing - current frame? */ } SpaceAction; + +/* -------------- Action Flags -------------- */ + /* Action Channel flags */ typedef enum ACHAN_FLAG { ACHAN_SELECTED = (1<<0), @@ -155,6 +196,20 @@ typedef enum ACHAN_FLAG { ACHAN_MOVED = (1<<31), } ACHAN_FLAG; + +/* Action Group flags */ +typedef enum AGRP_FLAG { + AGRP_SELECTED = (1<<0), + AGRP_ACTIVE = (1<<1), + AGRP_PROTECTED = (1<<2), + AGRP_EXPANDED = (1<<3), + + AGRP_TEMP = (1<<30), + AGRP_MOVED = (1<<31) +} AGRP_FLAG; + +/* ------------ Action Editor Flags -------------- */ + /* SpaceAction flag */ typedef enum SACTION_FLAG { /* during transform */ @@ -178,6 +233,9 @@ typedef enum SACTSNAP_MODES { /* snap to nearest marker */ SACTSNAP_MARKER, } SACTSNAP_MODES; + + +/* --------- Pose Flags --------------- */ /* Pose->flag */ typedef enum POSE_FLAG { diff --git a/source/blender/makesdna/DNA_material_types.h b/source/blender/makesdna/DNA_material_types.h index 1deda6a29d5..d885bfcae82 100644 --- a/source/blender/makesdna/DNA_material_types.h +++ b/source/blender/makesdna/DNA_material_types.h @@ -88,8 +88,10 @@ typedef struct Material { float strand_min, strand_widthfade; char strand_uvname[32]; - float sbias; /* shadow bias */ + float sbias; /* shadow bias to prevent terminator prob */ + float lbias; /* factor to multiply lampbias with (0.0 = no mult) */ float shad_alpha; /* in use for irregular shadowbuffer */ + float padf; /* free padding, take me! */ /* for buttons and render*/ char rgbsel, texact, pr_type, use_nodes; diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index c02b353f604..f3a0dfdfdc7 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -119,7 +119,7 @@ typedef struct Object { int dupon, dupoff, dupsta, dupend; - float sf, ctime; + float sf, ctime; /* sf is time-offset, ctime is the objects current time */ /* during realtime */ @@ -297,6 +297,9 @@ extern Object workob; /* for stride edit */ #define OB_DISABLE_PATH 1024 +#define OB_OFFS_PARENTADD 2048 + + /* (short) trackflag / upflag */ #define OB_POSX 0 #define OB_POSY 1 diff --git a/source/blender/makesdna/DNA_particle_types.h b/source/blender/makesdna/DNA_particle_types.h index f83c2a59799..d39fbbbc679 100644 --- a/source/blender/makesdna/DNA_particle_types.h +++ b/source/blender/makesdna/DNA_particle_types.h @@ -128,7 +128,7 @@ typedef struct ParticleSettings { /* general values */ float sta, end, lifetime, randlife; - float timetweak, jitfac, keyed_time; + float timetweak, jitfac, keyed_time, eff_hair, rt; int totpart, userjit, grid_res; /* initial velocity factors */ diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 282093f39be..b342bc5afe8 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -153,6 +153,8 @@ typedef struct SceneRenderLayer { #define SCE_PASS_INDEXOB 2048 #define SCE_PASS_UV 4096 #define SCE_PASS_RADIO 8192 +#define SCE_PASS_MIST 16384 + /* note, srl->passflag is treestore element 'nr' in outliner, short still... */ @@ -279,7 +281,7 @@ typedef struct RenderData { float YF_gamma, YF_exposure, YF_raybias, YF_AApixelsize, YF_AAthreshold; /* paths to backbufffer, output, ftype */ - char backbuf[160], pic[160], ftype[160]; + char backbuf[160], pic[160]; /* stamps flags. */ int stamp; @@ -549,6 +551,9 @@ typedef struct Scene { #define R_THREADS 0x80000 #define R_SPEED 0x100000 #define R_SSS 0x200000 +#define R_NO_OVERWRITE 0x400000 /* skip existing files */ +#define R_TOUCH 0x800000 /* touch files before rendering */ + /* filtertype */ #define R_FILTER_BOX 0 @@ -608,7 +613,7 @@ typedef struct Scene { #define R_TARGA 0 #define R_IRIS 1 #define R_HAMX 2 -#define R_FTYPE 3 +#define R_FTYPE 3 /* ftype is nomore */ #define R_JPEG90 4 #define R_MOVIE 5 #define R_IRIZ 7 @@ -658,6 +663,7 @@ typedef struct Scene { #define SCE_SNAP_TARGET_CLOSEST 0 #define SCE_SNAP_TARGET_CENTER 1 #define SCE_SNAP_TARGET_MEDIAN 2 +#define SCE_SNAP_TARGET_ACTIVE 3 /* sce->selectmode */ #define SCE_SELECT_VERTEX 1 /* for mesh */ diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 2250e6e43ab..569a6ffc8aa 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -421,7 +421,7 @@ typedef struct SpaceImaSel { /* filesel types */ #define FILE_UNIX 8 -#define FILE_BLENDER 8 +#define FILE_BLENDER 8 /* dont display relative paths */ #define FILE_SPECIAL 9 #define FILE_LOADLIB 1 diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 9f118bd38cc..14002daded5 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -230,7 +230,7 @@ extern UserDef U; /* from usiblender.c !!!! */ #define USER_CUSTOM_RANGE (1 << 17) #define USER_ADD_EDITMODE (1 << 18) #define USER_ADD_VIEWALIGNED (1 << 19) -#define USER_ADD_VIEWALIGNED (1 << 19) +#define USER_RELPATHS (1 << 20) /* viewzom */ #define USER_ZOOM_CONT 0 diff --git a/source/blender/makesdna/DNA_world_types.h b/source/blender/makesdna/DNA_world_types.h index 9e5ec4cdb9a..e7a8d839227 100644 --- a/source/blender/makesdna/DNA_world_types.h +++ b/source/blender/makesdna/DNA_world_types.h @@ -104,9 +104,8 @@ typedef struct World { float aodist, aodistfac, aoenergy, aobias; short aomode, aosamp, aomix, aocolor; float ao_adapt_thresh, ao_adapt_speed_fac; - float pad2[2]; - short ao_samp_method; - short pad1[3]; + float ao_approx_error, ao_approx_correction; + short ao_samp_method, ao_gather_method, ao_approx_passes, pad1; float *aosphere, *aotables; @@ -151,12 +150,17 @@ typedef struct World { /* aomode (use distances & random sampling modes) */ #define WO_AODIST 1 #define WO_AORNDSMP 2 +#define WO_AOCACHE 4 /* aocolor */ #define WO_AOPLAIN 0 #define WO_AOSKYCOL 1 #define WO_AOSKYTEX 2 +/* ao_gather_method */ +#define WO_AOGATHER_RAYTRACE 0 +#define WO_AOGATHER_APPROX 1 + /* texco (also in DNA_material_types.h) */ #define TEXCO_ANGMAP 64 #define TEXCO_H_SPHEREMAP 256 diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_image.c b/source/blender/nodes/intern/CMP_nodes/CMP_image.c index 20308e968d3..0984aa4bfe1 100644 --- a/source/blender/nodes/intern/CMP_nodes/CMP_image.c +++ b/source/blender/nodes/intern/CMP_nodes/CMP_image.c @@ -48,6 +48,7 @@ static bNodeSocketType cmp_node_rlayers_out[]= { { SOCK_RGBA, 0, "Refract", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_RGBA, 0, "Radio", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_VALUE, 0, "IndexOB", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_VALUE, 0, "Mist", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { -1, 0, "" } }; @@ -149,6 +150,8 @@ void outputs_multilayer_get(RenderData *rd, RenderLayer *rl, bNodeStack **out, I out[RRES_OUT_RADIO]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_RADIO); if(out[RRES_OUT_INDEXOB]->hasoutput) out[RRES_OUT_INDEXOB]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_INDEXOB); + if(out[RRES_OUT_MIST]->hasoutput) + out[RRES_OUT_MIST]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_MIST); }; @@ -236,7 +239,7 @@ static CompBuf *compbuf_from_pass(RenderData *rd, RenderLayer *rl, int rectx, in CompBuf *buf; int buftype= CB_VEC3; - if(ELEM(passcode, SCE_PASS_Z, SCE_PASS_INDEXOB)) + if(ELEM3(passcode, SCE_PASS_Z, SCE_PASS_INDEXOB, SCE_PASS_MIST)) buftype= CB_VAL; else if(passcode==SCE_PASS_VECTOR) buftype= CB_VEC4; @@ -282,7 +285,9 @@ void node_composit_rlayers_out(RenderData *rd, RenderLayer *rl, bNodeStack **out if(out[RRES_OUT_RADIO]->hasoutput) out[RRES_OUT_RADIO]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_RADIO); if(out[RRES_OUT_INDEXOB]->hasoutput) - out[RRES_OUT_INDEXOB]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_INDEXOB); + out[RRES_OUT_INDEXOB]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_INDEXOB); + if(out[RRES_OUT_MIST]->hasoutput) + out[RRES_OUT_MIST]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_MIST); }; diff --git a/source/blender/python/api2_2x/Effect.c b/source/blender/python/api2_2x/Effect.c index ce6b553da0d..43c86ebe634 100644 --- a/source/blender/python/api2_2x/Effect.c +++ b/source/blender/python/api2_2x/Effect.c @@ -1330,7 +1330,7 @@ static PyObject *Effect_getParticlesLoc( BPy_Effect * self ) /* if object is in motion */ if( ob->ipoflag & OB_OFFS_PARTICLE ) - p_time= ob->sf; + p_time= give_timeoffset(ob); else p_time= 0.0; diff --git a/source/blender/python/api2_2x/Group.c b/source/blender/python/api2_2x/Group.c index 26e5edd0733..b4819a425f3 100644 --- a/source/blender/python/api2_2x/Group.c +++ b/source/blender/python/api2_2x/Group.c @@ -697,7 +697,7 @@ static PyObject *GroupObSeq_unlink( BPy_GroupObSeq * self, BPy_Object *value ) rem_from_group(self->bpygroup->group, blen_ob); - if(find_group(blen_ob)==NULL) { + if(find_group(blen_ob, NULL)==NULL) { blen_ob->flag &= ~OB_FROMGROUP; base= object_in_scene(blen_ob, G.scene); diff --git a/source/blender/python/api2_2x/doc/Ipo.py b/source/blender/python/api2_2x/doc/Ipo.py index b8c472b371a..c479926ccf3 100644 --- a/source/blender/python/api2_2x/doc/Ipo.py +++ b/source/blender/python/api2_2x/doc/Ipo.py @@ -47,7 +47,7 @@ The valid IpoCurve constants are: 4. Camera Ipo: CA_LENS, CA_CLSTA, CA_CLEND, CA_APERT, CA_FDIST 5. Object Ipo: OB_LOCX, OB_LOCY, OB_LOCZ, OB_DLOCX, OB_DLOCY, OB_DLOCZ, OB_ROTX, OB_ROTY, OB_ROTZ, OB_DROTX, OB_DROTY, OB_DROTZ, - OB_SIZEX, OB_SIZEY, OB_SIZEZ, OB_DSIZEX, OB_DSIZEY, OB_DSIZEZ, + OB_SCALEX, OB_SCALEY, OB_SCALEZ, OB_DSCALEX, OB_DSCALEY, OB_DSCALEZ, OB_LAYER, OB_TIME, OB_COLR, OB_COLG, OB_COLB, OB_COLA, OB_FSTRENG, OB_FFALL, OB_RDAMP, OB_DAMPING, OB_PERM 6. Curve Ipo: CU_SPEED diff --git a/source/blender/python/api2_2x/doc/Render.py b/source/blender/python/api2_2x/doc/Render.py index d75e07de8e3..7ab3d7b90a9 100644 --- a/source/blender/python/api2_2x/doc/Render.py +++ b/source/blender/python/api2_2x/doc/Render.py @@ -246,10 +246,12 @@ class RenderData: @type extensions: boolean @ivar compositor: 'Do Compositor' enabled. @type compositor: boolean - @ivar freeImages: 'Do Compositor' enabled. + @ivar freeImages: Texture images are freed after render. @type freeImages: boolean @ivar singleLayer: Only render the active layer. @type singleLayer: boolean + @ivar activeLayer: The active render layer. Must be in range[0,num render layers-1] + @type activeLayer: int @ivar saveBuffers: Save render buffers to disk while rendering, saves memory. @type saveBuffers: boolean @ivar compositeFree: Free nodes that are not used while composite. diff --git a/source/blender/python/api2_2x/sceneRender.c b/source/blender/python/api2_2x/sceneRender.c index aecd1d5b356..5f71cfc4bd1 100644 --- a/source/blender/python/api2_2x/sceneRender.c +++ b/source/blender/python/api2_2x/sceneRender.c @@ -116,8 +116,6 @@ static PyObject *RenderData_SetRenderPath( BPy_RenderData *self, PyObject *args ); static PyObject *RenderData_SetBackbufPath( BPy_RenderData *self, PyObject *args ); -static PyObject *RenderData_SetFtypePath( BPy_RenderData *self, - PyObject *args ); static PyObject *RenderData_SetOversamplingLevel( BPy_RenderData * self, PyObject * args ); static PyObject *RenderData_SetRenderWinSize( BPy_RenderData * self, @@ -982,7 +980,6 @@ static int RenderData_setImageType( BPy_RenderData *self, PyObject *value ) case R_HAMX : case R_IRIS : case R_IRIZ : - case R_FTYPE : case R_TIFF : case R_CINEON : case R_DPX : @@ -2220,29 +2217,6 @@ static int RenderData_setBackbufPath( BPy_RenderData *self, PyObject *value ) return 0; } -PyObject *RenderData_getFtypePath( BPy_RenderData * self ) -{ - return PyString_FromString( self->renderContext->ftype ); -} - -static int RenderData_setFtypePath( BPy_RenderData *self, PyObject *value ) -{ - char *name; - - name = PyString_AsString( value ); - if( !name ) - return EXPP_ReturnIntError( PyExc_TypeError, "expected a string" ); - - if( strlen( name ) >= sizeof(self->renderContext->ftype) ) - return EXPP_ReturnIntError( PyExc_ValueError, - "ftype path is too long" ); - - strcpy( self->renderContext->ftype, name ); - EXPP_allqueue( REDRAWBUTSSCENE, 0 ); - - return 0; -} - PyObject *RenderData_getRenderWinSize( BPy_RenderData * self ) { return PyInt_FromLong( (long) self->renderContext->size ); @@ -2357,6 +2331,32 @@ static int RenderData_setThreads( BPy_RenderData *self, PyObject *value ) return 0; } +PyObject *RenderData_getActiveLayer( BPy_RenderData * self ) +{ + return PyInt_FromLong( (long) self->renderContext->actlay ); +} + +static int RenderData_setActiveLayer( BPy_RenderData *self, PyObject *value ) +{ + int layer; + short nr; + SceneRenderLayer *srl; + + if( !PyInt_Check( value ) ) + return EXPP_ReturnIntError( PyExc_TypeError, "active layer must be an int" ); + + layer = PyInt_AsLong( value ); + for(nr=0, srl= self->renderContext->layers.first; srl; srl= srl->next, nr++) { + } + if(layer >= nr) + return EXPP_ReturnIntError( PyExc_ValueError, "value larger than number of render layers" ); + + self->renderContext->actlay = layer; + EXPP_allqueue(REDRAWBUTSSCENE, 0); + EXPP_allqueue(REDRAWNODE, 0); + return 0; +} + /***************************************************************************/ /* BPy_RenderData attribute def */ /***************************************************************************/ @@ -2481,10 +2481,6 @@ static PyGetSetDef BPy_RenderData_getseters[] = { (getter)RenderData_getBackbufPath, (setter)RenderData_setBackbufPath, "Path to a background image (setting loads image)", NULL}, - {"ftypePath", - (getter)RenderData_getFtypePath, (setter)RenderData_setFtypePath, - "The path to Ftype file", - NULL}, {"edgeColor", (getter)RenderData_getEdgeColor, (setter)RenderData_setEdgeColor, "RGB color triplet for edges in Toon shading", @@ -2600,6 +2596,11 @@ static PyGetSetDef BPy_RenderData_getseters[] = { "Scene link 'set' value", NULL}, + {"activeLayer", + (getter)RenderData_getActiveLayer, (setter)RenderData_setActiveLayer, + "Active rendering layer", + NULL}, + {"yafrayGIMethod", (getter)RenderData_getYafrayGIMethod, (setter)RenderData_setYafrayGIMethod, "Global illumination method", @@ -2699,10 +2700,6 @@ static PyMethodDef BPy_RenderData_methods[] = { {"enableBackbuf", ( PyCFunction ) RenderData_EnableBackbuf, METH_VARARGS, "(bool) - enable/disable the backbuf image"}, - {"setFtypePath", ( PyCFunction ) RenderData_SetFtypePath, METH_VARARGS, - "(string) - get/set the path to output the Ftype file"}, - {"getFtypePath", ( PyCFunction ) RenderData_getFtypePath, METH_NOARGS, - "() - get the path to Ftype file"}, {"enableExtensions", ( PyCFunction ) RenderData_EnableExtensions, METH_VARARGS, "(bool) - enable/disable windows extensions for output files"}, @@ -3109,7 +3106,6 @@ PyObject *Render_Init( void ) PyModule_AddIntConstant( submodule, "HAMX", R_HAMX ); PyModule_AddIntConstant( submodule, "IRIS", R_IRIS ); PyModule_AddIntConstant( submodule, "IRISZ", R_IRIZ ); - PyModule_AddIntConstant( submodule, "FTYPE", R_FTYPE ); PyModule_AddIntConstant( submodule, "PAL", B_PR_PAL ); PyModule_AddIntConstant( submodule, "NTSC", B_PR_NTSC ); PyModule_AddIntConstant( submodule, "DEFAULT", B_PR_PRESET ); @@ -3173,13 +3169,6 @@ static PyObject *RenderData_SetBackbufPath( BPy_RenderData *self, (setter)RenderData_setBackbufPath ); } -static PyObject *RenderData_SetFtypePath( BPy_RenderData *self, - PyObject *args ) -{ - return EXPP_setterWrapperTuple( (void *)self, args, - (setter)RenderData_setFtypePath ); -} - static PyObject *RenderData_SetOversamplingLevel( BPy_RenderData * self, PyObject * args ) { diff --git a/source/blender/render/extern/include/RE_shader_ext.h b/source/blender/render/extern/include/RE_shader_ext.h index 8971126e643..8b5880ff507 100644 --- a/source/blender/render/extern/include/RE_shader_ext.h +++ b/source/blender/render/extern/include/RE_shader_ext.h @@ -47,7 +47,7 @@ typedef struct ShadeResult { float combined[4]; float col[4]; - float alpha; + float alpha, mist; float diff[3]; /* no ramps, shadow, etc */ float spec[3]; float shad[3]; @@ -64,6 +64,7 @@ struct ShadeInputCopy { struct Material *mat; struct VlakRen *vlr; + struct StrandRen *strand; struct ObjectInstanceRen *obi; struct ObjectRen *obr; int facenr; @@ -96,6 +97,7 @@ typedef struct ShadeInput struct Material *mat; struct VlakRen *vlr; + struct StrandRen *strand; struct ObjectInstanceRen *obi; struct ObjectRen *obr; int facenr; @@ -132,7 +134,7 @@ typedef struct ShadeInput /* texture coordinates */ float lo[3], gl[3], ref[3], orn[3], winco[3], sticky[3], vcol[4], rad[3]; float refcol[4], displace[3]; - float strand, tang[3], stress, winspeed[4]; + float strandco, tang[3], stress, winspeed[4]; float duplilo[3], dupliuv[3]; ShadeInputUV uv[8]; /* 8 = MAX_MTFACE */ diff --git a/source/blender/render/intern/include/occlusion.h b/source/blender/render/intern/include/occlusion.h new file mode 100644 index 00000000000..3f10d50ab2e --- /dev/null +++ b/source/blender/render/intern/include/occlusion.h @@ -0,0 +1,51 @@ +/* + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2008 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Brecht Van Lommel. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef OCCLUSION_H +#define OCCLUSION_H + +struct Render; +struct ShadeInput; +struct ShadeResult; +struct RenderPart; +struct ShadeSample; +struct DerivedMesh; +struct ObjectRen; + +void make_occ_tree(struct Render *re); +void free_occ(struct Render *re); +void sample_occ(struct Render *re, struct ShadeInput *shi); + +void cache_occ_samples(struct Render *re, struct RenderPart *pa, struct ShadeSample *ssamp); +void free_occ_samples(struct Render *re, struct RenderPart *pa); + +void *cache_occ_mesh(struct Render *re, struct ObjectRen *obr, struct DerivedMesh *dm, float mat[][4]); + +#endif + diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h index 9034ff79243..6124870d63e 100644 --- a/source/blender/render/intern/include/render_types.h +++ b/source/blender/render/intern/include/render_types.h @@ -158,6 +158,10 @@ struct Render /* octree tables and variables for raytrace */ void *raytree; + + /* occlusion tree */ + void *occlusiontree; + ListBase occlusionmesh; /* use this instead of R.r.cfra */ float cfra; @@ -174,7 +178,6 @@ struct Render struct ObjectInstanceRen *objectinstance; ListBase instancetable; - struct GHash *objecthash; int totinstance; struct Image *backbuf, *bakebuf; @@ -342,6 +345,7 @@ typedef struct StrandBuffer { struct ObjectRen *obr; struct Material *ma; + void *occlusionmesh; unsigned int lay; int overrideuv; int flag, maxdepth; diff --git a/source/blender/render/intern/include/renderdatabase.h b/source/blender/render/intern/include/renderdatabase.h index a3a3b4e5e4a..a74579acc4a 100644 --- a/source/blender/render/intern/include/renderdatabase.h +++ b/source/blender/render/intern/include/renderdatabase.h @@ -70,6 +70,7 @@ typedef struct StrandTableNode { float *winspeed; float *surfnor; float *simplify; + int *face; struct MCol *mcol; float *uv; int totuv, totmcol; @@ -114,6 +115,7 @@ float *RE_strandren_get_surfnor(struct ObjectRen *obr, struct StrandRen *strand, float *RE_strandren_get_uv(struct ObjectRen *obr, struct StrandRen *strand, int n, char **name, int verify); struct MCol *RE_strandren_get_mcol(struct ObjectRen *obr, struct StrandRen *strand, int n, char **name, int verify); float *RE_strandren_get_simplify(struct ObjectRen *obr, struct StrandRen *strand, int verify); +int *RE_strandren_get_face(struct ObjectRen *obr, struct StrandRen *strand, int verify); float *RE_strandren_get_winspeed(struct ObjectInstanceRen *obi, struct StrandRen *strand, int verify); struct VertRen *RE_vertren_copy(struct ObjectRen *obr, struct VertRen *ver); diff --git a/source/blender/render/intern/include/shadbuf.h b/source/blender/render/intern/include/shadbuf.h index 20a266f8579..c5d8f2690c7 100644 --- a/source/blender/render/intern/include/shadbuf.h +++ b/source/blender/render/intern/include/shadbuf.h @@ -57,7 +57,7 @@ void threaded_makeshadowbufs(struct Render *re); * @param inp The inproduct between viewvector and ? * */ -float testshadowbuf(struct ShadBuf *shb, float *rco, float *dxco, float *dyco, float inp); +float testshadowbuf(struct ShadBuf *shb, float *rco, float *dxco, float *dyco, float inp, float mat_bias); /** * Determines the shadow factor for lamp , between diff --git a/source/blender/render/intern/include/shading.h b/source/blender/render/intern/include/shading.h index 6ca63a2976d..e3ffe5ef28f 100644 --- a/source/blender/render/intern/include/shading.h +++ b/source/blender/render/intern/include/shading.h @@ -69,6 +69,7 @@ void shade_input_initialize(struct ShadeInput *shi, struct RenderPart *pa, struc void shade_sample_initialize(struct ShadeSample *ssamp, struct RenderPart *pa, struct RenderLayer *rl); void shade_samples_do_AO(struct ShadeSample *ssamp); +void shade_samples_fill_with_ps(struct ShadeSample *ssamp, struct PixStr *ps, int x, int y); int shade_samples(struct ShadeSample *ssamp, struct PixStr *ps, int x, int y); void vlr_set_uv_indices(struct VlakRen *vlr, int *i1, int *i2, int *i3); diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index 1e391508228..293b367a049 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -100,6 +100,7 @@ #include "envmap.h" #include "multires.h" +#include "occlusion.h" #include "render_types.h" #include "rendercore.h" #include "renderdatabase.h" @@ -1497,7 +1498,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem float *orco=0,*surfnor=0,*uvco=0, strandlen=0.0f, curlen=0.0f; float hasize, pa_size, pa_time, r_tilt, cfra=bsystem_time(ob,(float)CFRA,0.0); float adapt_angle=0.0, adapt_pix=0.0, random, simplify[2]; - int i, a, k, max_k=0, totpart, totuv=0, override_uv=-1, dosimplify = 0; + int i, a, k, max_k=0, totpart, totuv=0, override_uv=-1, dosimplify = 0, doapproxao = 0; int path_possible=0, keys_possible=0, baked_keys=0, totchild=psys->totchild; int seed, path_nbr=0, path=0, orco1=0, adapt=0, uv[3]={0,0,0}, num; char **uv_name=0; @@ -1656,6 +1657,10 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem strandbuf->flag |= R_STRAND_B_UNITS; svert= strandbuf->vert; + + if((re->wrld.mode & WO_AMB_OCC) && (re->wrld.ao_gather_method == WO_AOGATHER_APPROX)) + if(ma->amb != 0.0f) + doapproxao= 1; } } } @@ -1704,15 +1709,15 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem else psys_particle_on_emitter(ob, psmd,part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,nor,0,0,orco,0); + num= pa->num_dmcache; + + if(num == DMCACHE_NOTFOUND) + if(pa->num < psmd->dm->getNumFaces(psmd->dm)) + num= pa->num; + if(uvco && ELEM(part->from,PART_FROM_FACE,PART_FROM_VOLUME)){ layer=psmd->dm->faceData.layers + CustomData_get_layer_index(&psmd->dm->faceData,CD_MFACE); - num= pa->num_dmcache; - - if(num == DMCACHE_NOTFOUND) - if(pa->num < psmd->dm->getNumFaces(psmd->dm)) - num= pa->num; - for(i=0; idm->getFaceData(psmd->dm,num,CD_MFACE); @@ -1761,6 +1766,8 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem r_tilt=2.0f*cpa->rand[2]; + num= cpa->num; + /* get orco */ psys_particle_on_emitter(ob, psmd, (part->childtype == PART_CHILD_FACES)? PART_FROM_FACE: PART_FROM_PARTICLE, @@ -1831,6 +1838,11 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem VECCOPY(snor, surfnor); } + if(doapproxao && num >= 0) { + int *facenum= RE_strandren_get_face(obr, strand, 1); + *facenum= num; + } + if(uvco){ for(i=0; iocclusionmesh= cache_occ_mesh(re, obr, psmd->dm, mat); + /* 4. clean up */ if(ma) do_mat_ipo(ma); @@ -3636,13 +3651,18 @@ void init_render_world(Render *re) if(re->osa) while(re->wrld.aosamp*re->wrld.aosamp < re->osa) re->wrld.aosamp++; - if(!(re->r.mode & R_RAYTRACE)) + if(!(re->r.mode & R_RAYTRACE) && (re->wrld.ao_gather_method == WO_AOGATHER_RAYTRACE)) re->wrld.mode &= ~WO_AMB_OCC; } else { memset(&re->wrld, 0, sizeof(World)); - re->wrld.exp= 0.0; - re->wrld.range= 1.0; + re->wrld.exp= 0.0f; + re->wrld.range= 1.0f; + + /* for mist pass */ + re->wrld.miststa= re->clipsta; + re->wrld.mistdist= re->clipend-re->clipsta; + re->wrld.misi= 1.0f; } re->wrld.linfac= 1.0 + pow((2.0*re->wrld.exp + 0.5), -10); @@ -3870,6 +3890,29 @@ static int render_object_type(int type) return ELEM5(type, OB_FONT, OB_CURVE, OB_SURF, OB_MESH, OB_MBALL); } +static void find_dupli_instances(Render *re, ObjectRen *obr) +{ + ObjectInstanceRen *obi; + float imat[4][4], obmat[4][4], obimat[4][4], nmat[3][3]; + + Mat4MulMat4(obmat, obr->ob->obmat, re->viewmat); + Mat4Invert(imat, obmat); + + for(obi=re->instancetable.last; obi; obi=obi->prev) { + if(!obi->obr && obi->ob == obr->ob && obi->psysindex == obr->psysindex) { + obi->obr= obr; + + /* compute difference between object matrix and + * object matrix with dupli transform, in viewspace */ + Mat4CpyMat4(obimat, obi->mat); + Mat4MulMat4(obi->mat, imat, obimat); + + Mat3CpyMat4(nmat, obi->mat); + Mat3Inv(obi->imat, nmat); + } + } +} + static void init_render_object_data(Render *re, ObjectRen *obr, int only_verts) { Object *ob= obr->ob; @@ -3937,6 +3980,8 @@ static void add_render_object(Render *re, Object *ob, Object *par, int index, in /* only add instance for objects that have not been used for dupli */ if(!(ob->transflag & OB_RENDER_DUPLI)) RE_addRenderInstance(re, obr, ob, par, index, 0, NULL); + else + find_dupli_instances(re, obr); } /* and one render object per particle system */ @@ -3950,6 +3995,8 @@ static void add_render_object(Render *re, Object *ob, Object *par, int index, in /* only add instance for objects that have not been used for dupli */ if(!(ob->transflag & OB_RENDER_DUPLI)) RE_addRenderInstance(re, obr, ob, par, index, psysindex, NULL); + else + find_dupli_instances(re, obr); } } } @@ -4042,6 +4089,7 @@ void RE_Database_Free(Render *re) if(re->r.mode & R_RAYTRACE) freeraytree(re); free_sss(re); + free_occ(re); re->totvlak=re->totvert=re->totstrand=re->totlamp=re->tothalo= 0; re->i.convertdone= 0; @@ -4070,9 +4118,8 @@ static int allow_render_object(Object *ob, int nolamps, int onlyselected, Object for(psys=ob->particlesystem.first; psys; psys=psys->next){ part=psys->part; - if((part->draw_as==PART_DRAW_OB && part->dup_ob) || (part->draw_as==PART_DRAW_GR && part->dup_group)) - if(part->draw & PART_DRAW_EMITTER) - allow= 1; + if(part->draw & PART_DRAW_EMITTER) + allow= 1; } } @@ -4105,22 +4152,30 @@ static void dupli_render_particle_set(Render *re, Object *ob, int level, int ena Group *group; GroupObject *go; ParticleSystem *psys; + DerivedMesh *dm; if(level >= MAX_DUPLI_RECUR) return; if(ob->transflag & OB_DUPLIPARTS) { - DerivedMesh *dm; + for(psys=ob->particlesystem.first; psys; psys=psys->next) { + if(ELEM(psys->part->draw_as, PART_DRAW_OB, PART_DRAW_GR)) { + if(enable) + psys_render_set(ob, psys, re->viewmat, re->winmat, re->winx, re->winy); + else + psys_render_restore(ob, psys); + } + } - for(psys=ob->particlesystem.first; psys; psys=psys->next) - if(enable) - psys_render_set(ob, psys, re->viewmat, re->winmat, re->winx, re->winy); - else - psys_render_restore(ob, psys); - - if(enable) { - dm = mesh_create_derived_render(ob, CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL); + if(level == 0 && enable) { + /* this is to make sure we get render level duplis in groups: + * the derivedmesh must be created before init_render_mesh, + * since object_duplilist does dupliparticles before that */ + dm = mesh_create_derived_render(ob, CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL); dm->release(dm); + + for(psys=ob->particlesystem.first; psys; psys=psys->next) + psys_get_modifier(ob, psys)->flag &= ~eParticleSystemFlag_psys_updated; } } @@ -4137,7 +4192,7 @@ static void database_init_objects(Render *re, unsigned int lay, int nolamps, int Object *ob; ObjectInstanceRen *obi; Scene *sce; - float mat[4][4], obmat[4][4]; + float mat[4][4]; for(SETLOOPER(re->scene, base)) { ob= base->object; @@ -4151,7 +4206,7 @@ static void database_init_objects(Render *re, unsigned int lay, int nolamps, int for(SETLOOPER(re->scene, base)) { ob= base->object; - + /* if the object has been restricted from rendering in the outliner, ignore it */ if(ob->restrictflag & OB_RESTRICT_RENDER) continue; @@ -4173,16 +4228,15 @@ static void database_init_objects(Render *re, unsigned int lay, int nolamps, int for(dob= lb->first; dob; dob= dob->next) { Object *obd= dob->ob; - Mat4CpyMat4(obmat, obd->obmat); Mat4CpyMat4(obd->obmat, dob->mat); /* group duplis need to set ob matrices correct, for deform. so no_draw is part handled */ - if(dob->no_draw) + if(!(obd->transflag & OB_RENDER_DUPLI) && dob->no_draw) continue; if(obd->restrictflag & OB_RESTRICT_RENDER) continue; - + if(obd->type==OB_MBALL) continue; @@ -4192,13 +4246,9 @@ static void database_init_objects(Render *re, unsigned int lay, int nolamps, int if(allow_render_dupli_instance(re, dob, obd)) { ParticleSystem *psys; int psysindex; - float imat[4][4], mat[4][4]; - - /* compute difference between object matrix and - * object matrix with dupli transform, in viewspace */ - Mat4Invert(imat, obmat); - MTC_Mat4MulSerie(mat, re->viewmat, dob->mat, imat, re->viewinv, 0, 0, 0, 0); + float mat[4][4]; + Mat4MulMat4(mat, dob->mat, re->viewmat); obi= RE_addRenderInstance(re, NULL, obd, ob, dob->index, 0, mat); VECCOPY(obi->dupliorco, dob->orco); obi->dupliuv[0]= dob->uv[0]; @@ -4214,8 +4264,6 @@ static void database_init_objects(Render *re, unsigned int lay, int nolamps, int obd->flag |= OB_DONE; obd->transflag |= OB_RENDER_DUPLI; - - Mat4CpyMat4(obd->obmat, obmat); } else init_render_object(re, obd, ob, dob->index, only_verts); @@ -4277,7 +4325,7 @@ void RE_Database_FromScene(Render *re, Scene *scene, int use_camera_view) } init_render_world(re); /* do first, because of ambient. also requires re->osa set correct */ - if(re->wrld.mode & WO_AMB_OCC) { + if((re->r.mode & R_RAYTRACE) && (re->wrld.mode & WO_AMB_OCC)) { if (re->wrld.ao_samp_method == WO_AOSAMP_HAMMERSLEY) init_render_hammersley(re); else if (re->wrld.ao_samp_method == WO_AOSAMP_CONSTANT) @@ -4342,10 +4390,16 @@ void RE_Database_FromScene(Render *re, Scene *scene, int use_camera_view) if(!re->test_break()) project_renderdata(re, projectverto, re->r.mode & R_PANORAMA, 0, 1); + + /* Occlusion */ + if((re->wrld.mode & WO_AMB_OCC) && !re->test_break()) + if(re->wrld.ao_gather_method == WO_AOGATHER_APPROX) + if(re->r.renderer==R_INTERN) + make_occ_tree(re); /* SSS */ if((re->r.mode & R_SSS) && !re->test_break()) - if (re->r.renderer==R_INTERN) + if(re->r.renderer==R_INTERN) make_sss_tree(re); } @@ -4825,7 +4879,7 @@ void RE_Database_Baking(Render *re, Scene *scene, int type, Object *actob) } init_render_world(re); /* do first, because of ambient. also requires re->osa set correct */ - if(re->wrld.mode & WO_AMB_OCC) { + if((re->r.mode & R_RAYTRACE) && (re->wrld.mode & WO_AMB_OCC)) { if (re->wrld.ao_samp_method == WO_AOSAMP_HAMMERSLEY) init_render_hammersley(re); else if (re->wrld.ao_samp_method == WO_AOSAMP_CONSTANT) diff --git a/source/blender/render/intern/source/occlusion.c b/source/blender/render/intern/source/occlusion.c new file mode 100644 index 00000000000..bcd6ed3aa0d --- /dev/null +++ b/source/blender/render/intern/source/occlusion.c @@ -0,0 +1,1694 @@ +/* + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2008 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Brecht Van Lommel. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include +#include +#include +#include + +#include "MEM_guardedalloc.h" + +#include "DNA_material_types.h" +#include "DNA_meshdata_types.h" + +#include "BLI_arithb.h" +#include "BLI_blenlib.h" +#include "BLI_memarena.h" +#include "BLI_threads.h" + +#include "BKE_DerivedMesh.h" +#include "BKE_global.h" +#include "BKE_utildefines.h" + +#include "RE_shader_ext.h" + +/* local includes */ +#include "occlusion.h" +#include "render_types.h" +#include "rendercore.h" +#include "renderdatabase.h" +#include "pixelshading.h" +#include "shading.h" +#include "zbuf.h" + +/* ------------------------- Declarations --------------------------- */ + +#define INVALID_INDEX ((int)(~0)) +#define INVPI 0.31830988618379069f +#define TOTCHILD 8 +#define CACHE_STEP 3 + +typedef struct OcclusionCacheSample { + float co[3], n[3], col[3], intensity, dist2; + int x, y, filled; +} OcclusionCacheSample; + +typedef struct OcclusionCache { + OcclusionCacheSample *sample; + int x, y, w, h, step; +} OcclusionCache; + +typedef struct OcclusionCacheMesh { + struct OcclusionCacheMesh *next, *prev; + ObjectRen *obr; + int (*face)[4]; + float (*co)[3]; + float (*col)[3]; + int totvert, totface; +} OcclusionCacheMesh; + +typedef struct OccFace { + int obi; + int facenr; +} OccFace; + +typedef struct OccNode { + float co[3], area; + float sh[9], dco; + float occlusion; + int childflag; + union { + //OccFace face; + int face; + struct OccNode *node; + } child[TOTCHILD]; +} OccNode; + +typedef struct OcclusionTree { + MemArena *arena; + + float (*co)[3]; /* temporary during build */ + + OccFace *face; /* instance and face indices */ + float *occlusion; /* occlusion for faces */ + + OccNode *root; + + OccNode **stack[BLENDER_MAX_THREADS]; + int maxdepth; + + int totface; + + float error; + float distfac; + + OcclusionCache *cache; +} OcclusionTree; + +/* ------------------------- Shading --------------------------- */ + +extern Render R; // meh + +#if 0 +static void occ_shade(ShadeSample *ssamp, ObjectInstanceRen *obi, VlakRen *vlr, float *rad) +{ + ShadeInput *shi= ssamp->shi; + ShadeResult *shr= ssamp->shr; + float l, u, v, *v1, *v2, *v3; + + /* init */ + if(vlr->v4) { + shi->u= u= 0.5f; + shi->v= v= 0.5f; + } + else { + shi->u= u= 1.0f/3.0f; + shi->v= v= 1.0f/3.0f; + } + + /* setup render coordinates */ + v1= vlr->v1->co; + v2= vlr->v2->co; + v3= vlr->v3->co; + + /* renderco */ + l= 1.0f-u-v; + + shi->co[0]= l*v3[0]+u*v1[0]+v*v2[0]; + shi->co[1]= l*v3[1]+u*v1[1]+v*v2[1]; + shi->co[2]= l*v3[2]+u*v1[2]+v*v2[2]; + + shade_input_set_triangle_i(shi, obi, vlr, 0, 1, 2); + + /* set up view vector */ + VECCOPY(shi->view, shi->co); + Normalize(shi->view); + + /* cache for shadow */ + shi->samplenr++; + + shi->xs= 0; // TODO + shi->ys= 0; + + shade_input_set_normals(shi); + + /* no normal flip */ + if(shi->flippednor) + shade_input_flip_normals(shi); + + /* not a pretty solution, but fixes common cases */ + if(shi->obr->ob && shi->obr->ob->transflag & OB_NEG_SCALE) { + VecMulf(shi->vn, -1.0f); + VecMulf(shi->vno, -1.0f); + } + + /* init material vars */ + // note, keep this synced with render_types.h + memcpy(&shi->r, &shi->mat->r, 23*sizeof(float)); + shi->har= shi->mat->har; + + /* render */ + shade_input_set_shade_texco(shi); + shade_material_loop(shi, shr); /* todo: nodes */ + + VECCOPY(rad, shr->combined); +} + +static void occ_build_shade(Render *re, OcclusionTree *tree) +{ + ShadeSample ssamp; + ObjectInstanceRen *obi; + VlakRen *vlr; + int a; + + R= *re; + + /* setup shade sample with correct passes */ + memset(&ssamp, 0, sizeof(ShadeSample)); + ssamp.shi[0].lay= re->scene->lay; + ssamp.shi[0].passflag= SCE_PASS_DIFFUSE|SCE_PASS_RGBA; + ssamp.shi[0].combinedflag= ~(SCE_PASS_SPEC); + ssamp.tot= 1; + + for(a=0; atotface; a++) { + obi= &R.objectinstance[tree->face[a].obi]; + vlr= RE_findOrAddVlak(obi->obr, tree->face[a].vlr); + + occ_shade(&ssamp, obi, vlr, tree->rad[a]); + } +} +#endif + +/* ------------------------- Spherical Harmonics --------------------------- */ + +/* Use 2nd order SH => 9 coefficients, stored in this order: + 0 = (0,0), + 1 = (1,-1), 2 = (1,0), 3 = (1,1), + 4 = (2,-2), 5 = (2,-1), 6 = (2,0), 7 = (2,1), 8 = (2,2) */ + +static void sh_copy(float *shresult, float *sh) +{ + memcpy(shresult, sh, sizeof(float)*9); +} + +static void sh_mul(float *sh, float f) +{ + int i; + + for(i=0; i<9; i++) + sh[i] *= f; +} + +static void sh_add(float *shresult, float *sh1, float *sh2) +{ + int i; + + for(i=0; i<9; i++) + shresult[i]= sh1[i] + sh2[i]; +} + +static void sh_from_disc(float *n, float area, float *shresult) +{ + /* See formula (3) in: + "An Efficient Representation for Irradiance Environment Maps" */ + float sh[9], x, y, z; + + x= n[0]; + y= n[1]; + z= n[2]; + + sh[0]= 0.282095f; + + sh[1]= 0.488603f*y; + sh[2]= 0.488603f*z; + sh[3]= 0.488603f*x; + + sh[4]= 1.092548f*x*y; + sh[5]= 1.092548f*y*z; + sh[6]= 0.315392f*(3.0f*z*z - 1.0f); + sh[7]= 1.092548f*x*z; + sh[8]= 0.546274f*(x*x - y*y); + + sh_mul(sh, area); + sh_copy(shresult, sh); +} + +static float sh_eval(float *sh, float *v) +{ + /* See formula (13) in: + "An Efficient Representation for Irradiance Environment Maps" */ + static const float c1 = 0.429043f, c2 = 0.511664f, c3 = 0.743125f; + static const float c4 = 0.886227f, c5 = 0.247708f; + float x, y, z, sum; + + x= v[0]; + y= v[1]; + z= v[2]; + + sum= c1*sh[8]*(x*x - y*y); + sum += c3*sh[6]*z*z; + sum += c4*sh[0]; + sum += -c5*sh[6]; + sum += 2.0f*c1*(sh[4]*x*y + sh[7]*x*z + sh[5]*y*z); + sum += 2.0f*c2*(sh[3]*x + sh[1]*y + sh[2]*z); + + return sum; +} + +/* ------------------------------ Building --------------------------------- */ + +static void occ_face(const OccFace *face, float *co, float *normal, float *area) +{ + ObjectInstanceRen *obi; + VlakRen *vlr; + + obi= &R.objectinstance[face->obi]; + vlr= RE_findOrAddVlak(obi->obr, face->facenr); + + if(co) { + if(vlr->v4) + VecLerpf(co, vlr->v1->co, vlr->v3->co, 0.5f); + else + CalcCent3f(co, vlr->v1->co, vlr->v2->co, vlr->v3->co); + + if(obi->flag & R_TRANSFORMED) + Mat4MulVecfl(obi->mat, co); + } + + if(normal) { + normal[0]= -vlr->n[0]; + normal[1]= -vlr->n[1]; + normal[2]= -vlr->n[2]; + + if(obi->flag & R_TRANSFORMED) { + float xn, yn, zn, (*imat)[3]= obi->imat; + + xn= normal[0]; + yn= normal[1]; + zn= normal[2]; + + normal[0]= imat[0][0]*xn + imat[0][1]*yn + imat[0][2]*zn; + normal[1]= imat[1][0]*xn + imat[1][1]*yn + imat[1][2]*zn; + normal[2]= imat[2][0]*xn + imat[2][1]*yn + imat[2][2]*zn; + } + } + + if(area) { + /* todo: correct area for instances */ + if(vlr->v4) + *area= AreaQ3Dfl(vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->v4->co); + else + *area= AreaT3Dfl(vlr->v1->co, vlr->v2->co, vlr->v3->co); + } +} + +static void occ_sum_occlusion(OcclusionTree *tree, OccNode *node) +{ + OccNode *child; + float occ, area, totarea; + int a, b; + + occ= 0.0f; + totarea= 0.0f; + + for(b=0; bchildflag & (1<child[b].face; + occ_face(&tree->face[a], 0, 0, &area); + occ += area*tree->occlusion[a]; + totarea += area; + } + else if(node->child[b].node) { + child= node->child[b].node; + occ_sum_occlusion(tree, child); + + occ += child->area*child->occlusion; + totarea += child->area; + } + } + + if(totarea != 0.0f) + occ /= totarea; + + node->occlusion= occ; +} + +static int occ_find_bbox_axis(OcclusionTree *tree, int begin, int end, float *min, float *max) +{ + float len, maxlen= -1.0f; + int a, axis = 0; + + INIT_MINMAX(min, max); + + for(a=begin; aco[a], min, max) + + for(a=0; a<3; a++) { + len= max[a] - min[a]; + + if(len > maxlen) { + maxlen= len; + axis= a; + } + } + + return axis; +} + +void occ_node_from_face(OccFace *face, OccNode *node) +{ + float n[3]; + + occ_face(face, node->co, n, &node->area); + node->dco= 0.0f; + sh_from_disc(n, node->area, node->sh); +} + +static void occ_build_dco(OcclusionTree *tree, OccNode *node, float *co, float *dco) +{ + OccNode *child; + float dist, d[3], nco[3]; + int b; + + for(b=0; bchildflag & (1<face+node->child[b].face, nco, 0, 0); + } + else if(node->child[b].node) { + child= node->child[b].node; + occ_build_dco(tree, child, co, dco); + VECCOPY(nco, child->co); + } + + VECSUB(d, nco, co); + dist= INPR(d, d); + if(dist > *dco) + *dco= dist; + } +} + +static void occ_build_split(OcclusionTree *tree, int begin, int end, int *split) +{ + float min[3], max[3], mid; + int axis, a, enda; + + /* split in middle of boundbox. this seems faster than median split + * on complex scenes, possibly since it avoids two distant faces to + * be in the same node better? */ + axis= occ_find_bbox_axis(tree, begin, end, min, max); + mid= 0.5f*(min[axis]+max[axis]); + + a= begin; + enda= end; + while(aco[a][axis] > mid) { + enda--; + SWAP(OccFace, tree->face[a], tree->face[enda]); + SWAP(float, tree->co[a][0], tree->co[enda][0]); + SWAP(float, tree->co[a][1], tree->co[enda][1]); + SWAP(float, tree->co[a][2], tree->co[enda][2]); + } + else + a++; + } + + *split= enda; +} + +static void occ_build_8_split(OcclusionTree *tree, int begin, int end, int *offset, int *count) +{ + /* split faces into eight groups */ + int b, splitx, splity[2], splitz[4]; + + occ_build_split(tree, begin, end, &splitx); + + occ_build_split(tree, begin, splitx, &splity[0]); + occ_build_split(tree, splitx, end, &splity[1]); + + occ_build_split(tree, begin, splity[0], &splitz[0]); + occ_build_split(tree, splity[0], splitx, &splitz[1]); + occ_build_split(tree, splitx, splity[1], &splitz[2]); + occ_build_split(tree, splity[1], end, &splitz[3]); + + offset[0]= begin; + offset[1]= splitz[0]; + offset[2]= splity[0]; + offset[3]= splitz[1]; + offset[4]= splitx; + offset[5]= splitz[2]; + offset[6]= splity[1]; + offset[7]= splitz[3]; + + for(b=0; b<7; b++) + count[b]= offset[b+1] - offset[b]; + count[7]= end - offset[7]; +} + +static OccNode *occ_build_recursive(OcclusionTree *tree, int begin, int end, int depth) +{ + OccNode *node, *child, tmpnode; + OccFace *face; + int a, b, offset[TOTCHILD], count[TOTCHILD]; + + /* keep track of maximum depth for stack */ + if(depth > tree->maxdepth) + tree->maxdepth= depth; + + /* add a new node */ + node= BLI_memarena_alloc(tree->arena, sizeof(OccNode)); + node->occlusion= 1.0f; + + /* leaf node with only children */ + if(end - begin <= TOTCHILD) { + for(a=begin, b=0; aface[a]; + node->child[b].face= a; + node->childflag |= (1<child[b].node= NULL; + } + else if(count[b] == 1) { + face= &tree->face[offset[b]]; + node->child[b].face= offset[b]; + node->childflag |= (1<child[b].node= child; + } + } + } + + /* combine area, position and sh */ + for(b=0; bchildflag & (1<face+node->child[b].face, &tmpnode); + } + else { + child= node->child[b].node; + } + + if(child) { + node->area += child->area; + sh_add(node->sh, node->sh, child->sh); + VECADDFAC(node->co, node->co, child->co, child->area); + } + } + + if(node->area != 0.0f) + VecMulf(node->co, 1.0f/node->area); + + /* compute maximum distance from center */ + node->dco= 0.0f; + occ_build_dco(tree, node, node->co, &node->dco); + + return node; +} + +static void occ_build_sh_normalize(OccNode *node) +{ + /* normalize spherical harmonics to not include area, so + * we can clamp the dot product and then mutliply by area */ + int b; + + if(node->area != 0.0f) + sh_mul(node->sh, 1.0f/node->area); + + for(b=0; bchildflag & (1<child[b].node) + occ_build_sh_normalize(node->child[b].node); + } +} + +static OcclusionTree *occ_tree_build(Render *re) +{ + OcclusionTree *tree; + ObjectInstanceRen *obi; + ObjectRen *obr; + VlakRen *vlr= NULL; + int a, b, c, totface; + + /* count */ + totface= 0; + for(obi=re->instancetable.first; obi; obi=obi->next) { + if(obi->flag & R_TRANSFORMED) + continue; + + obr= obi->obr; + for(a=0; atotvlak; a++) { + if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; + else vlr++; + + if(vlr->mat->mode & MA_TRACEBLE) + totface++; + } + } + + if(totface == 0) + return NULL; + + tree= MEM_callocN(sizeof(OcclusionTree), "OcclusionTree"); + tree->totface= totface; + + /* parameters */ + tree->error= re->wrld.ao_approx_error; + tree->distfac= (re->wrld.aomode & WO_AODIST)? re->wrld.aodistfac: 0.0f; + + /* allocation */ + tree->arena= BLI_memarena_new(0x8000 * sizeof(OccNode)); + BLI_memarena_use_calloc(tree->arena); + + if(re->wrld.aomode & WO_AOCACHE) + tree->cache= MEM_callocN(sizeof(OcclusionCache)*BLENDER_MAX_THREADS, "OcclusionCache"); + + tree->face= MEM_callocN(sizeof(OccFace)*totface, "OcclusionFace"); + tree->co= MEM_callocN(sizeof(float)*3*totface, "OcclusionCo"); + tree->occlusion= MEM_callocN(sizeof(float)*totface, "OcclusionOcclusion"); + + /* make array of face pointers */ + for(b=0, c=0, obi=re->instancetable.first; obi; obi=obi->next, c++) { + if(obi->flag & R_TRANSFORMED) + continue; /* temporary to avoid slow renders with loads of duplis */ + + obr= obi->obr; + for(a=0; atotvlak; a++) { + if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; + else vlr++; + + if(vlr->mat->mode & MA_TRACEBLE) { + tree->face[b].obi= c; + tree->face[b].facenr= a; + tree->occlusion[b]= 1.0f; + occ_face(&tree->face[b], tree->co[b], NULL, NULL); + b++; + } + } + } + + /* recurse */ + tree->root= occ_build_recursive(tree, 0, totface, 1); + +#if 0 + if(tree->doindirect) { + occ_build_shade(re, tree); + occ_sum_occlusion(tree, tree->root); + } +#endif + + MEM_freeN(tree->co); + tree->co= NULL; + + occ_build_sh_normalize(tree->root); + + for(a=0; astack[a]= MEM_callocN(sizeof(OccNode)*TOTCHILD*(tree->maxdepth+1), "OccStack"); + + return tree; +} + +static void occ_free_tree(OcclusionTree *tree) +{ + int a; + + if(tree) { + if(tree->arena) BLI_memarena_free(tree->arena); + for(a=0; astack[a]) + MEM_freeN(tree->stack[a]); + if(tree->occlusion) MEM_freeN(tree->occlusion); + if(tree->face) MEM_freeN(tree->face); + if(tree->cache) MEM_freeN(tree->cache); + MEM_freeN(tree); + } +} + +/* ------------------------- Traversal --------------------------- */ + +static float occ_solid_angle(OccNode *node, float *v, float d2, float *receivenormal) +{ + float dotreceive, dotemit, invd2 = 1.0f/sqrtf(d2); + float ev[3]; + + ev[0]= -v[0]*invd2; + ev[1]= -v[1]*invd2; + ev[2]= -v[2]*invd2; + dotemit= sh_eval(node->sh, ev); + dotreceive= INPR(receivenormal, v)*invd2; + + CLAMP(dotemit, 0.0f, 1.0f); + CLAMP(dotreceive, 0.0f, 1.0f); + + return ((node->area*dotemit*dotreceive)/(d2 + node->area*INVPI))*INVPI; +} + +static void VecAddDir(float *result, float *v1, float *v2, float fac) +{ + result[0]= v1[0] + fac*(v2[0] - v1[0]); + result[1]= v1[1] + fac*(v2[1] - v1[1]); + result[2]= v1[2] + fac*(v2[2] - v1[2]); +} + +static int occ_visible_quad(float *p, float *n, float *v0, float *v1, float *v2, float *q0, float *q1, float *q2, float *q3) +{ + static const float epsilon = 1e-6f; + float c, sd[3]; + + c= INPR(n, p); + + /* signed distances from the vertices to the plane. */ + sd[0]= INPR(n, v0) - c; + sd[1]= INPR(n, v1) - c; + sd[2]= INPR(n, v2) - c; + + if(fabs(sd[0]) < epsilon) sd[0] = 0.0f; + if(fabs(sd[1]) < epsilon) sd[1] = 0.0f; + if(fabs(sd[2]) < epsilon) sd[2] = 0.0f; + + if(sd[0] > 0) { + if(sd[1] > 0) { + if(sd[2] > 0) { + // +++ + VECCOPY(q0, v0); + VECCOPY(q1, v1); + VECCOPY(q2, v2); + VECCOPY(q3, q2); + } + else if(sd[2] < 0) { + // ++- + VECCOPY(q0, v0); + VECCOPY(q1, v1); + VecAddDir(q2, v1, v2, (sd[1]/(sd[1]-sd[2]))); + VecAddDir(q3, v0, v2, (sd[0]/(sd[0]-sd[2]))); + } + else { + // ++0 + VECCOPY(q0, v0); + VECCOPY(q1, v1); + VECCOPY(q2, v2); + VECCOPY(q3, q2); + } + } + else if(sd[1] < 0) { + if(sd[2] > 0) { + // +-+ + VECCOPY(q0, v0); + VecAddDir(q1, v0, v1, (sd[0]/(sd[0]-sd[1]))); + VecAddDir(q2, v1, v2, (sd[1]/(sd[1]-sd[2]))); + VECCOPY(q3, v2); + } + else if(sd[2] < 0) { + // +-- + VECCOPY(q0, v0); + VecAddDir(q1, v0, v1, (sd[0]/(sd[0]-sd[1]))); + VecAddDir(q2, v0, v2, (sd[0]/(sd[0]-sd[2]))); + VECCOPY(q3, q2); + } + else { + // +-0 + VECCOPY(q0, v0); + VecAddDir(q1, v0, v1, (sd[0]/(sd[0]-sd[1]))); + VECCOPY(q2, v2); + VECCOPY(q3, q2); + } + } + else { + if(sd[2] > 0) { + // +0+ + VECCOPY(q0, v0); + VECCOPY(q1, v1); + VECCOPY(q2, v2); + VECCOPY(q3, q2); + } + else if(sd[2] < 0) { + // +0- + VECCOPY(q0, v0); + VECCOPY(q1, v1); + VecAddDir(q2, v0, v2, (sd[0]/(sd[0]-sd[2]))); + VECCOPY(q3, q2); + } + else { + // +00 + VECCOPY(q0, v0); + VECCOPY(q1, v1); + VECCOPY(q2, v2); + VECCOPY(q3, q2); + } + } + } + else if(sd[0] < 0) { + if(sd[1] > 0) { + if(sd[2] > 0) { + // -++ + VecAddDir(q0, v0, v1, (sd[0]/(sd[0]-sd[1]))); + VECCOPY(q1, v1); + VECCOPY(q2, v2); + VecAddDir(q3, v0, v2, (sd[0]/(sd[0]-sd[2]))); + } + else if(sd[2] < 0) { + // -+- + VecAddDir(q0, v0, v1, (sd[0]/(sd[0]-sd[1]))); + VECCOPY(q1, v1); + VecAddDir(q2, v1, v2, (sd[1]/(sd[1]-sd[2]))); + VECCOPY(q3, q2); + } + else { + // -+0 + VecAddDir(q0, v0, v1, (sd[0]/(sd[0]-sd[1]))); + VECCOPY(q1, v1); + VECCOPY(q2, v2); + VECCOPY(q3, q2); + } + } + else if(sd[1] < 0) { + if(sd[2] > 0) { + // --+ + VecAddDir(q0, v0, v2, (sd[0]/(sd[0]-sd[2]))); + VecAddDir(q1, v1, v2, (sd[1]/(sd[1]-sd[2]))); + VECCOPY(q2, v2); + VECCOPY(q3, q2); + } + else if(sd[2] < 0) { + // --- + return 0; + } + else { + // --0 + return 0; + } + } + else { + if(sd[2] > 0) { + // -0+ + VecAddDir(q0, v0, v2, (sd[0]/(sd[0]-sd[2]))); + VECCOPY(q1, v1); + VECCOPY(q2, v2); + VECCOPY(q3, q2); + } + else if(sd[2] < 0) { + // -0- + return 0; + } + else { + // -00 + return 0; + } + } + } + else { + if(sd[1] > 0) { + if(sd[2] > 0) { + // 0++ + VECCOPY(q0, v0); + VECCOPY(q1, v1); + VECCOPY(q2, v2); + VECCOPY(q3, q2); + } + else if(sd[2] < 0) { + // 0+- + VECCOPY(q0, v0); + VECCOPY(q1, v1); + VecAddDir(q2, v1, v2, (sd[1]/(sd[1]-sd[2]))); + VECCOPY(q3, q2); + } + else { + // 0+0 + VECCOPY(q0, v0); + VECCOPY(q1, v1); + VECCOPY(q2, v2); + VECCOPY(q3, q2); + } + } + else if(sd[1] < 0) { + if(sd[2] > 0) { + // 0-+ + VECCOPY(q0, v0); + VecAddDir(q1, v1, v2, (sd[1]/(sd[1]-sd[2]))); + VECCOPY(q2, v2); + VECCOPY(q3, q2); + } + else if(sd[2] < 0) { + // 0-- + return 0; + } + else { + // 0-0 + return 0; + } + } + else { + if(sd[2] > 0) { + // 00+ + VECCOPY(q0, v0); + VECCOPY(q1, v1); + VECCOPY(q2, v2); + VECCOPY(q3, q2); + } + else if(sd[2] < 0) { + // 00- + return 0; + } + else { + // 000 + return 0; + } + } + } + + return 1; +} + +/* altivec optimization, this works, but is unused */ + +#if 0 +#include + +typedef union { + vFloat v; + float f[4]; +} vFloatResult; + +static vFloat vec_splat_float(float val) +{ + return (vFloat){val, val, val, val}; +} + +static float occ_quad_form_factor(float *p, float *n, float *q0, float *q1, float *q2, float *q3) +{ + vFloat vcos, rlen, vrx, vry, vrz, vsrx, vsry, vsrz, gx, gy, gz, vangle; + vUInt8 rotate = (vUInt8){4,5,6,7,8,9,10,11,12,13,14,15,0,1,2,3}; + vFloatResult vresult; + float result; + + /* compute r* */ + vrx = (vFloat){q0[0], q1[0], q2[0], q3[0]} - vec_splat_float(p[0]); + vry = (vFloat){q0[1], q1[1], q2[1], q3[1]} - vec_splat_float(p[1]); + vrz = (vFloat){q0[2], q1[2], q2[2], q3[2]} - vec_splat_float(p[2]); + + /* normalize r* */ + rlen = vec_rsqrte(vrx*vrx + vry*vry + vrz*vrz + vec_splat_float(1e-16f)); + vrx = vrx*rlen; + vry = vry*rlen; + vrz = vrz*rlen; + + /* rotate r* for cross and dot */ + vsrx= vec_perm(vrx, vrx, rotate); + vsry= vec_perm(vry, vry, rotate); + vsrz= vec_perm(vrz, vrz, rotate); + + /* cross product */ + gx = vsry*vrz - vsrz*vry; + gy = vsrz*vrx - vsrx*vrz; + gz = vsrx*vry - vsry*vrx; + + /* normalize */ + rlen = vec_rsqrte(gx*gx + gy*gy + gz*gz + vec_splat_float(1e-16f)); + gx = gx*rlen; + gy = gy*rlen; + gz = gz*rlen; + + /* angle */ + vcos = vrx*vsrx + vry*vsry + vrz*vsrz; + vcos= vec_max(vec_min(vcos, vec_splat_float(1.0f)), vec_splat_float(-1.0f)); + vangle= vacosf(vcos); + + /* dot */ + vresult.v = (vec_splat_float(n[0])*gx + + vec_splat_float(n[1])*gy + + vec_splat_float(n[2])*gz)*vangle; + + result= (vresult.f[0] + vresult.f[1] + vresult.f[2] + vresult.f[3])*(0.5f/(float)M_PI); + result= MAX2(result, 0.0f); + + return result; +} + +#endif + +/* SSE optimization, acos code doesn't work */ + +#if 0 + +#include + +static __m128 sse_approx_acos(__m128 x) +{ + /* needs a better approximation than taylor expansion of acos, since that + * gives big erros for near 1.0 values, sqrt(2*x)*acos(1-x) should work + * better, see http://www.tom.womack.net/projects/sse-fast-arctrig.html */ + + return _mm_set_ps1(1.0f); +} + +static float occ_quad_form_factor(float *p, float *n, float *q0, float *q1, float *q2, float *q3) +{ + float r0[3], r1[3], r2[3], r3[3], g0[3], g1[3], g2[3], g3[3]; + float a1, a2, a3, a4, dot1, dot2, dot3, dot4, result; + float fresult[4] __attribute__((aligned(16))); + __m128 qx, qy, qz, rx, ry, rz, rlen, srx, sry, srz, gx, gy, gz, glen, rcos, angle, aresult; + + /* compute r */ + qx = _mm_set_ps(q3[0], q2[0], q1[0], q0[0]); + qy = _mm_set_ps(q3[1], q2[1], q1[1], q0[1]); + qz = _mm_set_ps(q3[2], q2[2], q1[2], q0[2]); + + rx = qx - _mm_set_ps1(p[0]); + ry = qy - _mm_set_ps1(p[1]); + rz = qz - _mm_set_ps1(p[2]); + + /* normalize r */ + rlen = _mm_rsqrt_ps(rx*rx + ry*ry + rz*rz + _mm_set_ps1(1e-16f)); + rx = rx*rlen; + ry = ry*rlen; + rz = rz*rlen; + + /* cross product */ + srx = _mm_shuffle_ps(rx, rx, _MM_SHUFFLE(0,3,2,1)); + sry = _mm_shuffle_ps(ry, ry, _MM_SHUFFLE(0,3,2,1)); + srz = _mm_shuffle_ps(rz, rz, _MM_SHUFFLE(0,3,2,1)); + + gx = sry*rz - srz*ry; + gy = srz*rx - srx*rz; + gz = srx*ry - sry*rx; + + /* normalize g */ + glen = _mm_rsqrt_ps(gx*gx + gy*gy + gz*gz + _mm_set_ps1(1e-16f)); + gx = gx*glen; + gy = gy*glen; + gz = gz*glen; + + /* compute angle */ + rcos = rx*srx + ry*sry + rz*srz; + rcos= _mm_max_ps(_mm_min_ps(rcos, _mm_set_ps1(1.0f)), _mm_set_ps1(-1.0f)); + + angle = sse_approx_cos(rcos); + aresult = (_mm_set_ps1(n[0])*gx + _mm_set_ps1(n[1])*gy + _mm_set_ps1(n[2])*gz)*angle; + + /* sum together */ + result= (fresult[0] + fresult[1] + fresult[2] + fresult[3])*(0.5f/(float)M_PI); + result= MAX2(result, 0.0f); + + return result; +} + +#endif + +static float saacosf(float fac) +{ + if(fac<= -1.0f) return (float)M_PI; + else if(fac>=1.0f) return 0.0f; + else return acos(fac); /* acosf(fac) */ +} + +static void normalizef(float *n) +{ + float d; + + d= INPR(n, n); + + if(d > 1.0e-35F) { + d= 1.0f/sqrt(d); /* sqrtf(d) */ + + n[0] *= d; + n[1] *= d; + n[2] *= d; + } +} + +static float occ_quad_form_factor(float *p, float *n, float *q0, float *q1, float *q2, float *q3) +{ + float r0[3], r1[3], r2[3], r3[3], g0[3], g1[3], g2[3], g3[3]; + float a1, a2, a3, a4, dot1, dot2, dot3, dot4, result; + + VECSUB(r0, q0, p); + VECSUB(r1, q1, p); + VECSUB(r2, q2, p); + VECSUB(r3, q3, p); + + normalizef(r0); + normalizef(r1); + normalizef(r2); + normalizef(r3); + + Crossf(g0, r1, r0); normalizef(g0); + Crossf(g1, r2, r1); normalizef(g1); + Crossf(g2, r3, r2); normalizef(g2); + Crossf(g3, r0, r3); normalizef(g3); + + a1= saacosf(INPR(r0, r1)); + a2= saacosf(INPR(r1, r2)); + a3= saacosf(INPR(r2, r3)); + a4= saacosf(INPR(r3, r0)); + + dot1= INPR(n, g0); + dot2= INPR(n, g1); + dot3= INPR(n, g2); + dot4= INPR(n, g3); + + result= (a1*dot1 + a2*dot2 + a3*dot3 + a4*dot4)*0.5f/(float)M_PI; + result= MAX2(result, 0.0f); + + return result; +} + +float occ_form_factor(OccFace *face, float *p, float *n) +{ + ObjectInstanceRen *obi; + VlakRen *vlr; + float v1[3], v2[3], v3[3], v4[3], q0[3], q1[3], q2[3], q3[3], contrib= 0.0f; + + obi= &R.objectinstance[face->obi]; + vlr= RE_findOrAddVlak(obi->obr, face->facenr); + + VECCOPY(v1, vlr->v1->co); + VECCOPY(v2, vlr->v2->co); + VECCOPY(v3, vlr->v3->co); + + if(obi->flag & R_TRANSFORMED) { + Mat4MulVecfl(obi->mat, v1); + Mat4MulVecfl(obi->mat, v2); + Mat4MulVecfl(obi->mat, v3); + } + + if(occ_visible_quad(p, n, v1, v2, v3, q0, q1, q2, q3)) + contrib += occ_quad_form_factor(p, n, q0, q1, q2, q3); + + if(vlr->v4) { + VECCOPY(v4, vlr->v4->co); + if(obi->flag & R_TRANSFORMED) + Mat4MulVecfl(obi->mat, v4); + + if(occ_visible_quad(p, n, v1, v3, v4, q0, q1, q2, q3)) + contrib += occ_quad_form_factor(p, n, q0, q1, q2, q3); + } + + return contrib; +} + +static void occ_lookup(OcclusionTree *tree, int thread, OccFace *exclude, float *pp, float *pn, float *occ, float *bentn) +{ + OccNode *node, **stack; + OccFace *face; + float resultocc, v[3], p[3], n[3], co[3]; + float distfac, error, d2, weight, emitarea; + int b, totstack; + + /* init variables */ + VECCOPY(p, pp); + VECCOPY(n, pn); + VECADDFAC(p, p, n, 1e-4f); + + if(bentn) + VECCOPY(bentn, n); + + error= tree->error; + distfac= tree->distfac; + + resultocc= 0.0f; + + /* init stack */ + stack= tree->stack[thread]; + stack[0]= tree->root; + totstack= 1; + + while(totstack) { + /* pop point off the stack */ + node= stack[--totstack]; + + VECSUB(v, node->co, p); + d2= INPR(v, v) + 1e-16f; + emitarea= MAX2(node->area, node->dco); + + if(d2*error > emitarea) { + /* accumulate occlusion from spherical harmonics */ + weight= occ_solid_angle(node, v, d2, n); + weight *= node->occlusion; + + if(bentn) { + Normalize(v); + bentn[0] -= weight*v[0]; + bentn[1] -= weight*v[1]; + bentn[2] -= weight*v[2]; + } + + if(distfac != 0.0f) + weight /= (1.0 + distfac*d2); + + resultocc += weight; + } + else { + /* traverse into children */ + for(b=0; bchildflag & (1<face+node->child[b].face; + + /* accumulate occlusion with face form factor */ + if(!exclude || !(face->obi == exclude->obi && face->facenr == exclude->facenr)) { + weight= occ_form_factor(face, p, n); + weight *= tree->occlusion[node->child[b].face]; + + if(bentn || distfac != 0.0f) { + occ_face(face, co, NULL, NULL); + VECSUB(v, co, p); + + if(bentn) { + Normalize(v); + bentn[0] -= weight*v[0]; + bentn[1] -= weight*v[1]; + bentn[2] -= weight*v[2]; + } + + if(distfac != 0.0f) { + d2= INPR(v, v) + 1e-16f; + weight /= (1.0 + distfac*d2); + } + } + + resultocc += weight; + + } + } + else if(node->child[b].node) { + /* push child on the stack */ + stack[totstack++]= node->child[b].node; + } + } + } + } + + if(occ) *occ= resultocc; +} + +static void occ_compute_passes(Render *re, OcclusionTree *tree, int totpass) +{ + float *occ, co[3], n[3]; + int pass, i; + + occ= MEM_callocN(sizeof(float)*tree->totface, "OcclusionPassOcc"); + + for(pass=0; passtotface; i++) { + occ_face(&tree->face[i], co, n, NULL); + VecMulf(n, -1.0f); + VECADDFAC(co, co, n, 1e-8f); + + occ_lookup(tree, 0, &tree->face[i], co, n, &occ[i], NULL); + if(re->test_break()) + break; + } + + if(re->test_break()) + break; + + for(i=0; itotface; i++) { + tree->occlusion[i] -= occ[i]; //MAX2(1.0f-occ[i], 0.0f); + if(tree->occlusion[i] < 0.0f) + tree->occlusion[i]= 0.0f; + } + + occ_sum_occlusion(tree, tree->root); + } + + MEM_freeN(occ); +} + +static void sample_occ_tree(Render *re, OcclusionTree *tree, OccFace *exclude, float *co, float *n, int thread, int onlyshadow, float *skycol) +{ + float nn[3], bn[3], dxyview[3], fac, occ, occlusion, correction; + int aocolor; + + aocolor= re->wrld.aocolor; + if(onlyshadow) + aocolor= WO_AOPLAIN; + + VECCOPY(nn, n); + VecMulf(nn, -1.0f); + + occ_lookup(tree, thread, exclude, co, nn, &occ, (aocolor)? bn: NULL); + + correction= re->wrld.ao_approx_correction; + + occlusion= (1.0f-correction)*(1.0f-occ); + CLAMP(occlusion, 0.0f, 1.0f); + if(correction != 0.0f) + occlusion += correction*exp(-occ); + + if(aocolor) { + /* sky shading using bent normal */ + if(aocolor==WO_AOSKYCOL) { + fac= 0.5*(1.0f+bn[0]*re->grvec[0]+ bn[1]*re->grvec[1]+ bn[2]*re->grvec[2]); + skycol[0]= (1.0f-fac)*re->wrld.horr + fac*re->wrld.zenr; + skycol[1]= (1.0f-fac)*re->wrld.horg + fac*re->wrld.zeng; + skycol[2]= (1.0f-fac)*re->wrld.horb + fac*re->wrld.zenb; + } + else { /* WO_AOSKYTEX */ + dxyview[0]= 1.0f; + dxyview[1]= 1.0f; + dxyview[2]= 0.0f; + shadeSkyView(skycol, co, bn, dxyview); + } + + VecMulf(skycol, occlusion); + } + else { + skycol[0]= occlusion; + skycol[1]= occlusion; + skycol[2]= occlusion; + } +} + +/* ---------------------------- Caching ------------------------------- */ + +static OcclusionCacheSample *find_occ_sample(OcclusionCache *cache, int x, int y) +{ + x -= cache->x; + y -= cache->y; + + x /= cache->step; + y /= cache->step; + x *= cache->step; + y *= cache->step; + + if(x < 0 || x >= cache->w || y < 0 || y >= cache->h) + return NULL; + else + return &cache->sample[y*cache->w + x]; +} + +static int sample_occ_cache(OcclusionTree *tree, float *co, float *n, int x, int y, int thread, float *col) +{ + OcclusionCache *cache; + OcclusionCacheSample *samples[4], *sample; + float wn[4], wz[4], wb[4], tx, ty, w, totw, mino, maxo; + float d[3], dist2; + int i, x1, y1, x2, y2; + + if(!tree->cache) + return 0; + + /* first try to find a sample in the same pixel */ + cache= &tree->cache[thread]; + + if(cache->sample && cache->step) { + sample= &cache->sample[(y-cache->y)*cache->w + (x-cache->x)]; + if(sample->filled) { + VECSUB(d, sample->co, co); + dist2= INPR(d, d); + if(dist2 < 0.5f*sample->dist2 && INPR(sample->n, n) > 0.98f) { + VECCOPY(col, sample->col); + return 1; + } + } + } + else + return 0; + + /* try to interpolate between 4 neighbouring pixels */ + samples[0]= find_occ_sample(cache, x, y); + samples[1]= find_occ_sample(cache, x+cache->step, y); + samples[2]= find_occ_sample(cache, x, y+cache->step); + samples[3]= find_occ_sample(cache, x+cache->step, y+cache->step); + + for(i=0; i<4; i++) + if(!samples[i] || !samples[i]->filled) + return 0; + + /* require intensities not being too different */ + mino= MIN4(samples[0]->intensity, samples[1]->intensity, samples[2]->intensity, samples[3]->intensity); + maxo= MAX4(samples[0]->intensity, samples[1]->intensity, samples[2]->intensity, samples[3]->intensity); + + if(maxo - mino > 0.05f) + return 0; + + /* compute weighted interpolation between samples */ + col[0]= col[1]= col[2]= 0.0f; + totw= 0.0f; + + x1= samples[0]->x; + y1= samples[0]->y; + x2= samples[3]->x; + y2= samples[3]->y; + + tx= (float)(x2 - x)/(float)(x2 - x1); + ty= (float)(y2 - y)/(float)(y2 - y1); + + wb[3]= (1.0f-tx)*(1.0f-ty); + wb[2]= (tx)*(1.0f-ty); + wb[1]= (1.0f-tx)*(ty); + wb[0]= tx*ty; + + for(i=0; i<4; i++) { + VECSUB(d, samples[i]->co, co); + dist2= INPR(d, d); + + wz[i]= 1.0f; //(samples[i]->dist2/(1e-4f + dist2)); + wn[i]= pow(INPR(samples[i]->n, n), 32.0f); + + w= wb[i]*wn[i]*wz[i]; + + totw += w; + col[0] += w*samples[i]->col[0]; + col[1] += w*samples[i]->col[1]; + col[2] += w*samples[i]->col[2]; + } + + if(totw >= 0.9f) { + totw= 1.0f/totw; + col[0] *= totw; + col[1] *= totw; + col[2] *= totw; + return 1; + } + + return 0; +} + +static void sample_occ_cache_mesh(ShadeInput *shi) +{ + StrandRen *strand= shi->strand; + OcclusionCacheMesh *mesh= strand->buffer->occlusionmesh; + int *face, *index = RE_strandren_get_face(shi->obr, strand, 0); + float w[4], *co1, *co2, *co3, *co4; + + if(mesh && index) { + face= mesh->face[*index]; + + co1= mesh->co[face[0]]; + co2= mesh->co[face[1]]; + co3= mesh->co[face[2]]; + co4= (face[3])? mesh->co[face[3]]: NULL; + + InterpWeightsQ3Dfl(co1, co2, co3, co4, strand->vert->co, w); + + shi->ao[0]= shi->ao[1]= shi->ao[2]= 0.0f; + VECADDFAC(shi->ao, shi->ao, mesh->col[face[0]], w[0]); + VECADDFAC(shi->ao, shi->ao, mesh->col[face[1]], w[1]); + VECADDFAC(shi->ao, shi->ao, mesh->col[face[2]], w[2]); + if(face[3]) + VECADDFAC(shi->ao, shi->ao, mesh->col[face[3]], w[3]); + } + else { + shi->ao[0]= 1.0f; + shi->ao[1]= 1.0f; + shi->ao[2]= 1.0f; + } +} + +void *cache_occ_mesh(Render *re, ObjectRen *obr, DerivedMesh *dm, float mat[][4]) +{ + OcclusionCacheMesh *mesh; + MFace *mface; + MVert *mvert; + int a, totvert, totface; + + totvert= dm->getNumVerts(dm); + totface= dm->getNumFaces(dm); + + mesh= re->occlusionmesh.last; + if(mesh && mesh->obr->ob == obr->ob && mesh->obr->par == obr->par + && mesh->totvert==totvert && mesh->totface==totface) + return mesh; + + mesh= MEM_callocN(sizeof(OcclusionCacheMesh), "OcclusionCacheMesh"); + mesh->obr= obr; + mesh->totvert= totvert; + mesh->totface= totface; + mesh->co= MEM_callocN(sizeof(float)*3*mesh->totvert, "OcclusionMeshCo"); + mesh->face= MEM_callocN(sizeof(int)*4*mesh->totface, "OcclusionMeshFaces"); + mesh->col= MEM_callocN(sizeof(float)*3*mesh->totvert, "OcclusionMeshCol"); + + mvert= dm->getVertArray(dm); + for(a=0; atotvert; a++, mvert++) { + VECCOPY(mesh->co[a], mvert->co); + Mat4MulVecfl(mat, mesh->co[a]); + } + + mface= dm->getFaceArray(dm); + for(a=0; atotface; a++, mface++) { + mesh->face[a][0]= mface->v1; + mesh->face[a][1]= mface->v2; + mesh->face[a][2]= mface->v3; + mesh->face[a][3]= mface->v4; + } + + BLI_addtail(&re->occlusionmesh, mesh); + + return mesh; +} + +/* ------------------------- External Functions --------------------------- */ + +void make_occ_tree(Render *re) +{ + OcclusionCacheMesh *mesh; + float col[3], co[3], n[3], *co1, *co2, *co3, *co4; + int a, *face, *count; + + /* ugly, needed for occ_face */ + R= *re; + + re->i.infostr= "Occlusion preprocessing"; + re->stats_draw(&re->i); + + re->occlusiontree= occ_tree_build(re); + + if(re->occlusiontree) { + if(re->wrld.ao_approx_passes) + occ_compute_passes(re, re->occlusiontree, re->wrld.ao_approx_passes); + + for(mesh=re->occlusionmesh.first; mesh; mesh=mesh->next) { + count= MEM_callocN(sizeof(int)*mesh->totvert, "OcclusionCount"); + + for(a=0; atotface; a++) { + face= mesh->face[a]; + co1= mesh->co[face[0]]; + co2= mesh->co[face[1]]; + co3= mesh->co[face[2]]; + + if(face[3]) { + co4= mesh->co[face[3]]; + + VecLerpf(co, co1, co3, 0.5f); + CalcNormFloat4(co1, co2, co3, co4, n); + } + else { + CalcCent3f(co, co1, co2, co3); + CalcNormFloat(co1, co2, co3, n); + } + VecMulf(n, -1.0f); + + sample_occ_tree(re, re->occlusiontree, NULL, co, n, 0, 0, col); + + VECADD(mesh->col[face[0]], mesh->col[face[0]], col); + count[face[0]]++; + VECADD(mesh->col[face[1]], mesh->col[face[1]], col); + count[face[1]]++; + VECADD(mesh->col[face[2]], mesh->col[face[2]], col); + count[face[2]]++; + + if(face[3]) { + VECADD(mesh->col[face[3]], mesh->col[face[3]], col); + count[face[3]]++; + } + } + + for(a=0; atotvert; a++) + if(count[a]) + VecMulf(mesh->col[a], 1.0f/count[a]); + + MEM_freeN(count); + } + } +} + +void free_occ(Render *re) +{ + OcclusionCacheMesh *mesh; + + if(re->occlusiontree) { + occ_free_tree(re->occlusiontree); + re->occlusiontree = NULL; + } + + for(mesh=re->occlusionmesh.first; mesh; mesh=mesh->next) { + if(mesh->co) MEM_freeN(mesh->co); + if(mesh->col) MEM_freeN(mesh->col); + if(mesh->face) MEM_freeN(mesh->face); + } + + BLI_freelistN(&re->occlusionmesh); +} + +void sample_occ(Render *re, ShadeInput *shi) +{ + OcclusionTree *tree= re->occlusiontree; + OcclusionCache *cache; + OcclusionCacheSample *sample; + OccFace exclude; + int onlyshadow; + + if(tree) { + if(shi->strand) { + sample_occ_cache_mesh(shi); + } + /* try to get result from the cache if possible */ + else if(!sample_occ_cache(tree, shi->co, shi->vno, shi->xs, shi->ys, shi->thread, shi->ao)) { + /* no luck, let's sample the occlusion */ + exclude.obi= shi->obi - re->objectinstance; + exclude.facenr= shi->vlr->index; + onlyshadow= (shi->mat->mode & MA_ONLYSHADOW); + sample_occ_tree(re, tree, &exclude, shi->co, shi->vno, shi->thread, onlyshadow, shi->ao); + + if(G.rt & 32) + shi->ao[2] *= 2.0f; + + /* fill result into sample, each time */ + if(tree->cache) { + cache= &tree->cache[shi->thread]; + + if(cache->sample && cache->step) { + sample= &cache->sample[(shi->ys-cache->y)*cache->w + (shi->xs-cache->x)]; + VECCOPY(sample->co, shi->co); + VECCOPY(sample->n, shi->vno); + VECCOPY(sample->col, shi->ao); + sample->intensity= MAX3(sample->col[0], sample->col[1], sample->col[2]); + sample->dist2= INPR(shi->dxco, shi->dxco) + INPR(shi->dyco, shi->dyco); + sample->filled= 1; + } + } + } + } + else { + shi->ao[0]= 1.0f; + shi->ao[1]= 1.0f; + shi->ao[2]= 1.0f; + } +} + +void cache_occ_samples(Render *re, RenderPart *pa, ShadeSample *ssamp) +{ + OcclusionTree *tree= re->occlusiontree; + PixStr ps; + OcclusionCache *cache; + OcclusionCacheSample *sample; + OccFace exclude; + ShadeInput *shi; + int *ro, *rp, *rz, onlyshadow; + int x, y, step = CACHE_STEP; + + if(!tree->cache) + return; + + cache= &tree->cache[pa->thread]; + cache->w= pa->rectx; + cache->h= pa->recty; + cache->x= pa->disprect.xmin; + cache->y= pa->disprect.ymin; + cache->step= step; + cache->sample= MEM_callocN(sizeof(OcclusionCacheSample)*cache->w*cache->h, "OcclusionCacheSample"); + sample= cache->sample; + + ps.next= NULL; + ps.mask= 0xFFFF; + + ro= pa->recto; + rp= pa->rectp; + rz= pa->rectz; + + /* compute a sample at every step pixels */ + for(y=pa->disprect.ymin; ydisprect.ymax; y++) { + for(x=pa->disprect.xmin; xdisprect.xmax; x++, ro++, rp++, rz++, sample++) { + if((((x - pa->disprect.xmin + step) % step) == 0 || x == pa->disprect.xmax-1) && (((y - pa->disprect.ymin + step) % step) == 0 || y == pa->disprect.ymax-1)) { + if(*rp) { + ps.obi= *ro; + ps.facenr= *rp; + ps.z= *rz; + + shade_samples_fill_with_ps(ssamp, &ps, x, y); + shi= ssamp->shi; + if(!shi->vlr) + continue; + + onlyshadow= (shi->mat->mode & MA_ONLYSHADOW); + exclude.obi= shi->obi - re->objectinstance; + exclude.facenr= shi->vlr->index; + sample_occ_tree(re, tree, &exclude, shi->co, shi->vno, shi->thread, onlyshadow, shi->ao); + + VECCOPY(sample->co, shi->co); + VECCOPY(sample->n, shi->vno); + VECCOPY(sample->col, shi->ao); + sample->intensity= MAX3(sample->col[0], sample->col[1], sample->col[2]); + sample->dist2= INPR(shi->dxco, shi->dxco) + INPR(shi->dyco, shi->dyco); + sample->x= shi->xs; + sample->y= shi->ys; + sample->filled= 1; + } + + if(re->test_break()) + break; + } + } + } +} + +void free_occ_samples(Render *re, RenderPart *pa) +{ + OcclusionTree *tree= re->occlusiontree; + OcclusionCache *cache; + + if(tree->cache) { + cache= &tree->cache[pa->thread]; + + if(cache->sample) + MEM_freeN(cache->sample); + + cache->w= 0; + cache->h= 0; + cache->step= 0; + } +} + diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 0f9d4470164..b8e3091ae4a 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -331,6 +331,10 @@ static char *get_pass_name(int passtype, int channel) if(channel==-1) return "IndexOB"; return "IndexOB.X"; } + if(passtype == SCE_PASS_MIST) { + if(channel==-1) return "Mist"; + return "Mist.Z"; + } return "Unknown"; } @@ -379,6 +383,9 @@ static int passtype_from_name(char *str) if(strcmp(str, "IndexOB")==0) return SCE_PASS_INDEXOB; + if(strcmp(str, "Mist")==0) + return SCE_PASS_MIST; + return 0; } @@ -538,11 +545,16 @@ static RenderResult *new_render_result(Render *re, rcti *partrct, int crop, int if(srl->passflag & SCE_PASS_REFRACT) render_layer_add_pass(rr, rl, 3, SCE_PASS_REFRACT); } + else if(re->wrld.mode & WO_AMB_OCC) + if(re->wrld.ao_gather_method == WO_AOGATHER_APPROX) + render_layer_add_pass(rr, rl, 3, SCE_PASS_AO); if(re->r.mode & R_RADIO) if(srl->passflag & SCE_PASS_RADIO) render_layer_add_pass(rr, rl, 3, SCE_PASS_RADIO); if(srl->passflag & SCE_PASS_INDEXOB) render_layer_add_pass(rr, rl, 1, SCE_PASS_INDEXOB); + if(srl->passflag & SCE_PASS_MIST) + render_layer_add_pass(rr, rl, 1, SCE_PASS_MIST); } /* sss, previewrender and envmap don't do layers, so we make a default one */ @@ -2010,7 +2022,7 @@ static void renderresult_stampinfo() RenderResult rres; /* this is the basic trick to get the displayed float or char rect from render result */ RE_GetResultImage(RE_GetRender(G.scene->id.name), &rres); - BKE_stamp_buf((unsigned char *)rres.rect32, rres.rectf, rres.rectx, rres.recty); + BKE_stamp_buf((unsigned char *)rres.rect32, rres.rectf, rres.rectx, rres.recty, 4); } /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ @@ -2335,12 +2347,24 @@ void RE_BlenderAnim(Render *re, Scene *scene, int sfra, int efra) } } } else { - for(scene->r.cfra= sfra; - scene->r.cfra<=efra; scene->r.cfra++) { - re->r.cfra= scene->r.cfra; /* weak.... */ - - do_render_all_options(re); + for(scene->r.cfra= sfra; scene->r.cfra<=efra; scene->r.cfra++) { + char name[FILE_MAX]; + if (scene->r.mode & (R_NO_OVERWRITE | R_TOUCH) ) { + BKE_makepicstring(name, scene->r.pic, scene->r.cfra, scene->r.imtype); + } + + if (scene->r.mode & R_NO_OVERWRITE && BLI_exist(name)) { + printf("skipping existing frame \"%s\"\n", name); + continue; + } + if (scene->r.mode & R_TOUCH && !BLI_exist(name)) { + BLI_touch(name); + } + re->r.cfra= scene->r.cfra; /* weak.... */ + + do_render_all_options(re); + if(re->test_break() == 0) { do_write_image_or_movie(re, scene, mh); } diff --git a/source/blender/render/intern/source/pixelshading.c b/source/blender/render/intern/source/pixelshading.c index a1088d1a920..4e589789412 100644 --- a/source/blender/render/intern/source/pixelshading.c +++ b/source/blender/render/intern/source/pixelshading.c @@ -182,7 +182,7 @@ static void render_lighting_halo(HaloRen *har, float *colf) inp= vn[0]*lv[0] + vn[1]*lv[1] + vn[2]*lv[2]; if(inp>0.0) { /* testshadowbuf==0.0 : 100% shadow */ - shadfac = testshadowbuf(lar->shb, rco, dco, dco, inp); + shadfac = testshadowbuf(lar->shb, rco, dco, dco, inp, 0.0f); if( shadfac>0.0 ) { shadfac*= inp*soft*lar->energy; ir -= shadfac; @@ -219,7 +219,7 @@ static void render_lighting_halo(HaloRen *har, float *colf) if(i> -0.41) { /* heuristic valua! */ shadfac= 1.0; if(lar->shb) { - shadfac = testshadowbuf(lar->shb, rco, dco, dco, inp); + shadfac = testshadowbuf(lar->shb, rco, dco, dco, inp, 0.0f); if(shadfac==0.0) continue; i*= shadfac; } diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index e2f331afafd..e151151b0d2 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -60,6 +60,7 @@ #include "renderpipeline.h" #include "render_types.h" #include "renderdatabase.h" +#include "occlusion.h" #include "pixelblending.h" #include "pixelshading.h" #include "shadbuf.h" @@ -399,6 +400,12 @@ static void add_filt_passes(RenderLayer *rl, int curmask, int rectx, int offset, *fp= (float)shi->obr->ob->index; } break; + case SCE_PASS_MIST: + /* */ + col= &shr->mist; + pixsize= 1; + break; + case SCE_PASS_VECTOR: { /* add minimum speed in pixel, no filter */ @@ -477,6 +484,10 @@ static void add_passes(RenderLayer *rl, int offset, ShadeInput *shi, ShadeResult *fp= (float)shi->obr->ob->index; } break; + case SCE_PASS_MIST: + fp= rpass->rect + offset; + *fp= shr->mist; + break; } if(col) { fp= rpass->rect + pixsize*offset; @@ -534,7 +545,11 @@ static void shadeDA_tile(RenderPart *pa, RenderLayer *rl) /* general shader info, passes */ shade_sample_initialize(&ssamp, pa, rl); addpassflag= rl->passflag & ~(SCE_PASS_Z|SCE_PASS_COMBINED); - + + /* occlusion caching */ + if(R.occlusiontree) + cache_occ_samples(&R, pa, &ssamp); + /* filtered render, for now we assume only 1 filter size */ if(pa->crop) { crop= 1; @@ -582,6 +597,9 @@ static void shadeDA_tile(RenderPart *pa, RenderLayer *rl) if(R.r.mode & R_SHADOW) ISB_free(pa); + + if(R.occlusiontree) + free_occ_samples(&R, pa); } /* ************* pixel struct ******** */ @@ -1072,6 +1090,9 @@ void zbufshade_tile(RenderPart *pa) /* irregular shadowb buffer creation */ if(R.r.mode & R_SHADOW) ISB_create(pa, NULL); + + if(R.occlusiontree) + cache_occ_samples(&R, pa, &ssamp); for(y=pa->disprect.ymin; ydisprect.ymax; y++, rr->renrect.ymax++) { for(x=pa->disprect.xmin; xdisprect.xmax; x++, ro++, rz++, rp++, fcol+=4, offs++) { @@ -1085,9 +1106,6 @@ void zbufshade_tile(RenderPart *pa) if(shade_samples(&ssamp, &ps, x, y)) { QUATCOPY(fcol, ssamp.shr[0].combined); - if(!(fcol[0] == fcol[0])) - printvecf("fudgecol", fcol); - /* passes */ if(addpassflag) add_passes(rl, offs, ssamp.shi, ssamp.shr); @@ -1098,6 +1116,9 @@ void zbufshade_tile(RenderPart *pa) if(R.test_break()) break; } + if(R.occlusiontree) + free_occ_samples(&R, pa); + if(R.r.mode & R_SHADOW) ISB_free(pa); } diff --git a/source/blender/render/intern/source/renderdatabase.c b/source/blender/render/intern/source/renderdatabase.c index b9dfd0ab266..8aaf29b65c4 100644 --- a/source/blender/render/intern/source/renderdatabase.c +++ b/source/blender/render/intern/source/renderdatabase.c @@ -105,6 +105,7 @@ #define RE_UV_ELEMS 2 #define RE_SURFNOR_ELEMS 3 #define RE_SIMPLIFY_ELEMS 2 +#define RE_FACE_ELEMS 1 float *RE_vertren_get_sticky(ObjectRen *obr, VertRen *ver, int verify) { @@ -408,6 +409,7 @@ int RE_vlakren_get_normal(Render *re, ObjectInstanceRen *obi, VlakRen *vlr, floa nor[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn; nor[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn; nor[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn; + Normalize(nor); } else VECCOPY(nor, vlr->n); @@ -606,6 +608,21 @@ float *RE_strandren_get_simplify(struct ObjectRen *obr, struct StrandRen *strand return simplify + (strand->index & 255)*RE_SIMPLIFY_ELEMS; } +int *RE_strandren_get_face(ObjectRen *obr, StrandRen *strand, int verify) +{ + int *face; + int nr= strand->index>>8; + + face= obr->strandnodes[nr].face; + if(face==NULL) { + if(verify) + face= obr->strandnodes[nr].face= MEM_callocN(256*RE_FACE_ELEMS*sizeof(int), "face table"); + else + return NULL; + } + return face + (strand->index & 255)*RE_FACE_ELEMS; +} + /* winspeed is exception, it is stored per instance */ float *RE_strandren_get_winspeed(ObjectInstanceRen *obi, StrandRen *strand, int verify) { @@ -756,6 +773,8 @@ void free_renderdata_strandnodes(StrandTableNode *strandnodes) MEM_freeN(strandnodes[a].surfnor); if(strandnodes[a].simplify) MEM_freeN(strandnodes[a].simplify); + if(strandnodes[a].face) + MEM_freeN(strandnodes[a].face); } MEM_freeN(strandnodes); @@ -1275,34 +1294,9 @@ ObjectInstanceRen *RE_addRenderInstance(Render *re, ObjectRen *obr, Object *ob, return obi; } -void find_dupli_objectren(Render *re, ObjectInstanceRen *obi, ObjectInstanceRen *lastobi) -{ - ObjectRen *obr; - - /* see if last object did the same lookup, so we can just reuse result */ - if(lastobi && obi->ob == lastobi->ob && obi->par == lastobi->par && obi->psysindex == lastobi->psysindex) { - obi->obr= lastobi->obr; - return; - } - - /* dupli objects are created after object instances, so we look through - * object list to find it */ - obr= re->objecttable.first; - while(obr && (obr->ob != obi->ob || obr->par != obi->par || obr->psysindex != obi->psysindex)) - obr= obr->next; - - if(!obr) { - obr= re->objecttable.first; - while(obr && (obr->ob != obi->ob || obr->psysindex != obi->psysindex) && obr->par == NULL) - obr= obr->next; - } - - obi->obr= obr; -} - void RE_makeRenderInstances(Render *re) { - ObjectInstanceRen *obi, *oldobi, *lastobi= NULL; + ObjectInstanceRen *obi, *oldobi; ListBase newlist; int tot; @@ -1316,11 +1310,6 @@ void RE_makeRenderInstances(Render *re) for(oldobi=re->instancetable.first; oldobi; oldobi=oldobi->next) { *obi= *oldobi; - if(!obi->obr) { - find_dupli_objectren(re, obi, lastobi); - lastobi= obi; - } - if(obi->obr) { obi->prev= obi->next= NULL; BLI_addtail(&newlist, obi); diff --git a/source/blender/render/intern/source/shadbuf.c b/source/blender/render/intern/source/shadbuf.c index 8e37606cdf9..34fd5b0154a 100644 --- a/source/blender/render/intern/source/shadbuf.c +++ b/source/blender/render/intern/source/shadbuf.c @@ -648,11 +648,11 @@ static float readshadowbuf(ShadBuf *shb, ShadSampleBuf *shsample, int bias, int /* the externally called shadow testing (reading) function */ /* return 1.0: no shadow at all */ -float testshadowbuf(ShadBuf *shb, float *rco, float *dxco, float *dyco, float inp) +float testshadowbuf(ShadBuf *shb, float *rco, float *dxco, float *dyco, float inp, float mat_bias) { ShadSampleBuf *shsample; float fac, co[4], dx[3], dy[3], shadfac=0.0f; - float xs1,ys1, siz, *jit, *weight, xres, yres; + float xs1,ys1, siz, *jit, *weight, xres, yres, biasf; int xs, ys, zs, bias, *rz; short a, num; @@ -689,10 +689,12 @@ float testshadowbuf(ShadBuf *shb, float *rco, float *dxco, float *dyco, float in num= shb->samp*shb->samp; fac= shb->soft; + if(mat_bias!=0.0f) biasf= shb->bias*mat_bias; + else biasf= shb->bias; /* with inp==1.0, bias is half the size. correction value was 1.1, giving errors on cube edges, with one side being almost frontal lighted (ton) */ - bias= (1.5f-inp*inp)*shb->bias; - + bias= (1.5f-inp*inp)*biasf; + if(num==1) { for(shsample= shb->buffers.first; shsample; shsample= shsample->next) shadfac += readshadowbuf(shb, shsample, bias, (int)xs1, (int)ys1, zs); diff --git a/source/blender/render/intern/source/shadeinput.c b/source/blender/render/intern/source/shadeinput.c index d862729317b..3a8b0cca7fc 100644 --- a/source/blender/render/intern/source/shadeinput.c +++ b/source/blender/render/intern/source/shadeinput.c @@ -161,11 +161,16 @@ void shade_input_do_shade(ShadeInput *shi, ShadeResult *shr) } /* MIST */ - if((R.wrld.mode & WO_MIST) && (shi->mat->mode & MA_NOMIST)==0 ) { + if((shi->passflag & SCE_PASS_MIST) || ((R.wrld.mode & WO_MIST) && (shi->mat->mode & MA_NOMIST)==0)) { if(R.r.mode & R_ORTHO) - alpha= mistfactor(-shi->co[2], shi->co); + shr->mist= mistfactor(-shi->co[2], shi->co); else - alpha= mistfactor(VecLength(shi->co), shi->co); + shr->mist= mistfactor(VecLength(shi->co), shi->co); + } + else shr->mist= 0.0f; + + if((R.wrld.mode & WO_MIST) && (shi->mat->mode & MA_NOMIST)==0 ) { + alpha= shr->mist; } else alpha= 1.0f; @@ -422,7 +427,7 @@ void shade_input_set_strand_texco(ShadeInput *shi, StrandRen *strand, StrandVert } if(texco & TEXCO_STRAND) { - shi->strand= spoint->strandco; + shi->strandco= spoint->strandco; if(shi->osatex) { shi->dxstrand= spoint->dtstrandco; @@ -935,7 +940,7 @@ void shade_input_set_shade_texco(ShadeInput *shi) } if(texco & TEXCO_STRAND) { - shi->strand= (l*v3->accum - u*v1->accum - v*v2->accum); + shi->strandco= (l*v3->accum - u*v1->accum - v*v2->accum); if(shi->osatex) { dl= shi->dx_u+shi->dx_v; shi->dxstrand= dl*v3->accum-shi->dx_u*v1->accum-shi->dx_v*v2->accum; @@ -1236,7 +1241,7 @@ void shade_samples_do_AO(ShadeSample *ssamp) if(!(R.r.mode & R_SHADOW)) return; - if(!(R.r.mode & R_RAYTRACE)) + if(!(R.r.mode & R_RAYTRACE) && !(R.wrld.ao_gather_method == WO_AOGATHER_APPROX)) return; if(R.wrld.mode & WO_AMB_OCC) @@ -1248,7 +1253,7 @@ void shade_samples_do_AO(ShadeSample *ssamp) } -static void shade_samples_fill_with_ps(ShadeSample *ssamp, PixStr *ps, int x, int y) +void shade_samples_fill_with_ps(ShadeSample *ssamp, PixStr *ps, int x, int y) { ShadeInput *shi; float xs, ys; diff --git a/source/blender/render/intern/source/shadeoutput.c b/source/blender/render/intern/source/shadeoutput.c index 0823ae146f7..0ba7c09cdd8 100644 --- a/source/blender/render/intern/source/shadeoutput.c +++ b/source/blender/render/intern/source/shadeoutput.c @@ -43,6 +43,7 @@ #include "DNA_material_types.h" /* local include */ +#include "occlusion.h" #include "renderpipeline.h" #include "render_types.h" #include "pixelblending.h" @@ -1006,8 +1007,9 @@ static void do_specular_ramp(ShadeInput *shi, float is, float t, float *spec) /* pure AO, check for raytrace and world should have been done */ void ambient_occlusion(ShadeInput *shi) { - - if((R.r.mode & R_RAYTRACE) && shi->mat->amb!=0.0f) + if((R.wrld.ao_gather_method == WO_AOGATHER_APPROX) && shi->mat->amb!=0.0f) + sample_occ(&R, shi); + else if((R.r.mode & R_RAYTRACE) && shi->mat->amb!=0.0f) ray_ao(shi, shi->ao); else shi->ao[0]= shi->ao[1]= shi->ao[2]= 1.0f; @@ -1017,25 +1019,28 @@ void ambient_occlusion(ShadeInput *shi) /* wrld mode was checked for */ void ambient_occlusion_to_diffuse(ShadeInput *shi, float *diff) { - - if((R.r.mode & R_RAYTRACE) && shi->mat->amb!=0.0f) { - float f= R.wrld.aoenergy*shi->mat->amb; + if((R.r.mode & R_RAYTRACE) || R.wrld.ao_gather_method == WO_AOGATHER_APPROX) { + if(shi->mat->amb!=0.0f) { + float f= R.wrld.aoenergy*shi->mat->amb; - if (R.wrld.aomix==WO_AOADDSUB) { - diff[0] = 2.0f*shi->ao[0]-1.0f; - diff[1] = 2.0f*shi->ao[1]-1.0f; - diff[2] = 2.0f*shi->ao[2]-1.0f; + if (R.wrld.aomix==WO_AOADDSUB) { + diff[0] = 2.0f*shi->ao[0]-1.0f; + diff[1] = 2.0f*shi->ao[1]-1.0f; + diff[2] = 2.0f*shi->ao[2]-1.0f; + } + else if (R.wrld.aomix==WO_AOSUB) { + diff[0] = shi->ao[0]-1.0f; + diff[1] = shi->ao[1]-1.0f; + diff[2] = shi->ao[2]-1.0f; + } + else { + VECCOPY(diff, shi->ao); + } + + VECMUL(diff, f); } - else if (R.wrld.aomix==WO_AOSUB) { - diff[0] = shi->ao[0]-1.0f; - diff[1] = shi->ao[1]-1.0f; - diff[2] = shi->ao[2]-1.0f; - } - else { - VECCOPY(diff, shi->ao); - } - - VECMUL(diff, f); + else + diff[0]= diff[1]= diff[2]= 0.0f; } else diff[0]= diff[1]= diff[2]= 0.0f; @@ -1054,7 +1059,7 @@ void lamp_get_shadow(LampRen *lar, ShadeInput *shi, float inp, float *shadfac, i if(lar->buftype==LA_SHADBUF_IRREGULAR) shadfac[3]= ISB_getshadow(shi, lar->shb); else - shadfac[3] = testshadowbuf(lar->shb, shi->co, shi->dxco, shi->dyco, inp); + shadfac[3] = testshadowbuf(lar->shb, shi->co, shi->dxco, shi->dyco, inp, shi->mat->lbias); } else if(lar->mode & LA_SHAD_RAY) { ray_shadow(shi, lar, shadfac); diff --git a/source/blender/render/intern/source/strand.c b/source/blender/render/intern/source/strand.c index 3ad9bb66559..605b381cdc0 100644 --- a/source/blender/render/intern/source/strand.c +++ b/source/blender/render/intern/source/strand.c @@ -59,7 +59,7 @@ void merge_transp_passes(RenderLayer *rl, ShadeResult *shr); void add_transp_passes(RenderLayer *rl, int offset, ShadeResult *shr, float alpha); void hoco_to_zco(ZSpan *zspan, float *zco, float *hoco); void zspan_scanconvert_strand(ZSpan *zspan, void *handle, float *v1, float *v2, float *v3, void (*func)(void *, int, int, float, float, float) ); -void zbufsinglewire(ZSpan *zspan, ObjectRen *obr, int zvlnr, float *ho1, float *ho2); +void zbufsinglewire(ZSpan *zspan, int obi, int zvlnr, float *ho1, float *ho2); int addtosamp_shr(ShadeResult *samp_shr, ShadeSample *ssamp, int addpassflag); void add_transp_speed(RenderLayer *rl, int offset, float *speed, float alpha, long *rdrect); void reset_sky_speedvectors(RenderPart *pa, RenderLayer *rl, float *rectf); @@ -458,6 +458,11 @@ static int compare_strand_segment(const void *poin1, const void *poin2) return 1; } +static void interpolate_vec1(float *v1, float *v2, float t, float negt, float *v) +{ + v[0]= negt*v1[0] + t*v2[0]; +} + static void interpolate_vec3(float *v1, float *v2, float t, float negt, float *v) { v[0]= negt*v1[0] + t*v2[0]; @@ -504,6 +509,8 @@ static void interpolate_shade_result(ShadeResult *shr1, ShadeResult *shr2, float interpolate_vec3(shr1->refr, shr2->refr, t, negt, shr->refr); if(addpassflag & SCE_PASS_RADIO) interpolate_vec3(shr1->rad, shr2->rad, t, negt, shr->rad); + if(addpassflag & SCE_PASS_MIST) + interpolate_vec1(&shr1->mist, &shr2->mist, t, negt, &shr->mist); } } @@ -685,6 +692,7 @@ static void strand_shade_point(Render *re, ShadeSample *ssamp, StrandSegment *ss vlr.flag |= R_TANGENT; shi->vlr= &vlr; + shi->strand= sseg->strand; shi->obi= sseg->obi; shi->obr= sseg->obi->obr; @@ -1057,6 +1065,9 @@ unsigned short *zbuffer_strands_shade(Render *re, RenderPart *pa, RenderLayer *r if(re->test_break()) break; + if(!(strand->buffer->lay & rl->lay)) + continue; + #if 0 if(strand->clip) continue; diff --git a/source/blender/render/intern/source/texture.c b/source/blender/render/intern/source/texture.c index a4182637f02..be248ddda3f 100644 --- a/source/blender/render/intern/source/texture.c +++ b/source/blender/render/intern/source/texture.c @@ -1521,7 +1521,7 @@ void do_material_tex(ShadeInput *shi) } else if(mtex->texco==TEXCO_STRAND) { co= tempvec; dx= dxt; dy= dyt; - co[0]= shi->strand; + co[0]= shi->strandco; co[1]= co[2]= 0.0f; dx[0]= shi->dxstrand; dx[1]= dx[2]= 0.0f; diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c index 98a19c8c0e0..3779f238102 100644 --- a/source/blender/render/intern/source/zbuf.c +++ b/source/blender/render/intern/source/zbuf.c @@ -3346,6 +3346,10 @@ void merge_transp_passes(RenderLayer *rl, ShadeResult *shr) case SCE_PASS_NORMAL: col= shr->nor; break; + case SCE_PASS_MIST: + col= &shr->mist; + pixsize= 1; + break; case SCE_PASS_VECTOR: { @@ -3397,6 +3401,7 @@ void add_transp_passes(RenderLayer *rl, int offset, ShadeResult *shr, float alph for(rpass= rl->passes.first; rpass; rpass= rpass->next) { float *fp, *col= NULL; + int pixsize= 3; switch(rpass->passtype) { case SCE_PASS_RGBA: @@ -3427,13 +3432,19 @@ void add_transp_passes(RenderLayer *rl, int offset, ShadeResult *shr, float alph case SCE_PASS_NORMAL: col= shr->nor; break; + case SCE_PASS_MIST: + col= &shr->mist; + pixsize= 1; + break; } if(col) { - fp= rpass->rect + 3*offset; + fp= rpass->rect + pixsize*offset; fp[0]= alpha*col[0] + (1.0f-alpha)*fp[0]; - fp[1]= alpha*col[1] + (1.0f-alpha)*fp[1]; - fp[2]= alpha*col[2] + (1.0f-alpha)*fp[2]; + if(pixsize==3) { + fp[1]= alpha*col[1] + (1.0f-alpha)*fp[1]; + fp[2]= alpha*col[2] + (1.0f-alpha)*fp[2]; + } } } } @@ -3595,6 +3606,10 @@ int addtosamp_shr(ShadeResult *samp_shr, ShadeSample *ssamp, int addpassflag) if(addpassflag & SCE_PASS_RADIO) addvecmul(samp_shr->rad, shr->rad, fac); + + if(addpassflag & SCE_PASS_MIST) + samp_shr->mist= samp_shr->mist+fac*shr->mist; + } } } @@ -3775,6 +3790,7 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas add_transp_speed(rl, od, ssamp.shr[0].winspeed, pass[3], rdrect); } else { + float alpha= 0.0f; short filled, *sp= (short *)(ztramask+od); /* for each mask-sample we alpha-under colors. then in end it's added using filter */ @@ -3797,17 +3813,21 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas } } + /* note; cannot use pass[3] for alpha due to filtermask */ for(a=0; arectx); + alpha+= samp_shr[a].combined[3]; } if(addpassflag) { + alpha*= sampalpha; + /* merge all in one, and then add */ merge_transp_passes(rl, samp_shr); - add_transp_passes(rl, od, samp_shr, pass[3]); + add_transp_passes(rl, od, samp_shr, alpha); if(addpassflag & SCE_PASS_VECTOR) - add_transp_speed(rl, od, samp_shr[0].winspeed, pass[3], rdrect); + add_transp_speed(rl, od, samp_shr[0].winspeed, alpha, rdrect); } } } diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index cfa4937749d..0cacb98490b 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #ifdef WIN32 @@ -3867,6 +3868,43 @@ void do_armbuts(unsigned short event) } } break; + case B_POSEGRP_RECALC: + allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWBUTSEDIT, 0); + break; + case B_POSEGRP_ADD: + if (ob && ob->pose) { + bPose *pose= ob->pose; + bActionGroup *grp; + + grp= MEM_callocN(sizeof(bActionGroup), "PoseGroup"); + strcpy(grp->name, "Group"); + BLI_addtail(&pose->agroups, grp); + BLI_uniquename(&pose->agroups, grp, "Group", offsetof(bActionGroup, name), 32); + + pose->active_group= BLI_countlist(&pose->agroups); + + BIF_undo_push("Add Pose Group"); + allqueue(REDRAWBUTSEDIT, 0); + allqueue(REDRAWVIEW3D, 0); + } + break; + case B_POSEGRP_REMOVE: + if (ob && ob->pose && ob->pose->active_group) { + bPose *pose= ob->pose; + bActionGroup *grp= NULL; + + grp= BLI_findlink(&pose->agroups, pose->active_group-1); + if (grp) { + BLI_freelinkN(&pose->agroups, grp); + pose->active_group= 0; + } + + BIF_undo_push("Remove Pose Group"); + allqueue(REDRAWBUTSEDIT, 0); + allqueue(REDRAWVIEW3D, 0); + } + break; } } @@ -4297,6 +4335,37 @@ static int ob_arm_bone_pchan_lock(Object *ob, bArmature *arm, Bone *bone, bPoseC return 0; } +static char *build_posegroups_menustr(bPose *pose) +{ + DynStr *pupds= BLI_dynstr_new(); + bActionGroup *agrp; + char *str; + char buf[16]; + int i; + + /* add title first (and the "none" entry) */ + BLI_dynstr_append(pupds, "Pose Group%t|"); + BLI_dynstr_append(pupds, "BG: [None]%x0"); + + /* loop through markers, adding them */ + for (agrp= pose->agroups.first, i=1; agrp; agrp=agrp->next, i++) { + BLI_dynstr_append(pupds, "BG: "); + BLI_dynstr_append(pupds, agrp->name); + + sprintf(buf, "%%x%d", i); + BLI_dynstr_append(pupds, buf); + + if (agrp->next) + BLI_dynstr_append(pupds, "|"); + } + + /* convert to normal MEM_malloc'd string */ + str= BLI_dynstr_get_cstring(pupds); + BLI_dynstr_free(pupds); + + return str; +} + static void editing_panel_pose_bones(Object *ob, bArmature *arm) { uiBlock *block; @@ -4305,6 +4374,7 @@ static void editing_panel_pose_bones(Object *ob, bArmature *arm) Bone *curBone; int by, a; int index, zerodof, zerolimit; + char *menustr; /* Draw the bone name block */ block= uiNewBlock(&curarea->uiblocks, "editing_panel_pose_bones", UI_EMBOSS, UI_HELV, curarea->win); @@ -4320,19 +4390,23 @@ static void editing_panel_pose_bones(Object *ob, bArmature *arm) for (pchan=ob->pose->chanbase.first, index=0; pchan; pchan=pchan->next, index++){ curBone= pchan->bone; if ((curBone->flag & BONE_SELECTED) && (curBone->layer & arm->layer)) { - if(ob_arm_bone_pchan_lock(ob, arm, curBone, pchan)) uiDefBut(block, LABEL, 0, "Proxy Locked", 160, 180,150,18, NULL, 1, 0, 0, 0, ""); - /* Bone naming button */ + /* Bone naming button */ uiBlockBeginAlign(block); but=uiDefBut(block, TEX, REDRAWVIEW3D, "BO:", -10,by,117,19, curBone->name, 0, 24, 0, 0, "Change the bone name"); uiButSetFunc(but, validate_posebonebutton_cb, curBone, NULL); uiButSetCompleteFunc(but, autocomplete_bone, (void *)ob); - /* Dist and weight buttons */ - uiDefButF(block, NUM,B_ARM_RECALCDATA, "Dist:", 107, by, 105, 19, &curBone->dist, 0.0, 1000.0, 10.0, 0.0, "Bone deformation distance"); - uiDefButF(block, NUM,B_ARM_RECALCDATA, "Weight:", 220, by, 110, 19, &curBone->weight, 0.0F, 1000.0F, 10.0F, 0.0F, "Bone deformation weight"); + /* Bone custom drawing */ + menustr= build_posegroups_menustr(ob->pose); + uiDefButS(block, MENU,REDRAWVIEW3D, menustr, 107,by,105,19, &pchan->agrp_index, 0.0, 0.0, 0.0, 0.0, "Change the Pose Group this Bone belongs to"); + MEM_freeN(menustr); + + ob_arm_bone_pchan_lock(ob, arm, curBone, pchan); + uiDefIDPoinBut(block, test_obpoin_but, ID_OB, REDRAWVIEW3D, "OB:", 220,by,110,19, &pchan->custom, "Object that defines custom draw type for this Bone"); + ob_arm_bone_pchan_lock(ob, arm, curBone, NULL); /* Segment, ease in/out buttons */ uiBlockBeginAlign(block); @@ -4345,9 +4419,7 @@ static void editing_panel_pose_bones(Object *ob, bArmature *arm) uiDefButBitI(block, TOG, BONE_NO_SCALE, B_ARM_RECALCDATA, "S", 70,by-38,20,19, &curBone->flag, 1.0, 32.0, 0.0, 0.0, "Don't inherit scale from parent Bone"); uiDefButBitI(block, TOGN, BONE_NO_DEFORM, B_ARM_RECALCDATA, "Deform", 90, by-38, 80, 19, &curBone->flag, 0.0, 0.0, 0.0, 0.0, "Indicate if Bone deforms geometry"); uiDefButBitI(block, TOG, BONE_MULT_VG_ENV, B_ARM_RECALCDATA, "Mult", 170,by-38,80,19, &curBone->flag, 1.0, 32.0, 0.0, 0.0, "Multiply Bone Envelope with VertexGroup"); - ob_arm_bone_pchan_lock(ob, arm, curBone, pchan); - uiDefIDPoinBut(block, test_obpoin_but, ID_OB, REDRAWVIEW3D, "OB:", 250,by-38,80,19, &pchan->custom, "Object that defines custom draw type for this Bone"); - ob_arm_bone_pchan_lock(ob, arm, curBone, NULL); + uiDefButBitI(block, TOG, BONE_MULT_VG_ENV, B_ARM_RECALCDATA, "Hide", 250,by-38,80,19, &curBone->flag, 1.0, 32.0, 0.0, 0.0, "Toggles display of this bone in Edit Mode"); /* layers */ uiBlockBeginAlign(block); @@ -4995,6 +5067,22 @@ char *get_vertexgroup_menustr(Object *ob) return menustr; } +static void verify_poselib_posename(void *arg1, void *arg2) +{ + bAction *act= (bAction *)arg1; + TimeMarker *marker= (TimeMarker *)arg2; + + BLI_uniquename(&act->markers, marker, "Pose", offsetof(TimeMarker, name), 64); +} + +static void verify_posegroup_groupname(void *arg1, void *arg2) +{ + bPose *pose= (bPose *)arg1; + bActionGroup *grp= (bActionGroup *)arg2; + + BLI_uniquename(&pose->agroups, grp, "Group", offsetof(bActionGroup, name), 32); +} + static void editing_panel_links(Object *ob) { uiBlock *block; @@ -5081,10 +5169,14 @@ static void editing_panel_links(Object *ob) if (ob->type==OB_ARMATURE) { if ((ob->pose) && (ob->flag & OB_POSEMODE) && (G.obedit != ob)) { bAction *act= ob->poselib; + bPose *pose= ob->pose; + int count; + char *menustr; + /* PoseLib settings for armature reside on the left */ xco= 143; - uiDefBut(block, LABEL,0, "Pose Library (Action):", xco, 154, 200, 20, 0, 0, 0, 0, 0, ""); + uiDefBut(block, LABEL,0, "Pose Library:", xco, 154, 200, 20, 0, 0, 0, 0, 0, ""); /* PoseLib Action */ uiBlockSetCol(block, TH_BUT_SETTING2); @@ -5093,20 +5185,23 @@ static void editing_panel_links(Object *ob) uiDefBut(block, BUT, B_POSELIB_VALIDATE, "Auto-Sync PoseLib", xco,110,160,20, 0, 0, 0, 0, 0, "Syncs the current PoseLib with the poses available"); - /* poselib pose editing controls */ - if ((act) && (act->markers.first)) { - TimeMarker *marker= poselib_get_active_pose(act); - int count= BLI_countlist(&act->markers); - char *menustr= poselib_build_poses_menu(act, "PoseLib Poses"); - + /* PoseLib - Pose editing controls */ + if (act) { uiBlockBeginAlign(block); /* currently 'active' pose */ - uiDefButI(block, MENU, B_POSELIB_APPLYP, menustr, xco, 85,18,20, &act->active_marker, 1, count, 0, 0, "Browses Poses in Pose Library. Applies chosen pose."); - MEM_freeN(menustr); - - if (act->active_marker) { - uiDefBut(block, TEX, REDRAWBUTSEDIT,"", xco+18,85,160-18-20,20, marker->name, 0, 63, 0, 0, "Displays current Pose Library Pose name. Click to change."); - uiDefIconBut(block, BUT, B_POSELIB_REMOVEP, VICON_X, xco+160-20, 85, 20, 20, NULL, 0.0, 0.0, 0.0, 0.0, "Remove this Pose Library Pose from Pose Library."); + if (act->markers.first) { + count= BLI_countlist(&act->markers); + menustr= poselib_build_poses_menu(act, "PoseLib Poses"); + uiDefButI(block, MENU, B_POSELIB_APPLYP, menustr, xco, 85,18,20, &act->active_marker, 1, count, 0, 0, "Browses Poses in Pose Library. Applies chosen pose."); + MEM_freeN(menustr); + + if (act->active_marker) { + TimeMarker *marker= poselib_get_active_pose(act); + + but= uiDefBut(block, TEX, REDRAWBUTSEDIT,"", xco+18,85,160-18-20,20, marker->name, 0, 63, 0, 0, "Displays current Pose Library Pose name. Click to change."); + uiButSetFunc(but, verify_poselib_posename, act, marker); + uiDefIconBut(block, BUT, B_POSELIB_REMOVEP, VICON_X, xco+160-20, 85, 20, 20, NULL, 0.0, 0.0, 0.0, 0.0, "Remove this Pose Library Pose from Pose Library."); + } } /* add new poses */ @@ -5114,6 +5209,38 @@ static void editing_panel_links(Object *ob) uiDefBut(block, BUT, B_POSELIB_REPLACEP, "Replace Pose", xco+80,65,80,20, 0, 0, 0, 0, 0, "Replace existing PoseLib Pose with current pose"); uiBlockEndAlign(block); } + + + /* Action Groups settings for armature reside on the right */ + xco= 315; + + uiDefBut(block, LABEL,0, "Bone Groups:", xco, 154, 140, 20, 0, 0, 0, 0, 0, ""); + + /* add new group */ + uiDefBut(block, BUT, B_POSEGRP_ADD, "Add Group", xco,130,140,20, 0, 0, 0, 0, 0, "Add a new Pose Group for the Pose"); + + if (pose->agroups.first) { + uiBlockBeginAlign(block); + /* currently 'active' group - browse groups */ + count= BLI_countlist(&pose->agroups); + menustr= build_posegroups_menustr(pose); + uiDefButI(block, MENU, B_POSEGRP_RECALC, menustr, xco, 85,18,20, &pose->active_group, 1, count, 0, 0, "Browses Pose Groups available for Armature. Click to change."); + MEM_freeN(menustr); + + + if (pose->active_group) { + bActionGroup *grp= (bActionGroup *)BLI_findlink(&pose->agroups, pose->active_group-1); + + /* active group */ + but= uiDefBut(block, TEX, REDRAWBUTSEDIT,"", xco+18,85,140-18-20,20, grp->name, 0, 63, 0, 0, "Displays current Pose Group name. Click to change."); + uiButSetFunc(but, verify_posegroup_groupname, pose, grp); + uiDefIconBut(block, BUT, B_POSEGRP_REMOVE, VICON_X, xco+140-20, 85, 20, 20, NULL, 0.0, 0.0, 0.0, 0.0, "Remove this Pose Group"); + + /* set custom color set */ + uiDefButI(block, MENU,B_POSEGRP_RECALC, "Custom Color Set%t|GrpCol: [None]%x0", xco,65,140,19, &grp->customCol, 0.0, 0.0, 0.0, 0.0, "Set of Custom Colors to shade Group's bones with. (NOT YET FUNCTIONAL)"); + } + uiBlockEndAlign(block); + } } return; } diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index abc45e70183..384b88be1eb 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -2352,7 +2352,7 @@ static void group_ob_rem(void *gr_v, void *ob_v) Object *ob= OBACT; rem_from_group(gr_v, ob); - if(find_group(ob)==NULL) { + if(find_group(ob, NULL)==NULL) { ob->flag &= ~OB_FROMGROUP; BASACT->flag &= ~OB_FROMGROUP; } @@ -2496,19 +2496,25 @@ static void object_panel_anim(Object *ob) uiDefButI(block, NUM, REDRAWVIEW3D, "DupOn:", 170,85,146,19, &ob->dupon, 1.0, 1500.0, 0, 0, "Specify the number of frames to use between DupOff frames"); uiDefButI(block, NUM, REDRAWVIEW3D, "DupEnd", 24,65,140,19, &ob->dupend, 1.0, 32767, 0, 0, "Specify endframe for Dupliframes"); uiDefButI(block, NUM, REDRAWVIEW3D, "DupOff", 171,65,145,19, &ob->dupoff, 0.0, 1500.0, 0, 0, "Specify recurring frames to exclude from the Dupliframes"); - uiBlockBeginAlign(block); - uiDefButBitS(block, TOG, OB_OFFS_OB, REDRAWALL, "Offs Ob", 24,35,56,20, &ob->ipoflag, 0, 0, 0, 0, "Not functional at the moment!"); - uiDefButBitS(block, TOG, OB_OFFS_PARENT, REDRAWALL, "Offs Par", 82,35,56,20 , &ob->ipoflag, 0, 0, 0, 0, "Let the timeoffset work on the parent"); - uiDefButBitS(block, TOG, OB_OFFS_PARTICLE, REDRAWALL, "Offs Particle", 140,35,103,20, &ob->ipoflag, 0, 0, 0, 0, "Let the timeoffset work on the particle effect"); + uiBlockEndAlign(block); uiBlockBeginAlign(block); - uiDefButF(block, NUM, REDRAWALL, "TimeOffset:", 24,10,115,20, &ob->sf, -MAXFRAMEF, MAXFRAMEF, 100, 0, "Specify an offset in frames"); - uiDefBut(block, BUT, B_AUTOTIMEOFS, "Automatic Time", 139,10,104,20, 0, 0, 0, 0, 0, "Generate automatic timeoffset values for all selected frames"); - uiDefBut(block, BUT, B_PRINTSPEED, "PrSpeed", 248,10,67,20, 0, 0, 0, 0, 0, "Print objectspeed"); + uiDefButF(block, NUM, REDRAWALL, "TimeOffset:", 24,35,115,20, &ob->sf, -MAXFRAMEF, MAXFRAMEF, 100, 0, "Animation offset in frames for ipo's and dupligroup instances"); + uiDefBut(block, BUT, B_AUTOTIMEOFS, "Auto", 139,35,34,20, 0, 0, 0, 0, 0, "Assign selected objects a timeoffset within a range, starting from the active object"); + uiDefBut(block, BUT, B_OFSTIMEOFS, "Ofs", 173,35,34,20, 0, 0, 0, 0, 0, "Offset selected objects timeoffset"); + uiDefBut(block, BUT, B_RANDTIMEOFS, "Rand", 207,35,34,20, 0, 0, 0, 0, 0, "Randomize selected objects timeoffset"); + uiDefBut(block, BUT, B_PRINTSPEED, "PrSpeed", 250,35,65,20, 0, 0, 0, 0, 0, "Print objectspeed"); + uiBlockEndAlign(block); + + uiBlockBeginAlign(block); + uiDefButBitS(block, TOG, OB_OFFS_OB, REDRAWALL, "OfsEdit", 24,10,56,20, &ob->ipoflag, 0, 0, 0, 0, "Use timeoffset when inserting keys and display timeoffset for ipo and action views"); + uiDefButBitS(block, TOG, OB_OFFS_PARENT, REDRAWALL, "OfsParent", 82,10,56,20 , &ob->ipoflag, 0, 0, 0, 0, "Apply the timeoffset to this objects parent relationship"); + uiDefButBitS(block, TOG, OB_OFFS_PARTICLE, REDRAWALL, "OfsParticle", 140,10,56,20, &ob->ipoflag, 0, 0, 0, 0, "Let the timeoffset work on the particle effect"); + uiDefButBitS(block, TOG, OB_OFFS_PARENTADD, REDRAWALL, "AddParent", 196,10,56,20, &ob->ipoflag, 0, 0, 0, 0, "Add the parents timeoffset value"); uiBlockEndAlign(block); sprintf(str, "%.4f", prspeed); - uiDefBut(block, LABEL, 0, str, 247,35,63,31, NULL, 1.0, 0, 0, 0, ""); + uiDefBut(block, LABEL, 0, str, 260,10,63,31, NULL, 1.0, 0, 0, 0, ""); } @@ -2649,6 +2655,12 @@ void do_effects_panels(unsigned short event) case B_AUTOTIMEOFS: auto_timeoffs(); break; + case B_OFSTIMEOFS: + ofs_timeoffs(); + break; + case B_RANDTIMEOFS: + rand_timeoffs(); + break; case B_FRAMEMAP: G.scene->r.framelen= G.scene->r.framapto; G.scene->r.framelen/= G.scene->r.images; @@ -3451,15 +3463,18 @@ static void object_softbodies__enable_psys(void *ob_v, void *psys_v) #ifdef _work_on_sb_solver static char sbsolvers[] = "Solver %t|RKP almost SOFT not usable but for some german teachers %x1|STU ip semi implicit euler%x3|SI1 (half step)adaptive semi implict euler %x2|SI2 (use dv)adaptive semi implict euler %x4|SOFT step size controlled midpoint(1rst choice for real softbodies)%x0"; -#else +/* SIF would have been candidate .. well lack of time .. brecht is busy .. better make a stable version for peach now :) */ static char sbsolvers[] = "SIF semi implicit euler with fixed step size (worth a try with real stiff egdes)%x3|SOFT step size controlled midpoint(1rst choice for real softbodies)%x0"; +#else +static char sbsolvers[] = "SOFT step size controlled midpoint(1rst choice for real softbodies)%x0"; #endif + static void object_softbodies_II(Object *ob) { SoftBody *sb=ob->soft; uiBlock *block; static int val; - short *softflag=&ob->softflag, psys_cur=0,adaptive_mode; + short *softflag=&ob->softflag, psys_cur=0, adaptive_mode=0; int ob_has_hair=psys_ob_has_hair(ob); if(!_can_softbodies_at_all(ob)) return; /*bah that is ugly! creating missing data members in UI code*/ @@ -3546,6 +3561,7 @@ static void object_softbodies_II(Object *ob) uiBlockBeginAlign(block); uiDefButS(block, MENU, B_SOFTBODY_CHANGE, sbsolvers,10,100,50,20, &sb->solver_ID, 14.0, 0.0, 0, 0, "Select Solver"); /*some have adapive step size - some not*/ + sb->solver_ID = 0; /* ugly hack to prepare peach freeze */ switch (sb->solver_ID) { case 0: case 1: @@ -3998,9 +4014,13 @@ static void object_panel_particle_extra(Object *ob) buty=butx=160; uiDefButI(block, NUM, B_PART_DISTR, "Seed:", butx,(buty-=buth),butw,buth, &psys->seed, 0.0, 255.0, 1, 0, "Set an offset in the random table"); + if(part->type == PART_HAIR && psys->flag & PSYS_EDITED) + uiDefButF(block, NUM, B_PART_RECALC, "Stiff:", butx,(buty-=buth),butw,buth, &part->eff_hair, 0.0, 1.0, 0, 0, "Hair stiffness for effectors"); + else + buty-=buth; /* size changes must create a recalc event always so that sizes are updated properly */ - uiDefButF(block, NUM, B_PART_RECALC, "Size:", butx,(buty-=2*buth),butw,buth, &part->size, 0.01, 100, 10, 1, "The size of the particles"); + uiDefButF(block, NUM, B_PART_RECALC, "Size:", butx,(buty-=buth),butw,buth, &part->size, 0.01, 100, 10, 1, "The size of the particles"); uiDefButF(block, NUM, B_PART_RECALC, "Rand:", butx,(buty-=buth),butw,buth, &part->randsize, 0.0, 2.0, 10, 1, "Give the particle size a random variation"); uiDefButBitI(block, TOG, PART_SIZEMASS, B_PART_RECALC, "Mass from size", butx,(buty-=buth),butw,buth, &part->flag, 0, 0, 0, 0, "Multiply mass with particle size"); diff --git a/source/blender/src/buttons_scene.c b/source/blender/src/buttons_scene.c index dda48a298ff..c3209dfa814 100644 --- a/source/blender/src/buttons_scene.c +++ b/source/blender/src/buttons_scene.c @@ -578,27 +578,34 @@ static void seq_panel_editing() B_SEQ_BUT_TRANSFORM, "Chan", 130, 80, 120, 20, &last_seq->machine, 0.0, MAXSEQ, 0.0, 0.0, "Channel used (Y position)"); - - if (last_seq->type == SEQ_IMAGE) { + + if (check_single_seq(last_seq)) { uiDefButI(block, NUM, - B_SEQ_BUT_TRANSFORM, "Start-Still", - 10, 60, 120, 20, &last_seq->startstill, - 0.0, MAXFRAMEF, 0.0, 0.0, "Start still"); - uiDefButI(block, NUM, - B_SEQ_BUT_TRANSFORM, "End-Still", - 130, 60, 120, 19, &last_seq->endstill, - 0.0, MAXFRAMEF, 0.0, 0.0, "End still"); + B_SEQ_BUT_TRANSFORM, "End-Still", + 130, 60, 120, 19, &last_seq->endstill, + 0.0, MAXFRAMEF, 0.0, 0.0, "End still"); } else { - uiDefButI(block, NUM, - B_SEQ_BUT_TRANSFORM, "Start-Ofs", - 10, 60, 120, 20, &last_seq->startofs, - 0.0, last_seq->len - last_seq->endofs, - 0.0, 0.0, "Start offset"); - uiDefButI(block, NUM, - B_SEQ_BUT_TRANSFORM, "End-Ofs", - 130, 60, 120, 19, &last_seq->endofs, - 0.0, last_seq->len - last_seq->startofs, - 0.0, 0.0, "End offset"); + if (last_seq->type == SEQ_IMAGE) { + uiDefButI(block, NUM, + B_SEQ_BUT_TRANSFORM, "Start-Still", + 10, 60, 120, 20, &last_seq->startstill, + 0.0, MAXFRAMEF, 0.0, 0.0, "Start still"); + uiDefButI(block, NUM, + B_SEQ_BUT_TRANSFORM, "End-Still", + 130, 60, 120, 19, &last_seq->endstill, + 0.0, MAXFRAMEF, 0.0, 0.0, "End still"); + } else { + uiDefButI(block, NUM, + B_SEQ_BUT_TRANSFORM, "Start-Ofs", + 10, 60, 120, 20, &last_seq->startofs, + 0.0, last_seq->len - last_seq->endofs, + 0.0, 0.0, "Start offset"); + uiDefButI(block, NUM, + B_SEQ_BUT_TRANSFORM, "End-Ofs", + 130, 60, 120, 19, &last_seq->endofs, + 0.0, last_seq->len - last_seq->startofs, + 0.0, 0.0, "End offset"); + } } } @@ -1121,6 +1128,8 @@ void do_sequencer_panels(unsigned short event) break; case B_SEQ_BUT_TRANSFORM: calc_sequence(last_seq); + if (test_overlap_seq(last_seq)) + shuffle_seq(last_seq); break; } @@ -1156,12 +1165,6 @@ static void backbuf_pic(char *name) BIF_undo_push("Change background picture"); } -static void ftype_pic(char *name) -{ - strcpy(G.scene->r.ftype, name); - allqueue(REDRAWBUTSSCENE, 0); -} - static void run_playanim(char *file) { extern char bprogname[]; /* usiblender.c */ @@ -1260,15 +1263,6 @@ void do_render_panels(unsigned short event) else activate_fileselect(FILE_SPECIAL, "SELECT BACKBUF PICTURE", G.scene->r.backbuf, backbuf_pic); break; - - case B_FS_FTYPE: - sa= closest_bigger_area(); - areawinset(sa->win); - if(G.qual == LR_CTRLKEY) - activate_imageselect(FILE_SPECIAL, "SELECT FTYPE", G.scene->r.ftype, ftype_pic); - else - activate_fileselect(FILE_SPECIAL, "SELECT FTYPE", G.scene->r.ftype, ftype_pic); - break; case B_PR_PAL: G.scene->r.xsch= 720; @@ -1832,7 +1826,6 @@ static void render_panel_output(void) uiBlock *block; char *strp; - block= uiNewBlock(&curarea->uiblocks, "render_panel_output", UI_EMBOSS, UI_HELV, curarea->win); if(uiNewPanel(curarea, block, "Output", "Render", 0, 0, 318, 204)==0) return; @@ -1841,17 +1834,19 @@ static void render_panel_output(void) uiDefBut(block, TEX,0,"", 31, 190, 279, 20,G.scene->r.pic, 0.0,79.0, 0, 0, "Directory/name to save rendered Pics to"); uiDefIconBut(block, BUT,B_FS_BACKBUF, ICON_FILESEL, 10, 168, 20, 20, 0, 0, 0, 0, 0, "Open Fileselect to get Backbuf image"); uiDefBut(block, TEX,0,"", 31, 168, 279, 20,G.scene->r.backbuf, 0.0,79.0, 0, 0, "Image to use as background for rendering"); - uiDefIconBut(block, BUT,B_FS_FTYPE, ICON_FILESEL, 10, 146, 20, 20, 0, 0, 0, 0, 0, "Open Fileselect to get Ftype image"); - uiDefBut(block, TEX,0,"", 31, 146, 279, 20,G.scene->r.ftype,0.0,79.0, 0, 0, "Image to use with FTYPE Image type"); uiBlockEndAlign(block); + uiBlockBeginAlign(block); + uiDefButBitI(block, TOG, R_NO_OVERWRITE, B_NOP, "No Overwrite", 10, 142, 90, 20, &G.scene->r.mode, 0.0, 0.0, 0, 0, "Skip rendering frames when the file exists (image output only)"); + uiDefButBitI(block, TOG, R_TOUCH, B_NOP, "Touch", 100, 142, 50, 20, &G.scene->r.mode, 0.0, 0.0, 0, 0, "Create an empty file before rendering each frame"); + uiBlockEndAlign(block); /* SET BUTTON */ uiBlockBeginAlign(block); id= (ID *)G.scene->set; IDnames_to_pupstring(&strp, NULL, NULL, &(G.main->scene), id, &(G.buts->menunr)); if(strp[0]) - uiDefButS(block, MENU, B_SETBROWSE, strp, 10, 120, 20, 20, &(G.buts->menunr), 0, 0, 0, 0, "Scene to link as a Set"); + uiDefButS(block, MENU, B_SETBROWSE, strp, 10, 114, 20, 20, &(G.buts->menunr), 0, 0, 0, 0, "Scene to link as a Set"); MEM_freeN(strp); if(G.scene->set) { @@ -1863,8 +1858,8 @@ static void render_panel_output(void) uiBlockEndAlign(block); uiBlockSetCol(block, TH_BUT_SETTING1); - uiDefButBitS(block, TOG, R_BACKBUF, B_NOP,"Backbuf", 10, 94, 80, 20, &G.scene->r.bufflag, 0, 0, 0, 0, "Enable/Disable use of Backbuf image"); - uiDefButS(block, NUM, B_NOP, "Threads:", 10, 68, 100, 20, &G.scene->r.threads, 1, BLENDER_MAX_THREADS, 0, 0, "Amount of threads for render (takes advantage of multi-core and multi-processor computers)"); + uiDefButBitS(block, TOG, R_BACKBUF, B_NOP,"Backbuf", 10, 89, 80, 20, &G.scene->r.bufflag, 0, 0, 0, 0, "Enable/Disable use of Backbuf image"); + uiDefButS(block, NUM, B_NOP, "Threads:", 10, 63, 100, 20, &G.scene->r.threads, 1, BLENDER_MAX_THREADS, 0, 0, "Amount of threads for render (takes advantage of multi-core and multi-processor computers)"); uiBlockSetCol(block, TH_AUTO); uiBlockBeginAlign(block); @@ -1878,20 +1873,18 @@ static void render_panel_output(void) uiDefButS(block, MENU, B_REDR, "Render Display %t|Render Window %x1|Image Editor %x0|Full Screen %x2", 72, 10, 120, 19, &G.displaymode, 0.0, (float)R_DISPLAYWIN, 0, 0, "Sets render output display"); - uiDefButBitS(block, TOG, R_EXTENSION, B_NOP, "Extensions", 205, 10, 105, 19, &G.scene->r.scemode, 0.0, 0.0, 0, 0, "Adds filetype extensions to the filename when rendering animations"); - /* Dither control */ uiDefButF(block, NUM,B_DIFF, "Dither:", 205,31,105,19, &G.scene->r.dither_intensity, 0.0, 2.0, 0, 0, "The amount of dithering noise present in the output image (0.0 = no dithering)"); /* Toon shading buttons */ uiBlockBeginAlign(block); - uiDefButBitI(block, TOG, R_EDGE, B_NOP,"Edge", 100, 94, 70, 20, &G.scene->r.mode, 0, 0, 0, 0, "Enable Toon Edge-enhance"); - uiDefBlockBut(block, edge_render_menu, NULL, "Edge Settings", 170, 94, 140, 20, "Display Edge settings"); + uiDefButBitI(block, TOG, R_EDGE, B_NOP,"Edge", 100, 89, 70, 20, &G.scene->r.mode, 0, 0, 0, 0, "Enable Toon Edge-enhance"); + uiDefBlockBut(block, edge_render_menu, NULL, "Edge Settings", 170, 89, 140, 20, "Display Edge settings"); uiBlockEndAlign(block); uiBlockBeginAlign(block); - uiDefButBitS(block, TOG, R_NO_TEX, B_NOP, "Disable Tex", 115, 68, 70, 20, &G.scene->r.scemode, 0.0, 0.0, 0, 0, "Disables Textures for render"); - uiDefButBitS(block, TOG, R_FREE_IMAGE, B_NOP, "Free Tex Images", 205, 68, 100, 20, &G.scene->r.scemode, 0.0, 0.0, 0, 0, "Frees all Images used by Textures after each render"); + uiDefButBitS(block, TOG, R_NO_TEX, B_NOP, "Disable Tex", 115, 63, 70, 20, &G.scene->r.scemode, 0.0, 0.0, 0, 0, "Disables Textures for render"); + uiDefButBitS(block, TOG, R_FREE_IMAGE, B_NOP, "Free Tex Images", 205, 63, 100, 20, &G.scene->r.scemode, 0.0, 0.0, 0, 0, "Frees all Images used by Textures after each render"); uiBlockEndAlign(block); } @@ -2650,7 +2643,8 @@ static void render_panel_layers(void) uiDefButBitI(block, TOG, SCE_PASS_VECTOR, B_SET_PASS,"Vec", 120, 30, 40, 20, &srl->passflag, 0, 0, 0, 0, "Deliver Speed Vector pass"); uiDefButBitI(block, TOG, SCE_PASS_NORMAL, B_SET_PASS,"Nor", 160, 30, 40, 20, &srl->passflag, 0, 0, 0, 0, "Deliver Normal pass"); uiDefButBitI(block, TOG, SCE_PASS_UV, B_SET_PASS,"UV", 200, 30, 40, 20, &srl->passflag, 0, 0, 0, 0, "Deliver Texture UV pass"); - uiDefButBitI(block, TOG, SCE_PASS_INDEXOB, B_SET_PASS,"IndexOb",240, 30, 70, 20, &srl->passflag, 0, 0, 0, 0, "Deliver Object Index pass"); + uiDefButBitI(block, TOG, SCE_PASS_MIST, B_SET_PASS,"Mist", 240, 30, 35, 20, &srl->passflag, 0, 0, 0, 0, "Deliver Mist factor pass (0-1)"); + uiDefButBitI(block, TOG, SCE_PASS_INDEXOB, B_SET_PASS,"Index", 275, 30, 35, 20, &srl->passflag, 0, 0, 0, 0, "Deliver Object Index pass"); uiDefButBitI(block, TOG, SCE_PASS_RGBA, B_SET_PASS,"Col", 10, 10, 35, 20, &srl->passflag, 0, 0, 0, 0, "Deliver shade-less Color pass"); uiDefButBitI(block, TOG, SCE_PASS_DIFFUSE, B_SET_PASS,"Diff", 45, 10, 35, 20, &srl->passflag, 0, 0, 0, 0, "Deliver Diffuse pass"); diff --git a/source/blender/src/buttons_shading.c b/source/blender/src/buttons_shading.c index 4eef6b29599..2ac76942da7 100644 --- a/source/blender/src/buttons_shading.c +++ b/source/blender/src/buttons_shading.c @@ -748,8 +748,7 @@ static char *layer_menu(RenderResult *rr, short *curlay) a+= sprintf(str+a, "|%s %%x%d", rl->name, nr); } - if(*curlay >= nr) - *curlay= 0; + /* no curlay clip here, on render (redraws) the amount of layers can be 1 fir single-layer render */ return str; } @@ -2153,18 +2152,27 @@ static void world_panel_amb_occ(World *wrld) uiBlockSetCol(block, TH_AUTO); if(!(wrld->mode & WO_AMB_OCC)) return; - - yco -= YSPACE; - - uiDefButS(block, NUM, B_REDR, "Samples:", - X2CLM1, yco-=BUTH, BUTW2, BUTH, &wrld->aosamp, 1.0, 32.0, 100, 0, "Sets the number of samples used for AO (actual number: squared)"); - - yco -= YSPACE; - - uiDefButF(block, NUM, B_REDR, "Max Dist:", - X2CLM1, yco-=BUTH, BUTW2, BUTH, &wrld->aodist, 0.001, 5000.0, 100, 0, "Sets length of AO rays, defines how far away other faces give occlusion effect"); yco -= YSPACE; + + if(wrld->ao_gather_method == WO_AOGATHER_RAYTRACE) { + uiDefButS(block, NUM, B_REDR, "Samples:", + X2CLM1, yco-=BUTH, BUTW2, BUTH, &wrld->aosamp, 1.0, 32.0, 100, 0, "Sets the number of samples used for AO (actual number: squared)"); + + yco -= YSPACE; + + uiDefButF(block, NUM, B_REDR, "Max Dist:", + X2CLM1, yco-=BUTH, BUTW2, BUTH, &wrld->aodist, 0.001, 5000.0, 100, 0, "Sets length of AO rays, defines how far away other faces give occlusion effect"); + } + else { + uiDefButS(block, NUM, B_REDR, "Passes:", + X2CLM1, yco-=BUTH, BUTW2, BUTH, &wrld->ao_approx_passes, 0.0, 10.0, 0, 0, "Sets the number of preprocessing passes to reduce overocclusion"); + + yco -= YSPACE; + + uiDefButF(block, NUM, B_REDR, "Correction:", + X2CLM1, yco-=BUTH, BUTW2, BUTH, &wrld->ao_approx_correction, 0.0, 1.0, 0, 0, "Ad-hoc correction for over-occlusion due to the approximation."); + } uiBlockBeginAlign(block); uiDefButBitS(block, TOG, WO_AODIST, B_AO_FALLOFF, "Use Falloff", @@ -2177,23 +2185,38 @@ static void world_panel_amb_occ(World *wrld) /* column 2 */ yco = PANEL_YMAX - BUTH - YSPACE; - uiDefButS(block, MENU, B_REDR, "Constant QMC %x2|Adaptive QMC %x1|Constant Jittered %x0", - X2CLM2, yco-=BUTH, BUTW2, BUTH, &wrld->ao_samp_method, 0, 0, 0, 0, "Method for generating shadow samples: Constant QMC: best quality, Adaptive QMC: fast in high contrast areas"); - - yco -= YSPACE; - - if (wrld->ao_samp_method == WO_AOSAMP_HALTON) { - uiBlockBeginAlign(block); - uiDefButF(block, NUM, B_REDR, "Threshold:", - X2CLM2, yco-=BUTH, BUTW2, BUTH, &wrld->ao_adapt_thresh, 0.0, 1.0, 100, 0, "Samples below this threshold will be considered fully shadowed/unshadowed and skipped"); - uiDefButF(block, NUMSLI, B_REDR, "Adapt Vec:", - X2CLM2, yco-=BUTH, BUTW2, BUTH, &wrld->ao_adapt_speed_fac, 0.0, 1.0, 100, 0, "Use the speed vector pass to reduce AO samples in fast moving pixels. The higher the value, the more aggressive the sample reduction. Requires Vec pass enabled."); - uiBlockEndAlign(block); - } else if (wrld->ao_samp_method == WO_AOSAMP_CONSTANT) { - uiDefButF(block, NUMSLI, B_REDR, "Bias:", - X2CLM2, yco-=BUTH, BUTW2, BUTH, &wrld->aobias, 0.0, 0.5, 10, 0, "Sets bias to prevent smoothed faces to show banding (in radians)"); - } + uiDefButS(block, MENU, B_REDR, "Gather Method%t|Raytrace %x0|Approximate %x1", + X2CLM2, yco-=BUTH, BUTW2, BUTH, &wrld->ao_gather_method, 0, 0, 0, 0, "Method for occlusion gathering: Raytrace: slow when noise free results are required, but accurate, Approximate: faster and without noise, but inaccurate"); + yco -= YSPACE; + + if(wrld->ao_gather_method == WO_AOGATHER_RAYTRACE) { + uiDefButS(block, MENU, B_REDR, "Constant QMC %x2|Adaptive QMC %x1|Constant Jittered %x0", + X2CLM2, yco-=BUTH, BUTW2, BUTH, &wrld->ao_samp_method, 0, 0, 0, 0, "Method for generating shadow samples: Constant QMC: best quality, Adaptive QMC: fast in high contrast areas"); + + yco -= YSPACE; + + if (wrld->ao_samp_method == WO_AOSAMP_HALTON) { + uiBlockBeginAlign(block); + uiDefButF(block, NUM, B_REDR, "Threshold:", + X2CLM2, yco-=BUTH, BUTW2, BUTH, &wrld->ao_adapt_thresh, 0.0, 1.0, 100, 0, "Samples below this threshold will be considered fully shadowed/unshadowed and skipped"); + uiDefButF(block, NUMSLI, B_REDR, "Adapt Vec:", + X2CLM2, yco-=BUTH, BUTW2, BUTH, &wrld->ao_adapt_speed_fac, 0.0, 1.0, 100, 0, "Use the speed vector pass to reduce AO samples in fast moving pixels. The higher the value, the more aggressive the sample reduction. Requires Vec pass enabled."); + uiBlockEndAlign(block); + } else if (wrld->ao_samp_method == WO_AOSAMP_CONSTANT) { + uiDefButF(block, NUMSLI, B_REDR, "Bias:", + X2CLM2, yco-=BUTH, BUTW2, BUTH, &wrld->aobias, 0.0, 0.5, 10, 0, "Sets bias to prevent smoothed faces to show banding (in radians)"); + } + } + else { + uiBlockBeginAlign(block); + uiDefButF(block, NUM, B_REDR, "Error:", + X2CLM2, yco-=BUTH, BUTW2, BUTH, &wrld->ao_approx_error, 0.0001, 10.0, 0, 0, "Error tolerance (low values are slower and higher quality)"); + + uiDefButBitS(block, TOG, WO_AOCACHE, B_REDR, "Pixel Cache", + X2CLM2, yco-=BUTH, BUTW2, BUTH, &wrld->aomode, 0, 0, 0, 0, "Cache AO results in pixels and interpolate over neighbouring pixels for speedup."); + uiBlockEndAlign(block); + } yco = PANEL_YMAX - (5*BUTH+4*YSPACE); @@ -2205,6 +2228,7 @@ static void world_panel_amb_occ(World *wrld) X3CLM2, yco, BUTW3, BUTH, &wrld->aomix, 1.0, (float)WO_AOSUB, 0, 0, "subtracts light/shadows (needs at least one normal light to make anything visible)"); uiDefButS(block, ROW, B_REDR, "Both", X3CLM3, yco, BUTW3, BUTH, &wrld->aomix, 1.0, (float)WO_AOADDSUB, 0, 0, "both lightens & darkens"); + uiBlockEndAlign(block); yco -= YSPACE; @@ -2217,12 +2241,11 @@ static void world_panel_amb_occ(World *wrld) uiDefButS(block, ROW, B_REDR, "Sky Texture", X3CLM3, yco, BUTW3, BUTH, &wrld->aocolor, 2.0, (float)WO_AOSKYTEX, 0, 0, "Does full Sky texture render for diffuse energy"); uiBlockEndAlign(block); - + yco -= YSPACE; - + uiDefButF(block, NUMSLI, B_REDR, "Energy:", X2CLM1, yco-=BUTH, BUTW2, BUTH, &wrld->aoenergy, 0.01, 3.0, 100, 0, "Sets global energy scale for AO"); - } static void world_panel_world(World *wrld) @@ -3715,7 +3738,7 @@ static void material_panel_shading(Material *ma) uiBlock *block; block= uiNewBlock(&curarea->uiblocks, "material_panel_shading", UI_EMBOSS, UI_HELV, curarea->win); - if(uiNewPanel(curarea, block, "Shaders", "Material", 640, 0, 318, 204)==0) return; + if(uiNewPanel(curarea, block, "Shaders", "Material", 640, 0, 318, 224)==0) return; uiSetButLock(ma->id.lib!=NULL, ERROR_LIBDATA_MESSAGE); @@ -3793,6 +3816,7 @@ static void material_panel_shading(Material *ma) uiDefButF(block, NUMSLI, B_MATPRV, "SBias ", 159,30,151,19, &(ma->sbias), 0.0, 0.25, 10, 2, "Shadow bias, to prevent terminator problems on shadow boundary"); uiDefButF(block, NUMSLI, B_MATPRV, "Amb ", 9,10,150,19, &(ma->amb), 0.0, 1.0, 0, 0, "Sets the amount of global ambient color the material receives"); uiDefButF(block, NUMSLI, B_MATPRV, "Emit ", 159,10,151,19, &(ma->emit), 0.0, 2.0, 0, 0, "Sets the amount of light the material emits"); + uiDefButF(block, NUMSLI, B_MATPRV, "LBias ", 9,-10,300,19, &(ma->lbias), 0.0, 10.0, 100, 2, "Factor to multiply shadowbuffer bias with (0 is ignore)"); uiBlockEndAlign(block); uiBlockSetCol(block, TH_BUT_SETTING1); @@ -3807,7 +3831,9 @@ static void material_panel_shading(Material *ma) uiBlockBeginAlign(block); uiDefIDPoinBut(block, test_grouppoin_but, ID_GR, B_MATPRV, "GR:", 9, 55, 150, 19, &ma->group, "Limit Lighting to Lamps in this Group"); - uiDefButBitI(block, TOG, MA_GROUP_NOLAY, B_MATPRV, "Exclusive", 159,55, 85,20, &(ma->mode), 0, 0, 0, 0, "The material exclusively uses Lamps in this Group"); + uiDefButBitI(block, TOG, MA_GROUP_NOLAY, B_MATPRV, "Exclusive", 159,55, 85,20, &(ma->mode), 0, 0, 0, 0, "Material uses Lights in this group exclusively, they get excluded from the Scene lighting"); + + } } diff --git a/source/blender/src/drawaction.c b/source/blender/src/drawaction.c index 05a50fe4f16..a169af6cf93 100644 --- a/source/blender/src/drawaction.c +++ b/source/blender/src/drawaction.c @@ -64,6 +64,7 @@ #include "BKE_depsgraph.h" #include "BKE_ipo.h" #include "BKE_key.h" +#include "BKE_object.h" #include "BKE_global.h" #include "BKE_utildefines.h" @@ -94,6 +95,7 @@ /* 'old' stuff": defines and types, and own include -------------------- */ #include "blendef.h" +#include "interface.h" #include "mydevice.h" /********************************** Slider Stuff **************************** */ @@ -373,8 +375,8 @@ void draw_cfra_action (void) /* Draw dark green line if slow-parenting/time-offset is enabled */ ob= (G.scene->basact) ? (G.scene->basact->object) : 0; - if ((ob) && (ob->sf!=0.0) && (ob->ipoflag & OB_OFFS_OB)) { - vec[0]-= ob->sf; + if ((ob) && (ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)!=0.0)) { + vec[0]-= give_timeoffset(ob); /* could avoid calling twice */ BIF_ThemeColorShade(TH_CFRAME, -30); @@ -406,7 +408,7 @@ static void draw_channel_names(void) if (data == NULL) return; /* Clip to the scrollable area */ - if(curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) { + if (curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) { if(G.v2d->scroll) { ofsx= curarea->winrct.xmin; ofsy= curarea->winrct.ymin; @@ -434,16 +436,39 @@ static void draw_channel_names(void) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); for (ale= act_data.first; ale; ale= ale->next) { - short indent= 0, offset= 0, sel= 0; + short indent= 0, offset= 0, sel= 0, group=0; int expand= -1, protect = -1, special= -1, mute = -1; char name[32]; /* determine what needs to be drawn */ switch (ale->type) { + case ACTTYPE_GROUP: /* action group */ + { + bActionGroup *agrp= (bActionGroup *)ale->data; + + group= 2; + indent= 0; + special= -1; + + if (EXPANDED_AGRP(agrp)) + expand = ICON_TRIA_DOWN; + else + expand = ICON_TRIA_RIGHT; + + if (EDITABLE_AGRP(agrp)) + protect = ICON_UNLOCKED; + else + protect = ICON_LOCKED; + + sel = SEL_AGRP(agrp); + sprintf(name, agrp->name); + } + break; case ACTTYPE_ACHAN: /* action channel */ { bActionChannel *achan= (bActionChannel *)ale->data; + group= (ale->grp) ? 1 : 0; indent = 0; special = -1; @@ -473,6 +498,7 @@ static void draw_channel_names(void) bConstraintChannel *conchan = (bConstraintChannel *)ale->data; indent = 2; + group= (ale->grp) ? 1 : 0; if (EDITABLE_CONCHAN(conchan)) protect = ICON_UNLOCKED; @@ -496,6 +522,7 @@ static void draw_channel_names(void) indent = 2; protect = -1; // for now, until this can be supported by others + group= (ale->grp) ? 1 : 0; if (icu->flag & IPO_MUTE) mute = ICON_MUTE_IPO_ON; @@ -528,6 +555,7 @@ static void draw_channel_names(void) indent = 1; special = geticon_ipo_blocktype(achan->ipo->blocktype); + group= (ale->grp) ? 1 : 0; if (FILTER_IPO_ACHAN(achan)) expand = ICON_TRIA_DOWN; @@ -544,6 +572,7 @@ static void draw_channel_names(void) indent = 1; special = ICON_CONSTRAINT; + group= (ale->grp) ? 1 : 0; if (FILTER_CON_ACHAN(achan)) expand = ICON_TRIA_DOWN; @@ -558,9 +587,24 @@ static void draw_channel_names(void) /* now, start drawing based on this information */ /* draw backing strip behind channel name */ - BIF_ThemeColorShade(TH_HEADER, ((indent==0)?20: (indent==1)?-20: -40)); - offset = 7 * indent; - glRectf(x+offset, y-CHANNELHEIGHT/2, (float)NAMEWIDTH, y+CHANNELHEIGHT/2); + if (group == 2) { + /* only for group-channels */ + if (ale->flag & AGRP_ACTIVE) + BIF_ThemeColorShade(TH_GROUP_ACTIVE, 10); + else + BIF_ThemeColorShade(TH_GROUP, 20); + uiSetRoundBox((expand == ICON_TRIA_DOWN)? (1):(1|8)); + gl_round_box(GL_POLYGON, x, y-CHANNELHEIGHT/2, (float)NAMEWIDTH, y+CHANNELHEIGHT/2, 8); + + offset = 0; + } + else { + /* for normal channels */ + BIF_ThemeColorShade(TH_HEADER, ((indent==0)?20: (indent==1)?-20: -40)); + indent += group; + offset = 7 * indent; + glRectf(x+offset, y-CHANNELHEIGHT/2, (float)NAMEWIDTH, y+CHANNELHEIGHT/2); + } /* draw expand/collapse triangle */ if (expand > 0) { @@ -572,7 +616,7 @@ static void draw_channel_names(void) * only for expand widgets for Ipo and Constraint Channels */ if (special > 0) { - offset = 24; + offset = (group) ? 29 : 24; BIF_icon_draw(x+offset, y-CHANNELHEIGHT/2, special); offset += 17; } @@ -652,9 +696,12 @@ static void draw_channel_strips(void) float y, sta, end; int act_start, act_end, dummy; char col1[3], col2[3]; + char col1a[3], col2a[3]; BIF_GetThemeColor3ubv(TH_SHADE2, col2); BIF_GetThemeColor3ubv(TH_HILITE, col1); + BIF_GetThemeColor3ubv(TH_GROUP, col2a); + BIF_GetThemeColor3ubv(TH_GROUP_ACTIVE, col1a); /* get editor data */ data= get_action_context(&datatype); @@ -694,6 +741,12 @@ static void draw_channel_strips(void) if (ale->datatype != ALE_NONE) { /* determine if channel is selected */ switch (ale->type) { + case ACTTYPE_GROUP: + { + bActionGroup *agrp = (bActionGroup *)ale->data; + sel = SEL_AGRP(agrp); + } + break; case ACTTYPE_ACHAN: { bActionChannel *achan = (bActionChannel *)ale->data; @@ -717,12 +770,24 @@ static void draw_channel_strips(void) if (datatype == ACTCONT_ACTION) { gla2DDrawTranslatePt(di, G.v2d->cur.xmin, y, &frame1_x, &channel_y); - if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x22); - else glColor4ub(col2[0], col2[1], col2[2], 0x22); + if (ale->datatype == ALE_GROUP) { + if (sel) glColor4ub(col1a[0], col1a[1], col1a[2], 0x22); + else glColor4ub(col2a[0], col2a[1], col2a[2], 0x22); + } + else { + if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x22); + else glColor4ub(col2[0], col2[1], col2[2], 0x22); + } glRectf(frame1_x, channel_y-CHANNELHEIGHT/2, G.v2d->hor.xmax, channel_y+CHANNELHEIGHT/2); - if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x22); - else glColor4ub(col2[0], col2[1], col2[2], 0x22); + if (ale->datatype == ALE_GROUP) { + if (sel) glColor4ub(col1a[0], col1a[1], col1a[2], 0x22); + else glColor4ub(col2a[0], col2a[1], col2a[2], 0x22); + } + else { + if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x22); + else glColor4ub(col2[0], col2[1], col2[2], 0x22); + } glRectf(act_start, channel_y-CHANNELHEIGHT/2, act_end, channel_y+CHANNELHEIGHT/2); } else if (datatype == ACTCONT_SHAPEKEY) { @@ -752,6 +817,9 @@ static void draw_channel_strips(void) y = 0.0; for (ale= act_data.first; ale; ale= ale->next) { switch (ale->datatype) { + case ALE_GROUP: + draw_agroup_channel(di, ale->data, y); + break; case ALE_IPO: draw_ipo_channel(di, ale->key_data, y); break; @@ -1196,6 +1264,17 @@ void draw_icu_channel(gla2DDrawInfo *di, IpoCurve *icu, float ypos) BLI_freelistN(&blocks); } +void draw_agroup_channel(gla2DDrawInfo *di, bActionGroup *agrp, float ypos) +{ + ListBase keys = {0, 0}; + ListBase blocks = {0, 0}; + + agroup_to_keylist(agrp, &keys, &blocks); + draw_keylist(di, &keys, &blocks, ypos); + BLI_freelistN(&keys); + BLI_freelistN(&blocks); +} + void draw_action_channel(gla2DDrawInfo *di, bAction *act, float ypos) { ListBase keys = {0, 0}; @@ -1273,6 +1352,27 @@ void ipo_to_keylist(Ipo *ipo, ListBase *keys, ListBase *blocks) } } +void agroup_to_keylist(bActionGroup *agrp, ListBase *keys, ListBase *blocks) +{ + bActionChannel *achan; + bConstraintChannel *conchan; + + if (agrp) { + /* loop through action channels */ + for (achan= agrp->channels.first; achan && achan!=agrp->channels.last; achan= achan->next) { + /* firstly, add keys from action channel's ipo block */ + if (achan->ipo) + ipo_to_keylist(achan->ipo, keys, blocks); + + /* then, add keys from constraint channels */ + for (conchan= achan->constraintChannels.first; conchan; conchan= conchan->next) { + if (conchan->ipo) + ipo_to_keylist(conchan->ipo, keys, blocks); + } + } + } +} + void action_to_keylist(bAction *act, ListBase *keys, ListBase *blocks) { bActionChannel *achan; @@ -1288,7 +1388,7 @@ void action_to_keylist(bAction *act, ListBase *keys, ListBase *blocks) /* then, add keys from constraint channels */ for (conchan= achan->constraintChannels.first; conchan; conchan= conchan->next) { if (conchan->ipo) - ipo_to_keylist(achan->ipo, keys, blocks); + ipo_to_keylist(conchan->ipo, keys, blocks); } } } diff --git a/source/blender/src/drawarmature.c b/source/blender/src/drawarmature.c index 9ec688b5d8d..3e08910abfe 100644 --- a/source/blender/src/drawarmature.c +++ b/source/blender/src/drawarmature.c @@ -2015,8 +2015,7 @@ static void draw_ghost_poses_range(Base *base) if (G.vd->zbuf) glEnable(GL_DEPTH_TEST); ghost_poses_tag_unselected(ob, 1); /* unhide unselected bones if need be */ - free_pose_channels(posen); - MEM_freeN(posen); + free_pose(posen); /* restore */ CFRA= cfrao; @@ -2092,9 +2091,8 @@ static void draw_ghost_poses_keys(Base *base) if (G.vd->zbuf) glEnable(GL_DEPTH_TEST); ghost_poses_tag_unselected(ob, 1); /* unhide unselected bones if need be */ - free_pose_channels(posen); BLI_freelistN(&keys); - MEM_freeN(posen); + free_pose(posen); /* restore */ CFRA= cfrao; @@ -2193,8 +2191,7 @@ static void draw_ghost_poses(Base *base) if (G.vd->zbuf) glEnable(GL_DEPTH_TEST); ghost_poses_tag_unselected(ob, 1); /* unhide unselected bones if need be */ - free_pose_channels(posen); - MEM_freeN(posen); + free_pose(posen); /* restore */ CFRA= cfrao; diff --git a/source/blender/src/drawipo.c b/source/blender/src/drawipo.c index 07442a541a5..6a1744dccac 100644 --- a/source/blender/src/drawipo.c +++ b/source/blender/src/drawipo.c @@ -65,6 +65,7 @@ #include "BKE_global.h" #include "BKE_ipo.h" #include "BKE_key.h" +#include "BKE_object.h" #include "BKE_utildefines.h" #include "BIF_cursors.h" @@ -1571,8 +1572,8 @@ static void draw_cfra(SpaceIpo *sipo) if(sipo->blocktype==ID_OB) { ob= (G.scene->basact) ? (G.scene->basact->object) : 0; - if (ob && (ob->sf!=0.0) && (ob->ipoflag & OB_OFFS_OB) ) { - vec[0]-= ob->sf; + if (ob && (ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)!=0.0)) { + vec[0]-= give_timeoffset(ob); BIF_ThemeColorShade(TH_HILITE, -30); diff --git a/source/blender/src/drawnode.c b/source/blender/src/drawnode.c index cca13671017..3e93b46c1cb 100644 --- a/source/blender/src/drawnode.c +++ b/source/blender/src/drawnode.c @@ -694,13 +694,13 @@ static int node_shader_buts_geometry(uiBlock *block, bNodeTree *ntree, bNode *no NodeGeometry *ngeo= (NodeGeometry*)node->storage; if(!verify_valid_uv_name(ngeo->uvname)) - uiBlockSetCol(block, TH_REDALERT); + uiBlockSetCol(block, TH_REDALERT); but= uiDefBut(block, TEX, B_NODE_EXEC+node->nr, "UV:", butr->xmin, butr->ymin+20, butr->xmax-butr->xmin, 20, ngeo->uvname, 0, 31, 0, 0, "Set name of UV layer to use, default is active UV layer"); uiButSetCompleteFunc(but, autocomplete_uv, NULL); uiBlockSetCol(block, TH_AUTO); if(!verify_valid_vcol_name(ngeo->colname)) - uiBlockSetCol(block, TH_REDALERT); + uiBlockSetCol(block, TH_REDALERT); but= uiDefBut(block, TEX, B_NODE_EXEC+node->nr, "Col:", butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, ngeo->colname, 0, 31, 0, 0, "Set name of vertex color layer to use, default is active vertex color layer"); uiButSetCompleteFunc(but, autocomplete_vcol, NULL); uiBlockSetCol(block, TH_AUTO); @@ -1663,7 +1663,7 @@ static int node_composit_buts_color_spill(uiBlock *block, bNodeTree *ntree, bNod uiBlockEndAlign(block); } return 60; - } +} static int node_composit_buts_chroma_matte(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) { @@ -1945,7 +1945,7 @@ static void node_composit_set_butfunc(bNodeType *ntype) break; case CMP_NODE_CROP: ntype->butfunc= node_composit_buts_crop; - break; + break; case CMP_NODE_BLUR: ntype->butfunc= node_composit_buts_blur; break; @@ -2169,39 +2169,39 @@ static void draw_nodespace_back_tex(ScrArea *sa, SpaceNode *snode) ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); if(ibuf) { int x, y; - float zoom = 1.0; - - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); + float zoom = 1.0; + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); glaDefine2DArea(&sa->winrct); - if(ibuf->x > sa->winx || ibuf->y > sa->winy) { - float zoomx, zoomy; - zoomx= (float)sa->winx/ibuf->x; - zoomy= (float)sa->winy/ibuf->y; - zoom = MIN2(zoomx, zoomy); - } + if(ibuf->x > sa->winx || ibuf->y > sa->winy) { + float zoomx, zoomy; + zoomx= (float)sa->winx/ibuf->x; + zoomy= (float)sa->winy/ibuf->y; + zoom = MIN2(zoomx, zoomy); + } - x = (sa->winx-zoom*ibuf->x)/2 + snode->xof; + x = (sa->winx-zoom*ibuf->x)/2 + snode->xof; y = (sa->winy-zoom*ibuf->y)/2 + snode->yof; - glPixelZoom(zoom, zoom); + glPixelZoom(zoom, zoom); - glColor4f(1.0, 1.0, 1.0, 1.0); + glColor4f(1.0, 1.0, 1.0, 1.0); if(ibuf->rect) - glaDrawPixelsTex(x, y, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, ibuf->rect); + glaDrawPixelsTex(x, y, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, ibuf->rect); else if(ibuf->channels==4) - glaDrawPixelsTex(x, y, ibuf->x, ibuf->y, GL_FLOAT, ibuf->rect_float); - - glPixelZoom(1.0, 1.0); + glaDrawPixelsTex(x, y, ibuf->x, ibuf->y, GL_FLOAT, ibuf->rect_float); - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); + glPixelZoom(1.0, 1.0); + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); } } } diff --git a/source/blender/src/drawobject.c b/source/blender/src/drawobject.c index 56eaeae29c9..c8d2e3dad90 100644 --- a/source/blender/src/drawobject.c +++ b/source/blender/src/drawobject.c @@ -3137,7 +3137,7 @@ static void draw_particle_system(Base *base, PartEff *paf) mymultmatrix(mat); } - if(ob->ipoflag & OB_OFFS_PARTICLE) ptime= ob->sf; + if(ob->ipoflag & OB_OFFS_PARTICLE) ptime= give_timeoffset(ob); else ptime= 0.0; ctime= bsystem_time(ob, (float)(G.scene->r.cfra), ptime); @@ -3317,7 +3317,7 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys) psys->flag|=PSYS_DRAWING; - if(!psys->childcache) + if(part->type==PART_HAIR && !psys->childcache) totchild=0; else totchild=psys->totchild*part->disp/100; @@ -5528,7 +5528,7 @@ void draw_object(Base *base, int flag) for (ct= targets.first; ct; ct= ct->next) { /* calculate target's matrix */ if (cti->get_target_matrix) - cti->get_target_matrix(curcon, cob, ct, bsystem_time(ob, (float)(G.scene->r.cfra), ob->sf)); + cti->get_target_matrix(curcon, cob, ct, bsystem_time(ob, (float)(G.scene->r.cfra), give_timeoffset(ob))); else Mat4One(ct->matrix); diff --git a/source/blender/src/drawseq.c b/source/blender/src/drawseq.c index 2b301ab90c1..abf0f24e892 100644 --- a/source/blender/src/drawseq.c +++ b/source/blender/src/drawseq.c @@ -92,6 +92,26 @@ #define SEQ_STRIP_OFSBOTTOM 0.2 #define SEQ_STRIP_OFSTOP 0.8 +static GLubyte halftone[] = { + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55}; + +/* Note, Dont use WHILE_SEQ while drawing! - it messes up transform, - Campbell */ + int no_rightbox=0, no_leftbox= 0; static void draw_seq_handle(Sequence *seq, SpaceSeq *sseq, float pixelx, short direction); static void draw_seq_extensions(Sequence *seq, SpaceSeq *sseq); @@ -207,20 +227,26 @@ static void get_seq_color3ubv(Sequence *seq, char *col) static void drawmeta_contents(Sequence *seqm, float x1, float y1, float x2, float y2) { + /* Note, this used to use WHILE_SEQ, but it messes up the seq->depth value, (needed by transform when doing overlap checks) + * so for now, just use the meta's immediate children, could be fixed but its only drawing - Campbell */ Sequence *seq; float dx; int nr; char col[3]; - nr= 0; - WHILE_SEQ(&seqm->seqbase) { - nr++; - } - END_SEQ + nr= BLI_countlist(&seqm->seqbase); dx= (x2-x1)/nr; - WHILE_SEQ(&seqm->seqbase) { + if (seqm->flag & SEQ_MUTE) { + glEnable(GL_POLYGON_STIPPLE); + glPolygonStipple(halftone); + + glEnable(GL_LINE_STIPPLE); + glLineStipple(1, 0x8888); + } + + for (seq= seqm->seqbase.first; seq; seq= seq->next) { get_seq_color3ubv(seq, col); glColor3ubv((GLubyte *)col); @@ -234,7 +260,11 @@ static void drawmeta_contents(Sequence *seqm, float x1, float y1, float x2, floa x1+= dx; } - END_SEQ + + if (seqm->flag & SEQ_MUTE) { + glDisable(GL_POLYGON_STIPPLE); + glDisable(GL_LINE_STIPPLE); + } } static void drawseqwave(Sequence *seq, float x1, float y1, float x2, float y2, int winx) @@ -604,6 +634,11 @@ static void draw_shadedstrip(Sequence *seq, char *col, float x1, float y1, float { float ymid1, ymid2; + if (seq->flag & SEQ_MUTE) { + glEnable(GL_POLYGON_STIPPLE); + glPolygonStipple(halftone); + } + ymid1 = (y2-y1)*0.25 + y1; ymid2 = (y2-y1)*0.65 + y1; @@ -645,6 +680,9 @@ static void draw_shadedstrip(Sequence *seq, char *col, float x1, float y1, float glEnd(); + if (seq->flag & SEQ_MUTE) { + glDisable(GL_POLYGON_STIPPLE); + } } /* @@ -702,8 +740,17 @@ static void draw_seq_strip(Sequence *seq, ScrArea *sa, SpaceSeq *sseq, int outli BIF_GetColorPtrBlendShade3ubv(col, col, col, 0.0, outline_tint); glColor3ubv((GLubyte *)col); + + if (seq->flag & SEQ_MUTE) { + glEnable(GL_LINE_STIPPLE); + glLineStipple(1, 0x8888); + } + gl_round_box_shade(GL_LINE_LOOP, x1, y1, x2, y2, 0.0, 0.1, 0.0); - + + if (seq->flag & SEQ_MUTE) { + glDisable(GL_LINE_STIPPLE); + } /* calculate if seq is long enough to print a name */ x1= seq->startdisp+seq->handsize; diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c index fd23761c82c..e3d73f4cda3 100644 --- a/source/blender/src/drawview.c +++ b/source/blender/src/drawview.c @@ -125,6 +125,7 @@ #include "BIF_mywindow.h" #include "BIF_poseobject.h" #include "BIF_previewrender.h" +#include "BIF_radialcontrol.h" #include "BIF_resources.h" #include "BIF_retopo.h" #include "BIF_screen.h" @@ -3061,68 +3062,13 @@ void drawview3dspace(ScrArea *sa, void *spacedata) /* Draw Sculpt Mode brush */ if(!G.obedit && (G.f & G_SCULPTMODE) && area_is_active_area(v3d->area) && sculpt_session()) { - PropsetData *pd= sculpt_session()->propset; - short r1=100, r2=100, r3=100; - short mouse[2]; + RadialControl *rc= sculpt_session()->radialcontrol; if(sculpt_data()->flags & SCULPT_INPUT_SMOOTH) sculpt_stroke_draw(); - if(pd) { - if(pd->mode == PropsetSize) { - r1= sculptmode_brush()->size; - r2= pd->origsize; - r3= r1; - } else if(pd->mode == PropsetStrength) { - r1= 200 - sculptmode_brush()->strength * 2; - r2= 200; - r3= 200; - } else if(pd->mode == PropsetTexRot) { - r1= r2= 200; - r3= 200; - } - - /* Draw brush with texture */ - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - glBindTexture(GL_TEXTURE_2D, pd->tex); - - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - glPushMatrix(); - glTranslatef(pd->origloc[0], pd->origloc[1], 0); - glRotatef(tex_angle(), 0, 0, 1); - - glEnable(GL_TEXTURE_2D); - glBegin(GL_QUADS); - glColor4f(0,0,0,1); - glTexCoord2f(0,0); - glVertex2f(-r3, -r3); - glTexCoord2f(1,0); - glVertex2f(r3, -r3); - glTexCoord2f(1,1); - glVertex2f(r3, r3); - glTexCoord2f(0,1); - glVertex2f(-r3, r3); - glEnd(); - glDisable(GL_TEXTURE_2D); - - glPopMatrix(); - - if(r1 != r2) - fdrawXORcirc(pd->origloc[0], pd->origloc[1], r1); - fdrawXORcirc(pd->origloc[0], pd->origloc[1], r2); - - if(pd->mode == PropsetTexRot) { - const float ang= pd->origtexrot * (M_PI/180.0f); - getmouseco_areawin(mouse); - sdrawXORline(pd->origloc[0], pd->origloc[1], - pd->origloc[0]+200*cos(ang), pd->origloc[1]+200*sin(ang)); - sdrawXORline(pd->origloc[0], pd->origloc[1], mouse[0], mouse[1]); - } - } + if(rc) + radialcontrol_draw(rc); else if(sculpt_data()->flags & SCULPT_DRAW_BRUSH) { short csc[2], car[2]; getmouseco_sc(csc); @@ -3143,7 +3089,9 @@ void drawview3dspace(ScrArea *sa, void *spacedata) ParticleEditSettings *pset = PE_settings(); short c[2]; - if(psys && psys->edit && pset->brushtype>=0){ + if(*PE_radialcontrol()) + radialcontrol_draw(*PE_radialcontrol()); + else if(psys && psys->edit && pset->brushtype>=0) { getmouseco_areawin(c); fdrawXORcirc((float)c[0], (float)c[1], (float)pset->brush[pset->brushtype].size); } diff --git a/source/blender/src/editaction.c b/source/blender/src/editaction.c index 311f2a653d5..cb436e8bff1 100644 --- a/source/blender/src/editaction.c +++ b/source/blender/src/editaction.c @@ -31,6 +31,7 @@ */ #include +#include #include #include "MEM_guardedalloc.h" @@ -198,8 +199,25 @@ bActListElem *make_new_actlistelem (void *data, short datatype, void *owner, sho ale->owner= owner; ale->ownertype= ownertype; + if ((owner) && (ownertype == ACTTYPE_ACHAN)) { + bActionChannel *ochan= (bActionChannel *)owner; + ale->grp= ochan->grp; + } + else + ale->grp= NULL; + /* do specifics */ switch (datatype) { + case ACTTYPE_GROUP: + { + bActionGroup *agrp= (bActionGroup *)data; + + ale->flag= agrp->flag; + + ale->key_data= NULL; + ale->datatype= ALE_GROUP; + } + break; case ACTTYPE_ACHAN: { bActionChannel *achan= (bActionChannel *)data; @@ -276,81 +294,116 @@ bActListElem *make_new_actlistelem (void *data, short datatype, void *owner, sho /* ----------------------------------------- */ -static void actdata_filter_action (ListBase *act_data, bAction *act, int filter_mode) +static void actdata_filter_actionchannel (ListBase *act_data, bActionChannel *achan, int filter_mode) { bActListElem *ale; - bActionChannel *achan; bConstraintChannel *conchan; IpoCurve *icu; - /* loop over action channels, performing the necessary checks */ - for (achan= act->chanbase.first; achan; achan= achan->next) { - /* only work with this channel and its subchannels if it is visible */ - if (!(filter_mode & ACTFILTER_VISIBLE) || VISIBLE_ACHAN(achan)) { - /* only work with this channel and its subchannels if it is editable */ - if (!(filter_mode & ACTFILTER_FOREDIT) || EDITABLE_ACHAN(achan)) { - /* check if this achan should only be included if it is selected */ - if (!(filter_mode & ACTFILTER_SEL) || SEL_ACHAN(achan)) { - /* are we only interested in the ipo-curves? */ - if ((filter_mode & ACTFILTER_ONLYICU)==0) { - ale= make_new_actlistelem(achan, ACTTYPE_ACHAN, achan, ACTTYPE_ACHAN); - if (ale) BLI_addtail(act_data, ale); - } + /* only work with this channel and its subchannels if it is visible */ + if (!(filter_mode & ACTFILTER_VISIBLE) || VISIBLE_ACHAN(achan)) { + /* only work with this channel and its subchannels if it is editable */ + if (!(filter_mode & ACTFILTER_FOREDIT) || EDITABLE_ACHAN(achan)) { + /* check if this achan should only be included if it is selected */ + if (!(filter_mode & ACTFILTER_SEL) || SEL_ACHAN(achan)) { + /* are we only interested in the ipo-curves? */ + if ((filter_mode & ACTFILTER_ONLYICU)==0) { + ale= make_new_actlistelem(achan, ACTTYPE_ACHAN, achan, ACTTYPE_ACHAN); + if (ale) BLI_addtail(act_data, ale); } - else { - /* only consider selected channels - achan not selected */ - continue; - } + } + else { + /* only consider selected channels - achan not selected */ + return; + } + + /* check if expanded - if not, continue on to next action channel */ + if (EXPANDED_ACHAN(achan) == 0 && (filter_mode & ACTFILTER_ONLYICU)==0) + return; - /* check if expanded - if not, continue on to next action channel */ - if (EXPANDED_ACHAN(achan) == 0 && (filter_mode & ACTFILTER_ONLYICU)==0) - continue; - - /* ipo channels */ - if (achan->ipo) { - /* include ipo-expand widget? */ - if ((filter_mode & ACTFILTER_CHANNELS) && (filter_mode & ACTFILTER_ONLYICU)==0) { - ale= make_new_actlistelem(achan, ACTTYPE_FILLIPO, achan, ACTTYPE_ACHAN); - if (ale) BLI_addtail(act_data, ale); - } - - /* add ipo-curve channels? */ - if (FILTER_IPO_ACHAN(achan) || (filter_mode & ACTFILTER_ONLYICU)) { - /* loop through ipo-curve channels, adding them */ - for (icu= achan->ipo->curve.first; icu; icu=icu->next) { - ale= make_new_actlistelem(icu, ACTTYPE_ICU, achan, ACTTYPE_ACHAN); - if (ale) BLI_addtail(act_data, ale); - } - } + /* ipo channels */ + if (achan->ipo) { + /* include ipo-expand widget? */ + if ((filter_mode & ACTFILTER_CHANNELS) && (filter_mode & ACTFILTER_ONLYICU)==0) { + ale= make_new_actlistelem(achan, ACTTYPE_FILLIPO, achan, ACTTYPE_ACHAN); + if (ale) BLI_addtail(act_data, ale); } - /* constraint channels */ - if (achan->constraintChannels.first) { - /* include constraint-expand widget? */ - if ((filter_mode & ACTFILTER_CHANNELS) && (filter_mode & ACTFILTER_ONLYICU)==0) { - ale= make_new_actlistelem(achan, ACTTYPE_FILLCON, achan, ACTTYPE_ACHAN); - if (ale) BLI_addtail(act_data, ale); + /* add ipo-curve channels? */ + if (FILTER_IPO_ACHAN(achan) || (filter_mode & ACTFILTER_ONLYICU)) { + /* loop through ipo-curve channels, adding them */ + for (icu= achan->ipo->curve.first; icu; icu=icu->next) { + ale= make_new_actlistelem(icu, ACTTYPE_ICU, achan, ACTTYPE_ACHAN); + if (ale) BLI_addtail(act_data, ale); } - - /* add constaint channels? */ - if (FILTER_CON_ACHAN(achan)) { - /* loop through constraint channels, checking and adding them */ - for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) { - /* only work with this channel and its subchannels if it is editable */ - if (!(filter_mode & ACTFILTER_FOREDIT) || EDITABLE_CONCHAN(conchan)) { - /* check if this conchan should only be included if it is selected */ - if (!(filter_mode & ACTFILTER_SEL) || SEL_CONCHAN(conchan)) { - if ((filter_mode & ACTFILTER_ONLYICU)==0) { - ale= make_new_actlistelem(conchan, ACTTYPE_CONCHAN, achan, ACTTYPE_ACHAN); - if (ale) BLI_addtail(act_data, ale); - } + } + } + + /* constraint channels */ + if (achan->constraintChannels.first) { + /* include constraint-expand widget? */ + if ((filter_mode & ACTFILTER_CHANNELS) && (filter_mode & ACTFILTER_ONLYICU)==0) { + ale= make_new_actlistelem(achan, ACTTYPE_FILLCON, achan, ACTTYPE_ACHAN); + if (ale) BLI_addtail(act_data, ale); + } + + /* add constaint channels? */ + if (FILTER_CON_ACHAN(achan)) { + /* loop through constraint channels, checking and adding them */ + for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) { + /* only work with this channel and its subchannels if it is editable */ + if (!(filter_mode & ACTFILTER_FOREDIT) || EDITABLE_CONCHAN(conchan)) { + /* check if this conchan should only be included if it is selected */ + if (!(filter_mode & ACTFILTER_SEL) || SEL_CONCHAN(conchan)) { + if ((filter_mode & ACTFILTER_ONLYICU)==0) { + ale= make_new_actlistelem(conchan, ACTTYPE_CONCHAN, achan, ACTTYPE_ACHAN); + if (ale) BLI_addtail(act_data, ale); } } } } } - } + } + } + } +} + +static void actdata_filter_action (ListBase *act_data, bAction *act, int filter_mode) +{ + bActListElem *ale; + bActionGroup *agrp; + bActionChannel *achan, *lastchan=NULL; + + /* loop over groups */ + for (agrp= act->groups.first; agrp; agrp= agrp->next) { + /* add this group as a channel first */ + if (!(filter_mode & ACTFILTER_ONLYICU) && !(filter_mode & ACTFILTER_IPOKEYS)) { + ale= make_new_actlistelem(agrp, ACTTYPE_GROUP, NULL, ACTTYPE_NONE); + if (ale) BLI_addtail(act_data, ale); } + + /* store reference to last channel of group */ + if (agrp->channels.last) + lastchan= agrp->channels.last; + + /* filters here are a bit convulted... + * - groups show a "summary" of keyframes beside their name which must accessable for tools which handle keyframes + * - groups can be collapsed (and those tools which are only interested in channels rely on knowing that group is closed) + */ + if (!(filter_mode & ACTFILTER_VISIBLE) || EXPANDED_AGRP(agrp) || + (filter_mode & (ACTFILTER_IPOKEYS|ACTFILTER_ONLYICU))) + { + if (!(filter_mode & ACTFILTER_FOREDIT) || EDITABLE_AGRP(agrp)) { + for (achan= agrp->channels.first; achan && achan->grp==agrp; achan= achan->next) { + actdata_filter_actionchannel(act_data, achan, filter_mode); + } + } + } + } + + /* loop over action channels */ + for (achan=(lastchan)?lastchan->next:act->chanbase.first; achan; achan=achan->next) { + actdata_filter_actionchannel(act_data, achan, filter_mode); } } @@ -450,7 +503,6 @@ void actdata_filter (ListBase *act_data, int filter_mode, void *data, short data /* **************************************************** */ /* GENERAL ACTION TOOLS */ - /* gets the key data from the currently selected * mesh/lattice. If a mesh is not selected, or does not have * key data, then we return NULL (currently only @@ -641,6 +693,10 @@ static void *get_nearest_action_key (float *selx, short *sel, short *ret_type, b break; } } + else if (ale->type == ACTTYPE_GROUP) { + bActionGroup *agrp= (bActionGroup *)ale->data; + agroup_to_keylist(agrp, &act_keys, NULL); + } /* loop through keyframes, finding one that was clicked on */ for (ak= act_keys.first; ak; ak= ak->next) { @@ -707,6 +763,268 @@ void *get_action_context (short *datatype) } } +/* **************************************************** */ +/* ACTION CHANNEL GROUPS */ + +/* Get the active action-group for an Action */ +bActionGroup *get_active_actiongroup (bAction *act) +{ + bActionGroup *agrp= NULL; + + if (act && act->groups.first) { + for (agrp= act->groups.first; agrp; agrp= agrp->next) { + if (agrp->flag & AGRP_ACTIVE) + break; + } + } + + return agrp; +} + +/* Make the given Action-Group the active one */ +void set_active_actiongroup (bAction *act, bActionGroup *agrp, short select) +{ + bActionGroup *grp; + + /* sanity checks */ + if (act == NULL) + return; + + /* Deactive all others */ + for (grp= act->groups.first; grp; grp= grp->next) { + if ((grp==agrp) && (select)) + grp->flag |= AGRP_ACTIVE; + else + grp->flag &= ~AGRP_ACTIVE; + } +} + +/* Add given channel into (active) group + * - assumes that channel is not linked to anything anymore + * - always adds at the end of the group + */ +static void action_groups_addachan (bAction *act, bActionGroup *agrp, bActionChannel *achan) +{ + bActionChannel *chan; + short done=0; + + /* sanity checks */ + if (ELEM3(NULL, act, agrp, achan)) + return; + + /* try to find a channel to slot this in before/after */ + for (chan= act->chanbase.first; chan; chan= chan->next) { + /* if channel has no group, then we have ungrouped channels, which should always occur after groups */ + if (chan->grp == NULL) { + BLI_insertlinkbefore(&act->chanbase, chan, achan); + + if (agrp->channels.first == NULL) + agrp->channels.first= achan; + agrp->channels.last= achan; + + done= 1; + break; + } + + /* if channel has group after current, we can now insert (otherwise we have gone too far) */ + else if (chan->grp == agrp->next) { + BLI_insertlinkbefore(&act->chanbase, chan, achan); + + if (agrp->channels.first == NULL) + agrp->channels.first= achan; + agrp->channels.last= achan; + + done= 1; + break; + } + + /* if channel has group we're targeting, check whether it is the last one of these */ + else if (chan->grp == agrp) { + if ((chan->next) && (chan->next->grp != agrp)) { + BLI_insertlinkafter(&act->chanbase, chan, achan); + agrp->channels.last= achan; + done= 1; + break; + } + else if (chan->next == NULL) { + BLI_addtail(&act->chanbase, achan); + agrp->channels.last= achan; + done= 1; + break; + } + } + + /* if channel has group before target, check whether the next one is something after target */ + else if (chan->grp == agrp->prev) { + if (chan->next) { + if ((chan->next->grp != chan->grp) && (chan->next->grp != agrp)) { + BLI_insertlinkafter(&act->chanbase, chan, achan); + + agrp->channels.first= achan; + agrp->channels.last= achan; + + done= 1; + break; + } + } + else { + BLI_insertlinkafter(&act->chanbase, chan, achan); + + agrp->channels.first= achan; + agrp->channels.last= achan; + + done= 1; + break; + } + } + } + + /* only if added, set channel as belonging to this group */ + if (done) { + achan->grp= agrp; + } + else + printf("Error: ActionChannel: '%s' couldn't be added to Group: '%s' \n", achan->name, agrp->name); +} + +/* Remove the given channel from all groups */ +static void action_groups_removeachan (bAction *act, bActionChannel *achan) +{ + /* sanity checks */ + if (ELEM(NULL, act, achan)) + return; + + /* check if any group used this directly */ + if (achan->grp) { + bActionGroup *agrp= achan->grp; + + if (agrp->channels.first == agrp->channels.last) { + if (agrp->channels.first == achan) { + agrp->channels.first= NULL; + agrp->channels.last= NULL; + } + } + else if (agrp->channels.first == achan) { + if ((achan->next) && (achan->next->grp==agrp)) + agrp->channels.first= achan->next; + else + agrp->channels.first= NULL; + } + else if (agrp->channels.last == achan) { + if ((achan->prev) && (achan->prev->grp==agrp)) + agrp->channels.last= achan->prev; + else + agrp->channels.last= NULL; + } + + achan->grp= NULL; + } + + /* now just remove from list */ + BLI_remlink(&act->chanbase, achan); +} + +/* Add a new Action-Group or add channels to active one */ +void action_groups_group (short add_group) +{ + bAction *act; + bActionChannel *achan, *anext; + bActionGroup *agrp; + void *data; + short datatype; + + /* validate type of data we are working on */ + data = get_action_context(&datatype); + if (data == NULL) return; + if (datatype != ACTCONT_ACTION) return; + act= (bAction *)data; + + /* get active group */ + if ((act->groups.first==NULL) || (add_group)) { + /* Add a new group, and make it active */ + agrp= MEM_callocN(sizeof(bActionGroup), "bActionGroup"); + + agrp->flag |= (AGRP_ACTIVE|AGRP_SELECTED|AGRP_EXPANDED); + sprintf(agrp->name, "Group"); + + BLI_addtail(&act->groups, agrp); + BLI_uniquename(&act->groups, agrp, "Group", offsetof(bActionGroup, name), 32); + + set_active_actiongroup(act, agrp, 1); + + add_group= 1; + } + else { + agrp= get_active_actiongroup(act); + + if (agrp == NULL) { + error("No Active Action Group"); + return; + } + } + + /* loop through action-channels, finding those that are selected + visible to move */ + // FIXME: this should be done with action api instead + for (achan= act->chanbase.first; achan; achan= anext) { + anext= achan->next; + + /* make sure not already in new-group */ + if (achan->grp != agrp) { + if (VISIBLE_ACHAN(achan) && SEL_ACHAN(achan)) { + /* unlink from everything else */ + action_groups_removeachan(act, achan); + + /* add to end of group's channels */ + action_groups_addachan(act, agrp, achan); + } + } + } + + /* updates and undo */ + if (add_group) + BIF_undo_push("Add Action Group"); + else + BIF_undo_push("Add to Action Group"); + + allqueue(REDRAWACTION, 0); +} + +/* Remove selected channels from their groups */ +void action_groups_ungroup (void) +{ + ListBase act_data = {NULL, NULL}; + bActListElem *ale; + bAction *act; + void *data; + short datatype; + short filter; + + /* validate type of data we are working on */ + data = get_action_context(&datatype); + if (data == NULL) return; + if (datatype != ACTCONT_ACTION) return; + act= (bAction *)data; + + /* filter data */ + filter= (ACTFILTER_VISIBLE|ACTFILTER_SEL); + actdata_filter(&act_data, filter, act, ACTCONT_ACTION); + + /* Only ungroup selected action-channels */ + for (ale= act_data.first; ale; ale= ale->next) { + if (ale->type == ACTTYPE_ACHAN) { + action_groups_removeachan(act, ale->data); + BLI_addtail(&act->chanbase, ale->data); + } + } + + BLI_freelistN(&act_data); + + /* updates and undo */ + BIF_undo_push("Remove From Action Groups"); + + allqueue(REDRAWACTION, 0); +} + /* **************************************************** */ /* TRANSFORM TOOLS */ @@ -1063,6 +1381,32 @@ void delete_action_channels (void) if (datatype != ACTCONT_ACTION) return; act= (bAction *)data; + /* deal with groups first */ + if (act->groups.first) { + bActionGroup *agrp, *grp; + bActionChannel *chan, *nchan; + + /* unlink achan's that belonged to this group (and make sure they're not selected if they weren't visible) */ + for (agrp= act->groups.first; agrp; agrp= grp) { + grp= agrp->next; + + /* remove if group is selected */ + if (SEL_AGRP(agrp)) { + for (chan= agrp->channels.first; chan && chan->grp==agrp; chan= nchan) { + nchan= chan->next; + + action_groups_removeachan(act, chan); + BLI_addtail(&act->chanbase, chan); + + if (EXPANDED_AGRP(agrp) == 0) + chan->flag &= ~(ACHAN_SELECTED|ACHAN_HILIGHTED); + } + + BLI_freelinkN(&act->groups, agrp); + } + } + } + /* filter data */ filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_CHANNELS | ACTFILTER_SEL); actdata_filter(&act_data, filter, data, datatype); @@ -1240,10 +1584,15 @@ void sample_action_keys (void) /* - The copy/paste buffer currently stores a set of Action Channels, with temporary * IPO-blocks, and also temporary IpoCurves which only contain the selected keyframes. * - Only pastes between compatable data is possible (i.e. same achan->name, ipo-curve type, etc.) + * Unless there is only one element in the buffer, names are also tested to check for compatability. + * - All pasted frames are offset by the same amount. This is calculated as the difference in the times of + * the current frame and the 'first keyframe' (i.e. the earliest one in all channels). + * - The earliest frame is calculated per copy operation. */ /* globals for copy/paste data (like for other copy/paste buffers) */ ListBase actcopybuf = {NULL, NULL}; +static float actcopy_firstframe= 999999999.0f; /* This function frees any MEM_calloc'ed copy/paste buffer data */ void free_actcopybuf () @@ -1274,6 +1623,7 @@ void free_actcopybuf () } actcopybuf.first= actcopybuf.last= NULL; + actcopy_firstframe= 999999999.0f; } /* This function adds data to the copy/paste buffer, freeing existing data first @@ -1345,10 +1695,16 @@ void copy_actdata () icn->adrcode = icu->adrcode; BLI_addtail(&ipn->curve, icn); - /* find selected BezTriples to add to the buffer */ + /* find selected BezTriples to add to the buffer (and set first frame) */ for (i=0, bezt=icu->bezt; i < icu->totvert; i++, bezt++) { - if (BEZSELECTED(bezt)) + if (BEZSELECTED(bezt)) { + /* add to buffer ipo-curve */ insert_bezt_icu(icn, bezt); + + /* check if this is the earliest frame encountered so far */ + if (bezt->vec[1][0] < actcopy_firstframe) + actcopy_firstframe= bezt->vec[1][0]; + } } } } @@ -1368,7 +1724,9 @@ void paste_actdata () int filter; void *data; short datatype; + short no_name= 0; + float offset = CFRA - actcopy_firstframe; /* check if buffer is empty */ if (ELEM(NULL, actcopybuf.first, actcopybuf.last)) { @@ -1394,8 +1752,6 @@ void paste_actdata () IpoCurve *ico, *icu; BezTriple *bezt; int i; - float offset= 0.0f; - short offsetInit= 1; /* find matching ipo-block */ for (achan= actcopybuf.first; achan; achan= achan->next) { @@ -1443,13 +1799,7 @@ void paste_actdata () /* only paste if compatable blocktype + adrcode */ if ((ico->blocktype==icu->blocktype) && (ico->adrcode==icu->adrcode)) { /* just start pasting, with the the first keyframe on the current frame, and so on */ - for (i=0, bezt=ico->bezt; i < ico->totvert; i++, bezt++) { - /* initialise offset (if not already done) */ - if (offsetInit) { - offset= CFRA - bezt->vec[1][0]; - offsetInit= 0; - } - + for (i=0, bezt=ico->bezt; i < ico->totvert; i++, bezt++) { /* temporarily apply offset to src beztriple while copying */ bezt->vec[0][0] += offset; bezt->vec[1][0] += offset; @@ -1634,6 +1984,7 @@ static void numbuts_action () void *act_channel; short chantype; + bActionGroup *agrp= NULL; bActionChannel *achan= NULL; bConstraintChannel *conchan= NULL; IpoCurve *icu= NULL; @@ -1739,6 +2090,18 @@ static void numbuts_action () add_numbut(but++, NUM|FLO, "Slider Max:", kb->slidermin, 10000, &kb->slidermax, 0); } + else if (chantype == ACTTYPE_GROUP) { + /* Action Group */ + agrp= (bActionGroup *)act_channel; + + strcpy(str, agrp->name); + protect= (agrp->flag & AGRP_PROTECTED); + expand = (agrp->flag & AGRP_EXPANDED); + + add_numbut(but++, TEX, "ActGroup: ", 0, 31, str, "Name of Action Group"); + add_numbut(but++, TOG|SHO, "Expanded", 0, 24, &expand, "Action Group is Expanded"); + add_numbut(but++, TOG|SHO, "Protected", 0, 24, &protect, "Group is Protected"); + } else { /* nothing under-cursor */ return; @@ -1777,6 +2140,16 @@ static void numbuts_action () if (achan->ipo) achan->ipo->muteipo = mute; } + else if (agrp) { + strcpy(agrp->name, str); + BLI_uniquename(&( ((bAction *)data)->groups ), agrp, "Group", offsetof(bActionGroup, name), 32); + + if (expand) agrp->flag |= AGRP_EXPANDED; + else agrp->flag &= ~AGRP_EXPANDED; + + if (protect) agrp->flag |= AGRP_PROTECTED; + else agrp->flag &= ~AGRP_PROTECTED; + } allqueue(REDRAWACTION, 0); allspace(REMAKEIPO, 0); @@ -1790,6 +2163,32 @@ static void numbuts_action () /* **************************************************** */ /* CHANNEL SELECTION */ +/* select_mode = SELECT_REPLACE + * = SELECT_ADD + * = SELECT_SUBTRACT + * = SELECT_INVERT + */ +static void select_action_group (bAction *act, bActionGroup *agrp, int selectmode) +{ + /* Select the channel based on the selection mode */ + short select; + + switch (selectmode) { + case SELECT_ADD: + agrp->flag |= AGRP_SELECTED; + break; + case SELECT_SUBTRACT: + agrp->flag &= ~AGRP_SELECTED; + break; + case SELECT_INVERT: + agrp->flag ^= AGRP_SELECTED; + break; + } + select = (agrp->flag & AGRP_SELECTED) ? 1 : 0; + + set_active_actiongroup(act, agrp, select); +} + static void hilight_channel(bAction *act, bActionChannel *achan, short select) { bActionChannel *curchan; @@ -1950,6 +2349,10 @@ void deselect_actionchannels (bAction *act, short test) break; switch (ale->type) { + case ACTTYPE_GROUP: + if (ale->flag & AGRP_SELECTED) + sel= 0; + break; case ACTTYPE_ACHAN: if (ale->flag & ACHAN_SELECTED) sel= 0; @@ -1971,6 +2374,16 @@ void deselect_actionchannels (bAction *act, short test) /* Now set the flags */ for (ale= act_data.first; ale; ale= ale->next) { switch (ale->type) { + case ACTTYPE_GROUP: + { + bActionGroup *agrp= (bActionGroup *)ale->data; + + if (sel) + agrp->flag |= AGRP_SELECTED; + else + agrp->flag &= ~AGRP_SELECTED; + } + break; case ACTTYPE_ACHAN: { bActionChannel *achan= (bActionChannel *)ale->data; @@ -2088,6 +2501,20 @@ void selectall_action_keys (short mval[], short mode, short select_mode) /* get channel, and act according to type */ act_channel= get_nearest_act_channel(mval, &chantype); switch (chantype) { + case ACTTYPE_GROUP: + { + bActionGroup *agrp= (bActionGroup *)act_channel; + bActionChannel *achan; + bConstraintChannel *conchan; + + for (achan= agrp->channels.first; achan && achan->grp==agrp; achan= achan->next) { + select_ipo_bezier_keys(achan->ipo, select_mode); + + for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) + select_ipo_bezier_keys(conchan->ipo, select_mode); + } + } + break; case ACTTYPE_ACHAN: { bActionChannel *achan= (bActionChannel *)act_channel; @@ -2484,6 +2911,18 @@ void borderselect_action (void) else if (ale->datatype == ALE_ICU) borderselect_icu_key(ale->key_data, rectf.xmin, rectf.xmax, select_function); } + else if (ale->type == ACTTYPE_GROUP) { + bActionGroup *agrp= ale->data; + bActionChannel *achan; + bConstraintChannel *conchan; + + for (achan= agrp->channels.first; achan && achan->grp==agrp; achan= achan->next) { + borderselect_ipo_key(achan->ipo, rectf.xmin, rectf.xmax, selectmode); + + for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) + borderselect_ipo_key(conchan->ipo, rectf.xmin, rectf.xmax, selectmode); + } + } break; case ACTEDIT_BORDERSEL_CHA: /* all in channel(s) */ if (!((ymax < rectf.ymin) || (ymin > rectf.ymax))) { @@ -2493,6 +2932,18 @@ void borderselect_action (void) else if (ale->datatype == ALE_ICU) select_icu_bezier_keys(ale->key_data, selectmode); } + else if (ale->type == ACTTYPE_GROUP) { + bActionGroup *agrp= ale->data; + bActionChannel *achan; + bConstraintChannel *conchan; + + for (achan= agrp->channels.first; achan && achan->grp==agrp; achan= achan->next) { + select_ipo_bezier_keys(achan->ipo, selectmode); + + for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) + select_ipo_bezier_keys(conchan->ipo, selectmode); + } + } } break; default: /* any keyframe inside region defined by region */ @@ -2503,6 +2954,18 @@ void borderselect_action (void) else if (ale->datatype == ALE_ICU) borderselect_icu_key(ale->key_data, rectf.xmin, rectf.xmax, select_function); } + else if (ale->type == ACTTYPE_GROUP) { + bActionGroup *agrp= ale->data; + bActionChannel *achan; + bConstraintChannel *conchan; + + for (achan= agrp->channels.first; achan && achan->grp==agrp; achan= achan->next) { + borderselect_ipo_key(achan->ipo, rectf.xmin, rectf.xmax, selectmode); + + for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) + borderselect_ipo_key(conchan->ipo, rectf.xmin, rectf.xmax, selectmode); + } + } } } @@ -2529,6 +2992,7 @@ static void mouse_action (int selectmode) short datatype; bAction *act= NULL; + bActionGroup *agrp= NULL; bActionChannel *achan= NULL; bConstraintChannel *conchan= NULL; IpoCurve *icu= NULL; @@ -2611,6 +3075,9 @@ static void mouse_action (int selectmode) case ACTTYPE_ACHAN: achan= (bActionChannel *)act_channel; break; + case ACTTYPE_GROUP: + agrp= (bActionGroup *)act_channel; + break; default: return; } @@ -2623,9 +3090,16 @@ static void mouse_action (int selectmode) if (datatype == ACTCONT_ACTION) { deselect_action_channels(0); - achan->flag |= ACHAN_SELECTED; - hilight_channel(act, achan, 1); - select_poseelement_by_name(achan->name, 2); /* 2 is activate */ + /* Highlight either an Action-Channel or Action-Group */ + if (achan) { + achan->flag |= ACHAN_SELECTED; + hilight_channel(act, achan, 1); + select_poseelement_by_name(achan->name, 2); /* 2 is activate */ + } + else if (agrp) { + agrp->flag |= AGRP_SELECTED; + set_active_actiongroup(act, agrp, 1); + } } } @@ -2633,8 +3107,16 @@ static void mouse_action (int selectmode) select_icu_key(icu, selx, selectmode); else if (conchan) select_ipo_key(conchan->ipo, selx, selectmode); - else + else if (achan) select_ipo_key(achan->ipo, selx, selectmode); + else if (agrp) { + for (achan= agrp->channels.first; achan && achan->grp==agrp; achan= achan->next) { + select_ipo_key(achan->ipo, selx, selectmode); + + for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) + select_ipo_key(conchan->ipo, selx, selectmode); + } + } std_rmouse_transform(transform_action_keys); @@ -2663,6 +3145,30 @@ static void mouse_actionchannels (short mval[]) /* action to take depends on what channel we've got */ switch (chantype) { + case ACTTYPE_GROUP: + { + bActionGroup *agrp= (bActionGroup *)act_channel; + + if (mval[0] < 16) { + /* toggle expand */ + agrp->flag ^= AGRP_EXPANDED; + } + else if (mval[0] >= (NAMEWIDTH-16)) { + /* toggle protection/locking */ + agrp->flag ^= AGRP_PROTECTED; + } + else { + /* select/deselect group */ + if (G.qual & LR_SHIFTKEY) { + select_action_group(act, agrp, SELECT_INVERT); + } + else { + deselect_actionchannels(act, 0); + select_action_group(act, agrp, SELECT_ADD); + } + } + } + break; case ACTTYPE_ACHAN: { bActionChannel *achan= (bActionChannel *)act_channel; @@ -2780,167 +3286,292 @@ static void mouse_actionchannels (short mval[]) /* **************************************************** */ /* ACTION CHANNEL RE-ORDERING */ -void top_sel_action () +/* make sure all action-channels belong to a group (and clear action's list) */ +static void split_groups_action_temp (bAction *act, bActionGroup *tgrp) { - bAction *act; + bActionChannel *achan; + bActionGroup *agrp; + + /* Separate action-channels into lists per group */ + for (agrp= act->groups.first; agrp; agrp= agrp->next) { + if (agrp->channels.first) { + achan= agrp->channels.last; + act->chanbase.first= achan->next; + + achan= agrp->channels.first; + achan->prev= NULL; + + achan= agrp->channels.last; + achan->next= NULL; + } + } + + /* Initialise memory for temp-group */ + memset(tgrp, 0, sizeof(bActionGroup)); + tgrp->flag |= (AGRP_EXPANDED|AGRP_TEMP); + strcpy(tgrp->name, "#TempGroup"); + + /* Move any action-channels not already moved, to the temp group */ + if (act->chanbase.first) { + /* start of list */ + achan= act->chanbase.first; + achan->prev= NULL; + tgrp->channels.first= achan; + act->chanbase.first= NULL; + + /* end of list */ + achan= act->chanbase.last; + achan->next= NULL; + tgrp->channels.last= achan; + act->chanbase.last= NULL; + } + + /* Add temp-group to list */ + BLI_addtail(&act->groups, tgrp); +} + +/* link lists of channels that groups have */ +static void join_groups_action_temp (bAction *act) +{ + bActionGroup *agrp; bActionChannel *achan; - /* Get the selected action, exit if none are selected */ - act = G.saction->action; - if (!act) return; + for (agrp= act->groups.first; agrp; agrp= agrp->next) { + ListBase tempGroup; + + /* add list of channels to action's channels */ + tempGroup= agrp->channels; + addlisttolist(&act->chanbase, &agrp->channels); + agrp->channels= tempGroup; + + /* clear moved flag */ + agrp->flag &= ~AGRP_MOVED; + + /* if temp-group... remove from list (but don't free as it's on the stack!) */ + if (agrp->flag & AGRP_TEMP) { + BLI_remlink(&act->groups, agrp); + break; + } + } - for (achan= act->chanbase.first; achan; achan= achan->next) { - if (VISIBLE_ACHAN(achan)) { - if (SEL_ACHAN(achan) && !(achan->flag & ACHAN_MOVED)) { - /* take it out off the chain keep data */ - BLI_remlink (&act->chanbase, achan); - /* make it first element */ - BLI_insertlinkbefore(&act->chanbase, act->chanbase.first, achan); - achan->flag |= ACHAN_MOVED; - /* restart with rest of list */ - achan= achan->next; + /* clear "moved" flag from all achans */ + for (achan= act->chanbase.first; achan; achan= achan->next) + achan->flag &= ~ACHAN_MOVED; +} + + +static short rearrange_actchannel_is_ok (Link *channel, short type) +{ + if (type == ACTTYPE_GROUP) { + bActionGroup *agrp= (bActionGroup *)channel; + + if (SEL_AGRP(agrp) && !(agrp->flag & AGRP_MOVED)) + return 1; + } + else if (type == ACTTYPE_ACHAN) { + bActionChannel *achan= (bActionChannel *)channel; + + if (VISIBLE_ACHAN(achan) && SEL_ACHAN(achan) && !(achan->flag & ACHAN_MOVED)) + return 1; + } + + return 0; +} + +static short rearrange_actchannel_after_ok (Link *channel, short type) +{ + if (type == ACTTYPE_GROUP) { + bActionGroup *agrp= (bActionGroup *)channel; + + if (agrp->flag & AGRP_TEMP) + return 0; + } + + return 1; +} + + +static short rearrange_actchannel_top (ListBase *list, Link *channel, short type) +{ + if (rearrange_actchannel_is_ok(channel, type)) { + /* take it out off the chain keep data */ + BLI_remlink(list, channel); + + /* make it first element */ + BLI_insertlinkbefore(list, list->first, channel); + + return 1; + } + + return 0; +} + +static short rearrange_actchannel_up (ListBase *list, Link *channel, short type) +{ + if (rearrange_actchannel_is_ok(channel, type)) { + Link *prev= channel->prev; + + if (prev) { + /* take it out off the chain keep data */ + BLI_remlink(list, channel); + + /* push it up */ + BLI_insertlinkbefore(list, prev, channel); + + return 1; + } + } + + return 0; +} + +static short rearrange_actchannel_down (ListBase *list, Link *channel, short type) +{ + if (rearrange_actchannel_is_ok(channel, type)) { + Link *next = (channel->next) ? channel->next->next : NULL; + + if (next) { + /* take it out off the chain keep data */ + BLI_remlink(list, channel); + + /* move it down */ + BLI_insertlinkbefore(list, next, channel); + + return 1; + } + else if (rearrange_actchannel_after_ok(list->last, type)) { + /* take it out off the chain keep data */ + BLI_remlink(list, channel); + + /* add at end */ + BLI_addtail(list, channel); + + return 1; + } + else { + /* take it out off the chain keep data */ + BLI_remlink(list, channel); + + /* add just before end */ + BLI_insertlinkbefore(list, list->last, channel); + + return 1; + } + } + + return 0; +} + +static short rearrange_actchannel_bottom (ListBase *list, Link *channel, short type) +{ + if (rearrange_actchannel_is_ok(channel, type)) { + if (rearrange_actchannel_after_ok(list->last, type)) { + /* take it out off the chain keep data */ + BLI_remlink(list, channel); + + /* add at end */ + BLI_addtail(list, channel); + + return 1; + } + } + + return 0; +} + + +/* Change the order of action-channels + * mode: REARRANGE_ACTCHAN_* + */ +void rearrange_action_channels (short mode) +{ + bAction *act; + bActionChannel *achan, *chan; + bActionGroup *agrp, *grp; + bActionGroup tgrp; + + void *data; + short datatype; + + short (*rearrange_func)(ListBase *, Link *, short); + char undostr[60]; + + /* Get the active action, exit if none are selected */ + data = get_action_context(&datatype); + if (data == NULL) return; + if (datatype != ACTCONT_ACTION) return; + act= (bAction *)data; + + /* exit if invalid mode */ + switch (mode) { + case REARRANGE_ACTCHAN_TOP: + strcpy(undostr, "Channel(s) to Top"); + rearrange_func= rearrange_actchannel_top; + break; + case REARRANGE_ACTCHAN_UP: + strcpy(undostr, "Channel(s) Move Up"); + rearrange_func= rearrange_actchannel_up; + break; + case REARRANGE_ACTCHAN_DOWN: + strcpy(undostr, "Channel(s) Move Down"); + rearrange_func= rearrange_actchannel_down; + break; + case REARRANGE_ACTCHAN_BOTTOM: + strcpy(undostr, "Channel(s) to Bottom"); + rearrange_func= rearrange_actchannel_bottom; + break; + default: + return; + } + + /* make sure we're only operating with groups */ + split_groups_action_temp(act, &tgrp); + + /* rearrange groups, and channels */ + #define GET_FIRST(list) ((mode > 0) ? (list.first) : (list.last)) + #define GET_NEXT(item) ((mode > 0) ? (item->next) : (item->prev)) + + for (agrp= GET_FIRST(act->groups); agrp; agrp= grp) { + /* Get next group to consider */ + grp= GET_NEXT(agrp); + + /* try to do group first */ + if (rearrange_func(&act->groups, (Link *)agrp, ACTTYPE_GROUP)) + agrp->flag |= AGRP_MOVED; + + /* only consider action-channels if they're visible (group expanded) */ + if (EXPANDED_AGRP(agrp)) { + for (achan= GET_FIRST(agrp->channels); achan; achan= chan) { + /* Get next channel to consider */ + chan= GET_NEXT(achan); + + /* Try to do channel */ + if (rearrange_func(&agrp->channels, (Link *)achan, ACTTYPE_ACHAN)) + achan->flag |= ACHAN_MOVED; } } } - /* clear temp flags */ - for (achan= act->chanbase.first; achan; achan= achan->next) { - achan->flag = achan->flag & ~ACHAN_MOVED; - } + #undef GET_FIRST + #undef GET_NEXT - /* Clean up and redraw stuff */ - remake_action_ipos(act); - BIF_undo_push("Top Action channel"); - allspace(REMAKEIPO, 0); + /* assemble lists into one list (and clear moved tags) */ + join_groups_action_temp(act); + + /* Undo + redraw */ + BIF_undo_push(undostr); allqueue(REDRAWACTION, 0); - allqueue(REDRAWIPO, 0); - allqueue(REDRAWNLA, 0); -} - -void up_sel_action () -{ - bAction *act; - bActionChannel *achan, *prev; - - /* Get the selected action, exit if none are selected */ - act = G.saction->action; - if (!act) return; - - for (achan=act->chanbase.first; achan; achan= achan->next) { - if (VISIBLE_ACHAN(achan)) { - if (SEL_ACHAN(achan) && !(achan->flag & ACHAN_MOVED)) { - prev = achan->prev; - if (prev) { - /* take it out off the chain keep data */ - BLI_remlink (&act->chanbase, achan); - /* push it up */ - BLI_insertlinkbefore(&act->chanbase, prev, achan); - achan->flag |= ACHAN_MOVED; - /* restart with rest of list */ - achan= achan->next; - } - } - } - } - /* clear temp flags */ - for (achan=act->chanbase.first; achan; achan= achan->next) { - achan->flag = achan->flag & ~ACHAN_MOVED; - } - - /* Clean up and redraw stuff */ - remake_action_ipos(act); - BIF_undo_push("Up Action channel"); - allspace(REMAKEIPO, 0); - allqueue(REDRAWACTION, 0); - allqueue(REDRAWIPO, 0); - allqueue(REDRAWNLA, 0); -} - -void down_sel_action () -{ - bAction *act; - bActionChannel *achan, *next; - - /* Get the selected action, exit if none are selected */ - act = G.saction->action; - if (!act) return; - - for (achan= act->chanbase.last; achan; achan= achan->prev) { - if (VISIBLE_ACHAN(achan)) { - if (SEL_ACHAN(achan) && !(achan->flag & ACHAN_MOVED)) { - next = achan->next; - if (next) next = next->next; - if (next) { - /* take it out off the chain keep data */ - BLI_remlink (&act->chanbase, achan); - /* move it down */ - BLI_insertlinkbefore(&act->chanbase, next, achan); - achan->flag |= ACHAN_MOVED; - } - else { - /* take it out off the chain keep data */ - BLI_remlink (&act->chanbase, achan); - /* add at end */ - BLI_addtail(&act->chanbase, achan); - achan->flag |= ACHAN_MOVED; - } - } - } - } - /* clear temp flags */ - for (achan= act->chanbase.first; achan; achan= achan->next) { - achan->flag = achan->flag & ~ACHAN_MOVED; - } - - /* Clean up and redraw stuff */ - remake_action_ipos(act); - BIF_undo_push("Down Action channel"); - allspace(REMAKEIPO, 0); - allqueue(REDRAWACTION, 0); - allqueue(REDRAWIPO, 0); - allqueue(REDRAWNLA, 0); -} - -void bottom_sel_action () -{ - bAction *act; - bActionChannel *achan; - - /* Get the selected action, exit if none are selected */ - act = G.saction->action; - if (!act) return; - - for (achan=act->chanbase.last; achan; achan= achan->prev) { - if (VISIBLE_ACHAN(achan)) { - if (SEL_ACHAN(achan) && !(achan->flag & ACHAN_MOVED)) { - /* take it out off the chain keep data */ - BLI_remlink(&act->chanbase, achan); - /* add at end */ - BLI_addtail(&act->chanbase, achan); - achan->flag |= ACHAN_MOVED; - } - } - } - /* clear temp flags */ - for (achan=act->chanbase.first; achan; achan= achan->next) { - achan->flag = achan->flag & ~ACHAN_MOVED; - } - - /* Clean up and redraw stuff */ - remake_action_ipos(act); - BIF_undo_push("Bottom Action channel"); - allspace(REMAKEIPO, 0); - allqueue(REDRAWACTION, 0); - allqueue(REDRAWIPO, 0); - allqueue(REDRAWNLA, 0); } +/* ******************************************************************* */ +/* CHANNEL VISIBILITY/FOLDING */ /* Expand all channels to show full hierachy */ void expand_all_action (void) { bAction *act; bActionChannel *achan; - short mode= 0; + bActionGroup *agrp; + short mode= 1; /* Get the selected action, exit if none are selected */ // TODO: really this should be done with the "action editor api" stuff, but this will suffice for now @@ -2948,15 +3579,32 @@ void expand_all_action (void) if (act == NULL) return; /* check if expand all, or close all */ - for (achan=act->chanbase.first; achan; achan= achan->next) { - if (VISIBLE_ACHAN(achan)) { - if (EXPANDED_ACHAN(achan)) - mode= 1; - break; + for (agrp= act->groups.first; agrp; agrp= agrp->next) { + if (EXPANDED_AGRP(agrp)) { + mode= 0; + break; + } + } + + if (mode == 0) { + for (achan= act->chanbase.first; achan; achan= achan->next) { + if (VISIBLE_ACHAN(achan)) { + if (EXPANDED_ACHAN(achan)) { + mode= 0; + break; + } + } } } /* expand/collapse depending on mode */ + for (agrp= act->groups.first; agrp; agrp= agrp->next) { + if (mode == 1) + agrp->flag |= AGRP_EXPANDED; + else + agrp->flag &= ~AGRP_EXPANDED; + } + for (achan=act->chanbase.first; achan; achan= achan->next) { if (VISIBLE_ACHAN(achan)) { if (mode == 1) @@ -2986,7 +3634,8 @@ void openclose_level_action (short mode) if (mode == 0) return; /* Only affect selected channels */ - for (achan=act->chanbase.first; achan; achan= achan->next) { + // FIXME: check for action-groups + for (achan= act->chanbase.first; achan; achan= achan->next) { if (VISIBLE_ACHAN(achan) && SEL_ACHAN(achan)) { if (EXPANDED_ACHAN(achan)) { if (FILTER_IPO_ACHAN(achan) || FILTER_CON_ACHAN(achan)) { @@ -3078,6 +3727,9 @@ void action_add_localmarker (bAction *act, int frame) BLI_addtail(&act->markers, marker); } + /* validate the name */ + BLI_uniquename(&act->markers, marker, "Pose", offsetof(TimeMarker, name), 64); + /* sets the newly added marker as the active one */ action_set_activemarker(act, marker, 1); @@ -3112,8 +3764,9 @@ void action_rename_localmarker (bAction *act) if (sbutton(name, 0, sizeof(name)-1, "Name: ") == 0) return; - /* copy name */ + /* copy then validate name */ BLI_strncpy(marker->name, name, sizeof(marker->name)); + BLI_uniquename(&act->markers, marker, "Pose", offsetof(TimeMarker, name), 64); /* undo and update */ BIF_undo_push("Action Rename Marker"); @@ -3255,12 +3908,41 @@ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt) break; case GKEY: - if (G.qual & LR_CTRLKEY) { - transform_markers('g', 0); + /* Action Channel Groups */ + if (G.qual == LR_SHIFTKEY) + action_groups_group(0); + else if (G.qual == (LR_CTRLKEY|LR_SHIFTKEY)) + action_groups_group(1); + else if (G.qual == LR_ALTKEY) + action_groups_ungroup(); + + else if (G.qual == (LR_CTRLKEY|LR_SHIFTKEY|LR_ALTKEY)) { + /* WARNING: this is a debug tool which should be removed once everything is stable... */ + bAction *act= G.saction->action; + bActionGroup *agrp; + bActionChannel *achan; + + printf("Debug Action Grouping: \n"); + + printf("\tGroups: \n"); + for (agrp= act->groups.first; agrp; agrp= agrp->next) { + printf("\t\tGroup \"%s\" : %p... start={%p} end={%p} \n", agrp->name, agrp, agrp->channels.first, agrp->channels.last); + } + + printf("\tAction Channels: \n"); + for (achan= act->chanbase.first; achan; achan= achan->next) { + printf("\t\tAchan \"%s\" : %p... group={%p} \n", achan->name, achan, achan->grp); + } } + + /* Transforms */ else { - if (mval[0]>=ACTWIDTH) - transform_action_keys('g', 0); + if (mval[0] >= ACTWIDTH) { + if (G.qual == LR_CTRLKEY) + transform_markers('g', 0); + else + transform_action_keys('g', 0); + } } break; @@ -3398,9 +4080,9 @@ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt) case PAGEUPKEY: if (datatype == ACTCONT_ACTION) { if (G.qual == (LR_CTRLKEY|LR_SHIFTKEY)) - top_sel_action(); + rearrange_action_channels(REARRANGE_ACTCHAN_TOP); else if (G.qual == LR_SHIFTKEY) - up_sel_action(); + rearrange_action_channels(REARRANGE_ACTCHAN_UP); else if (G.qual == LR_CTRLKEY) nextprev_action_keyframe(1); else @@ -3417,9 +4099,9 @@ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt) case PAGEDOWNKEY: if (datatype == ACTCONT_ACTION) { if (G.qual == (LR_CTRLKEY|LR_SHIFTKEY)) - bottom_sel_action(); + rearrange_action_channels(REARRANGE_ACTCHAN_BOTTOM); else if (G.qual == LR_SHIFTKEY) - down_sel_action(); + rearrange_action_channels(REARRANGE_ACTCHAN_DOWN); else if (G.qual == LR_CTRLKEY) nextprev_action_keyframe(-1); else @@ -3445,11 +4127,7 @@ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt) if (mval[0] >= NAMEWIDTH) remove_marker(); - allqueue(REDRAWTIME, 0); - allqueue(REDRAWIPO, 0); - allqueue(REDRAWACTION, 0); - allqueue(REDRAWNLA, 0); - allqueue(REDRAWSOUND, 0); + allqueue(REDRAWMARKER, 0); } break; diff --git a/source/blender/src/editgroup.c b/source/blender/src/editgroup.c index b17e6efee1b..4dfa339ed15 100644 --- a/source/blender/src/editgroup.c +++ b/source/blender/src/editgroup.c @@ -119,8 +119,8 @@ void rem_selected_from_group(void) for(base=FIRSTBASE; base; base= base->next) { if TESTBASE(base) { - - while( (group = find_group(base->object)) ) { + group = NULL; + while( (group = find_group(base->object, group)) ) { rem_from_group(group, base->object); } base->object->flag &= ~OB_FROMGROUP; diff --git a/source/blender/src/editimasel.c b/source/blender/src/editimasel.c index cf6a86917b7..ed630af2088 100644 --- a/source/blender/src/editimasel.c +++ b/source/blender/src/editimasel.c @@ -195,7 +195,7 @@ static void activate_imageselect_(int type, char *title, char *file, short *menu simasel->files = BIF_filelist_new(); } - if(G.relbase_valid && BLI_convertstringcode(name, G.sce, G.scene->r.cfra)) + if(G.relbase_valid && U.flag & USER_RELPATHS && type != FILE_BLENDER) simasel->flag |= FILE_STRINGCODE; else simasel->flag &= ~FILE_STRINGCODE; diff --git a/source/blender/src/editipo.c b/source/blender/src/editipo.c index bf0bfaef595..612d9f59b92 100644 --- a/source/blender/src/editipo.c +++ b/source/blender/src/editipo.c @@ -86,6 +86,7 @@ #include "BKE_particle.h" #include "BKE_texture.h" #include "BKE_utildefines.h" +#include "BKE_object.h" #include "BIF_butspace.h" #include "BIF_editaction.h" @@ -1052,8 +1053,10 @@ static void get_ipo_context(short blocktype, ID **from, Ipo **ipo, char *actname if(ob->action) { if(ob->flag & OB_POSEMODE) { bPoseChannel *pchan= get_active_posechannel(ob); - if(pchan) + if(pchan) { BLI_strncpy(actname, pchan->name, 32); + BLI_strncpy(bonename, pchan->name, 32); + } } else if(ob->ipoflag & OB_ACTION_OB) strcpy(actname, "Object"); @@ -1473,6 +1476,9 @@ void mouse_select_ipo(void) } if(G.sipo->showkey) { + float pixelwidth; + pixelwidth= (G.v2d->cur.xmax-G.v2d->cur.xmin)/(G.v2d->mask.xmax-G.v2d->mask.xmin); /* could make a generic function */ + getmouseco_areawin(mval); areamouseco_to_ipoco(G.v2d, mval, &x, &y); @@ -1481,7 +1487,7 @@ void mouse_select_ipo(void) ik= G.sipo->ipokey.first; while(ik) { dist= (float)(fabs(ik->val-x)); - if(ik->flag & 1) dist+= 1.0; + if(ik->flag & SELECT) dist+= pixelwidth; if(dist < mindist) { actik= ik; mindist= dist; @@ -2333,9 +2339,9 @@ static void insertkey_nonrecurs(ID *id, int blocktype, char *actname, char *cons if( GS(id->name)==ID_OB ) { ob= (Object *)id; - if(ob->sf!=0.0 && (ob->ipoflag & OB_OFFS_OB) ) { + if((ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)!=0.0) ) { /* actually frametofloat calc again! */ - cfra-= ob->sf*G.scene->r.framelen; + cfra-= give_timeoffset(ob)*G.scene->r.framelen; } } @@ -2554,9 +2560,9 @@ void insertkey(ID *id, int blocktype, char *actname, char *constname, int adrcod if( GS(id->name)==ID_OB ) { ob= (Object *)id; - if(ob->sf!=0.0 && (ob->ipoflag & OB_OFFS_OB) ) { + if((ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)!=0.0) ) { /* actually frametofloat calc again! */ - cfra-= ob->sf*G.scene->r.framelen; + cfra-= give_timeoffset(ob)*G.scene->r.framelen; } } @@ -2596,9 +2602,9 @@ void insertkey_smarter(ID *id, int blocktype, char *actname, char *constname, in if( GS(id->name)==ID_OB ) { ob= (Object *)id; - if(ob->sf!=0.0 && (ob->ipoflag & OB_OFFS_OB) ) { + if((ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)!=0.0) ) { /* actually frametofloat calc again! */ - cfra-= ob->sf*G.scene->r.framelen; + cfra-= give_timeoffset(ob)*G.scene->r.framelen; } } @@ -2647,9 +2653,9 @@ void insertfloatkey(ID *id, int blocktype, char *actname, char *constname, int a if( GS(id->name)==ID_OB ) { ob= (Object *)id; - if(ob->sf!=0.0 && (ob->ipoflag & OB_OFFS_OB) ) { + if((ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)!=0.0) ) { /* actually frametofloat calc again! */ - cfra-= ob->sf*G.scene->r.framelen; + cfra-= give_timeoffset(ob)*G.scene->r.framelen; } } @@ -2729,8 +2735,8 @@ void insertkey_editipo(void) id= G.sipo->from; if(id && GS(id->name)==ID_OB ) { Object *ob= (Object *)id; - if(ob->sf!=0.0 && (ob->ipoflag & OB_OFFS_OB) ) { - cfra-= ob->sf*G.scene->r.framelen; + if((ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)!=0.0) ) { + cfra-= give_timeoffset(ob)*G.scene->r.framelen; } } else if(id && GS(id->name)==ID_SEQ) { @@ -5767,8 +5773,8 @@ void move_to_frame(void) id= G.sipo->from; if(id && GS(id->name)==ID_OB ) { Object *ob= (Object *)id; - if(ob->sf!=0.0 && (ob->ipoflag & OB_OFFS_OB) ) { - cfra+= ob->sf/G.scene->r.framelen; + if((ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)!=0.0) ) { + cfra+= give_timeoffset(ob)/G.scene->r.framelen; } } CFRA= (int)floor(cfra+0.5); diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c index 4690c96b41f..7b3a1a24188 100644 --- a/source/blender/src/editobject.c +++ b/source/blender/src/editobject.c @@ -92,6 +92,7 @@ #include "BLI_arithb.h" #include "BLI_editVert.h" #include "BLI_ghash.h" +#include "BLI_rand.h" #include "BKE_action.h" #include "BKE_anim.h" @@ -1430,7 +1431,7 @@ void make_parent(void) add_constraint_to_object(con, base->object); - get_constraint_target_matrix(con, 0, CONSTRAINT_OBTYPE_OBJECT, NULL, cmat, G.scene->r.cfra - base->object->sf); + get_constraint_target_matrix(con, 0, CONSTRAINT_OBTYPE_OBJECT, NULL, cmat, G.scene->r.cfra - give_timeoffset(base->object)); VecSubf(vec, base->object->obmat[3], cmat[3]); base->object->loc[0] = vec[0]; @@ -5467,6 +5468,57 @@ void auto_timeoffs(void) allqueue(REDRAWBUTSOBJECT, 0); } +void ofs_timeoffs(void) +{ + Base *base; + float offset=0.0f; + + if(BASACT==0 || G.vd==NULL) return; + + if(fbutton(&offset, -10000.0f, 10000.0f, 10, 10, "Offset")==0) return; + + /* make array of all bases, xco yco (screen) */ + base= FIRSTBASE; + while(base) { + if(TESTBASELIB(base)) { + base->object->sf += offset; + if (base->object->sf < -MAXFRAMEF) base->object->sf = -MAXFRAMEF; + else if (base->object->sf > MAXFRAMEF) base->object->sf = MAXFRAMEF; + } + base= base->next; + } + + allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWBUTSOBJECT, 0); +} + + +void rand_timeoffs(void) +{ + Base *base; + float rand=0.0f; + + if(BASACT==0 || G.vd==NULL) return; + + if(fbutton(&rand, 0.0f, 10000.0f, 10, 10, "Randomize")==0) return; + + rand *= 2; + + base= FIRSTBASE; + while(base) { + if(TESTBASELIB(base)) { + base->object->sf += (BLI_drand()-0.5) * rand; + if (base->object->sf < -MAXFRAMEF) base->object->sf = -MAXFRAMEF; + else if (base->object->sf > MAXFRAMEF) base->object->sf = MAXFRAMEF; + } + base= base->next; + } + + allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWBUTSOBJECT, 0); +} + + void texspace_edit(void) { Base *base; diff --git a/source/blender/src/editparticle.c b/source/blender/src/editparticle.c index eb98f3243f7..feca286fb61 100644 --- a/source/blender/src/editparticle.c +++ b/source/blender/src/editparticle.c @@ -80,6 +80,7 @@ #include "BIF_interface.h" #include "BIF_meshtools.h" #include "BIF_mywindow.h" +#include "BIF_radialcontrol.h" #include "BIF_resources.h" #include "BIF_screen.h" #include "BIF_space.h" @@ -1989,6 +1990,46 @@ void PE_remove_doubles(void) BIF_undo_push("Remove double particles"); } +static void PE_radialcontrol_callback(const int mode, const int val) +{ + ParticleEditSettings *pset = PE_settings(); + + if(pset->brushtype>=0) { + ParticleBrushData *brush= &pset->brush[pset->brushtype]; + + if(mode == RADIALCONTROL_SIZE) + brush->size = val; + else if(mode == RADIALCONTROL_STRENGTH) + brush->strength = val; + } + + (*PE_radialcontrol()) = NULL; +} + +RadialControl **PE_radialcontrol() +{ + static RadialControl *rc = NULL; + return &rc; +} + +void PE_radialcontrol_start(const int mode) +{ + ParticleEditSettings *pset = PE_settings(); + int orig= 1; + + if(pset->brushtype>=0) { + ParticleBrushData *brush= &pset->brush[pset->brushtype]; + + if(mode == RADIALCONTROL_SIZE) + orig = brush->size; + else if(mode == RADIALCONTROL_STRENGTH) + orig = brush->strength; + + if(mode != RADIALCONTROL_NONE) + (*PE_radialcontrol())= radialcontrol_start(mode, PE_radialcontrol_callback, orig, 100, 0); + } +} + /************************************************/ /* Edit Brushes */ /************************************************/ diff --git a/source/blender/src/editseq.c b/source/blender/src/editseq.c index a85f4cb5874..d07d733ce90 100644 --- a/source/blender/src/editseq.c +++ b/source/blender/src/editseq.c @@ -111,9 +111,6 @@ char last_sounddir[FILE_MAXDIR+FILE_MAXFILE]= ""; #define SEQ_DESEL ~(SELECT+SEQ_LEFTSEL+SEQ_RIGHTSEL) -static int test_overlap_seq(Sequence *); -static void shuffle_seq(Sequence *); - typedef struct TransSeq { int start, machine; int startstill, endstill; @@ -537,7 +534,7 @@ void update_seq_icu_rects(Sequence * seq) } } -static int test_overlap_seq(Sequence *test) +int test_overlap_seq(Sequence *test) { Sequence *seq; Editing *ed; @@ -560,7 +557,7 @@ static int test_overlap_seq(Sequence *test) return 0; } -static void shuffle_seq(Sequence *test) +void shuffle_seq(Sequence *test) { Editing *ed; Sequence *seq; @@ -2875,10 +2872,10 @@ static void transform_grab_xlimits(Sequence *seq, int leftflag, int rightflag) static int can_transform_seq_test_func(Sequence * seq) { - if((seq->flag & SELECT) && !(seq->flag & SEQ_LOCK)) { + if((seq->flag & SELECT) && !(seq->depth==0 && seq->flag & SEQ_LOCK)) { return BUILD_SEQAR_COUNT_CURRENT | BUILD_SEQAR_COUNT_CHILDREN; } - if ((seq->flag & SEQ_LOCK) && !(seq->type & SEQ_EFFECT)) { + if ((seq->depth==0 && seq->flag & SEQ_LOCK) && !(seq->type & SEQ_EFFECT)) { if (seq->type != SEQ_META) { return BUILD_SEQAR_COUNT_NOTHING; } else { @@ -2937,7 +2934,7 @@ void transform_seq(int mode, int context) if (seqar) { for(seq_index=0, seq=seqar[0]; seq_index < totseq_index; seq=seqar[++seq_index]) { - if((seq->flag & SELECT) && !(seq->flag & SEQ_LOCK)) + if((seq->flag & SELECT) && !(seq->depth==0 && seq->flag & SEQ_LOCK)) totstrip++; } } @@ -2960,7 +2957,7 @@ void transform_seq(int mode, int context) ts=transmain= MEM_callocN(totstrip*sizeof(TransSeq), "transseq"); for(seq_index=0, seq=seqar[0]; seq_index < totseq_index; seq=seqar[++seq_index]) { - if((seq->flag & SELECT) && !(seq->flag & SEQ_LOCK)) { + if((seq->flag & SELECT) && !(seq->depth==0 && seq->flag & SEQ_LOCK)) { ts->start= seq->start; ts->machine= seq->machine; ts->startstill= seq->startstill; @@ -3146,7 +3143,7 @@ void transform_seq(int mode, int context) if (mode=='g' && !snapskip) { /* Grab */ for(seq_index=0, seq=seqar[0]; seq_index < totseq_index; seq=seqar[++seq_index]) { - if(seq->flag & SELECT && !(seq->flag & SEQ_LOCK)) { + if(seq->flag & SELECT && !(seq->depth==0 && seq->flag & SEQ_LOCK)) { int myofs; // SEQ_DEBUG_INFO(seq); @@ -3198,7 +3195,7 @@ void transform_seq(int mode, int context) /* Extend, Similar to grab but operate on one side of the cursor */ for(seq_index=0, seq=seqar[0]; seq_index < totseq_index; seq=seqar[++seq_index]) { - if(seq->flag & SELECT && !(seq->flag & SEQ_LOCK)) { + if(seq->flag & SELECT && !(seq->depth==0 && seq->flag & SEQ_LOCK)) { /* only move the contents of the metastrip otherwise the transformation is applied twice */ if (sequence_is_free_transformable(seq) && seq->type != SEQ_META) { @@ -3310,7 +3307,7 @@ void transform_seq(int mode, int context) /* test for effect and overlap */ for(seq_index=0, seq=seqar[0]; seq_index < totseq_index; seq=seqar[++seq_index]) { - if(seq->flag & SELECT && !(seq->flag & SEQ_LOCK)) { + if((seq->depth==0) && (seq->flag & SELECT) && !(seq->depth==0 && seq->flag & SEQ_LOCK)) { seq->flag &= ~SEQ_OVERLAP; if( test_overlap_seq(seq) ) { seq->flag |= SEQ_OVERLAP; @@ -3322,7 +3319,9 @@ void transform_seq(int mode, int context) else if(seq->seq3 && seq->seq3->flag & SELECT) calc_sequence(seq); } } - + /* warning, drawing should NEVER use WHILE_SEQ, + if it does the seq->depth value will be messed up and + overlap checks with metastrips will give incorrect results */ force_draw(0); } @@ -3359,7 +3358,7 @@ void transform_seq(int mode, int context) ts= transmain; for(seq_index=0, seq=seqar[0]; seq_index < totseq_index; seq=seqar[++seq_index]) { - if(seq->flag & SELECT && !(seq->flag & SEQ_LOCK)) { + if(seq->flag & SELECT && !(seq->depth==0 && seq->flag & SEQ_LOCK)) { seq->start= ts->start; seq->machine= ts->machine; seq->startstill= ts->startstill; @@ -3377,7 +3376,7 @@ void transform_seq(int mode, int context) else if(seq->seq3 && seq->seq3->flag & SELECT) calc_sequence(seq); } } - + /* Markers */ if (sseq->flag & SEQ_MARKER_TRANS) { for(a=0, marker= G.scene->markers.first; marker; marker= marker->next) { @@ -3643,7 +3642,7 @@ void seq_snap(short event) /* also check metas */ WHILE_SEQ(ed->seqbasep) { - if (seq->flag & SELECT && !(seq->flag & SEQ_LOCK) && + if (seq->flag & SELECT && !(seq->depth==0 && seq->flag & SEQ_LOCK) && sequence_is_free_transformable(seq)) { if((seq->flag & (SEQ_LEFTSEL+SEQ_RIGHTSEL))==0) { seq->start= CFRA-seq->startofs+seq->startstill; @@ -3662,7 +3661,7 @@ void seq_snap(short event) /* test for effects and overlap */ WHILE_SEQ(ed->seqbasep) { - if(seq->flag & SELECT && !(seq->flag & SEQ_LOCK)) { + if(seq->flag & SELECT && !(seq->depth==0 && seq->flag & SEQ_LOCK)) { seq->flag &= ~SEQ_OVERLAP; if( test_overlap_seq(seq) ) { shuffle_seq(seq); @@ -3686,6 +3685,23 @@ void seq_snap(short event) allqueue(REDRAWSEQ, 0); } +void seq_mute_sel(int mute) { + Editing *ed; + Sequence *seq; + + ed= G.scene->ed; + if(!ed) return NULL; + + for(seq= ed->seqbasep->first; seq; seq= seq->next) { + if ((seq->flag & SELECT) && (seq->flag & SEQ_LOCK)==0) { + if (mute) seq->flag |= SEQ_MUTE; + else seq->flag &= ~SEQ_MUTE; + } + } + BIF_undo_push(mute?"Mute Strips, Sequencer":"UnMute Strips, Sequencer"); + allqueue(REDRAWSEQ, 0); +} + void borderselect_seq(void) { Sequence *seq; diff --git a/source/blender/src/filesel.c b/source/blender/src/filesel.c index d6bbedec2b3..8a9b5b4d2b8 100644 --- a/source/blender/src/filesel.c +++ b/source/blender/src/filesel.c @@ -1192,7 +1192,7 @@ static void activate_fileselect_(int type, char *title, char *file, short *menup /* sfile->act is used for databrowse: double names of library objects */ sfile->act= -1; - if(G.relbase_valid && BLI_convertstringcode(name, G.sce, G.scene->r.cfra)) + if(G.relbase_valid && U.flag & USER_RELPATHS && type != FILE_BLENDER) sfile->flag |= FILE_STRINGCODE; else sfile->flag &= ~FILE_STRINGCODE; diff --git a/source/blender/src/header_action.c b/source/blender/src/header_action.c index c9edd6cd1f0..f9a3fb08bd8 100644 --- a/source/blender/src/header_action.c +++ b/source/blender/src/header_action.c @@ -133,6 +133,12 @@ enum { ACTMENU_KEY_CHANPOS_MOVE_CHANNEL_BOTTOM }; +enum { + ACTMENU_KEY_CHANGROUP_ADD_TOACTIVE = 0, + ACTMENU_KEY_CHANGROUP_ADD_TONEW, + ACTMENU_KEY_CHANGROUP_REMOVE +}; + enum { ACTMENU_KEY_TRANSFORM_MOVE = 0, ACTMENU_KEY_TRANSFORM_SCALE, @@ -466,35 +472,19 @@ static uiBlock *action_viewmenu(void *arg_unused) static void do_action_selectmenu_columnmenu(void *arg, int event) { - SpaceAction *saction; - bAction *act; - Key *key; - - saction = curarea->spacedata.first; - if (!saction) return; - - act = saction->action; - key = get_action_mesh_key(); - -#if 0 // actionrewite - if (event == ACTMENU_SEL_COLUMN_MARKERSBETWEEN) { - markers_selectkeys_between(); + switch (event) { + case ACTMENU_SEL_COLUMN_MARKERSBETWEEN: + markers_selectkeys_between(); + break; + case ACTMENU_SEL_COLUMN_KEYS: + column_select_action_keys(1); + break; + case ACTMENU_SEL_COLUMN_MARKERSCOLUMN: + column_select_action_keys(2); + break; } - else if (ELEM(event, ACTMENU_SEL_COLUMN_KEYS, ACTMENU_SEL_COLUMN_MARKERSCOLUMN)) { - if (act) - column_select_actionkeys(act, event); - else if (key) - column_select_shapekeys(key, event); - } - else - return; -#endif // actionrewite - allqueue(REDRAWTIME, 0); - allqueue(REDRAWIPO, 0); - allqueue(REDRAWACTION, 0); - allqueue(REDRAWNLA, 0); - allqueue(REDRAWSOUND, 0); + allqueue(REDRAWMARKER, 0); } static uiBlock *action_selectmenu_columnmenu(void *arg_unused) @@ -871,16 +861,16 @@ static void do_action_keymenu_chanposmenu(void *arg, int event) switch(event) { case ACTMENU_KEY_CHANPOS_MOVE_CHANNEL_DOWN: - down_sel_action(); + rearrange_action_channels(REARRANGE_ACTCHAN_DOWN); break; case ACTMENU_KEY_CHANPOS_MOVE_CHANNEL_UP: - up_sel_action(); + rearrange_action_channels(REARRANGE_ACTCHAN_UP); break; case ACTMENU_KEY_CHANPOS_MOVE_CHANNEL_TOP: - top_sel_action(); + rearrange_action_channels(REARRANGE_ACTCHAN_TOP); break; case ACTMENU_KEY_CHANPOS_MOVE_CHANNEL_BOTTOM: - bottom_sel_action(); + rearrange_action_channels(REARRANGE_ACTCHAN_BOTTOM); break; } @@ -923,6 +913,54 @@ static uiBlock *action_keymenu_chanposmenu(void *arg_unused) return block; } +static void do_action_keymenu_changroupmenu(void *arg, int event) +{ + switch(event) + { + case ACTMENU_KEY_CHANGROUP_ADD_TOACTIVE: + action_groups_group(0); + break; + case ACTMENU_KEY_CHANGROUP_ADD_TONEW: + action_groups_group(1); + break; + case ACTMENU_KEY_CHANGROUP_REMOVE: + action_groups_ungroup(); + break; + } +} + +static uiBlock *action_keymenu_changroupmenu(void *arg_unused) +{ + uiBlock *block; + short yco= 0, menuwidth=120; + + block= uiNewBlock(&curarea->uiblocks, "action_keymenu_changroupmenu", + UI_EMBOSSP, UI_HELV, G.curscreen->mainwin); + uiBlockSetButmFunc(block, do_action_keymenu_changroupmenu, NULL); + + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, + "Add to Active Group|Shift G", 0, yco-=20, + menuwidth, 19, NULL, 0.0, 0.0, 0, + ACTMENU_KEY_CHANGROUP_ADD_TOACTIVE, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, + "Add To New Group|Ctrl Shift G", 0, yco-=20, + menuwidth, 19, NULL, 0.0, 0.0, 0, + ACTMENU_KEY_CHANGROUP_ADD_TONEW, ""); + + uiDefBut(block, SEPR, 0, "", 0, yco-=6, + menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); + + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, + "Remove From Group|Alt G", 0, yco-=20, + menuwidth, 19, NULL, 0.0, 0.0, 0, + ACTMENU_KEY_CHANGROUP_REMOVE, ""); + + uiBlockSetDirection(block, UI_RIGHT); + uiTextBoundsBlock(block, 60); + + return block; +} + static void do_action_keymenu_snapmenu(void *arg, int event) { switch(event) @@ -1125,6 +1163,14 @@ static uiBlock *action_keymenu(void *arg_unused) uiDefIconTextBlockBut(block, action_keymenu_intpolmenu, NULL, ICON_RIGHTARROW_THIN, "Interpolation Mode", 0, yco-=20, 120, 20, ""); + + uiDefBut(block, SEPR, 0, "", 0, yco-=6, + menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); + + uiDefIconTextBlockBut(block, action_keymenu_changroupmenu, + NULL, ICON_RIGHTARROW_THIN, + "Channel Grouping", 0, yco-=20, 120, 20, ""); + uiDefIconTextBlockBut(block, action_keymenu_chanposmenu, NULL, ICON_RIGHTARROW_THIN, "Channel Ordering", 0, yco-=20, 120, 20, ""); diff --git a/source/blender/src/header_filesel.c b/source/blender/src/header_filesel.c index 999fa2733af..7591a6e7e21 100644 --- a/source/blender/src/header_filesel.c +++ b/source/blender/src/header_filesel.c @@ -136,10 +136,13 @@ void file_buttons(void) uiDefIconButBitS(block, TOG, FILE_HIDE_DOT, B_RELOADDIR, ICON_GHOST,xco+=XIC,0,XIC,YIC, &sfile->flag, 0, 0, 0, 0, "Hides dot files"); uiBlockEndAlign(block); - uiDefButBitS(block, TOG, FILE_STRINGCODE, 0, "Relative Paths", xco+=XIC+20,0,100,YIC, &sfile->flag, 0, 0, 0, 0, "Makes sure returned paths are relative to the current .blend file"); - - xco+=90; - + if(sfile->type==FILE_BLENDER) { + xco+=20; + } else { + uiDefButBitS(block, TOG, FILE_STRINGCODE, 0, "Relative Paths", xco+=XIC+20,0,100,YIC, &sfile->flag, 0, 0, 0, 0, "Makes sure returned paths are relative to the current .blend file"); + xco+=90; + } + if(sfile->type==FILE_LOADLIB) { uiBlockBeginAlign(block); uiDefButBitS(block, TOGN, FILE_LINK, B_REDR, "Append", xco+=XIC,0,100,YIC, &sfile->flag, 0, 0, 0, 0, "Copies selected data into current project"); diff --git a/source/blender/src/header_imasel.c b/source/blender/src/header_imasel.c index 3968cff4757..bd09416e1ba 100644 --- a/source/blender/src/header_imasel.c +++ b/source/blender/src/header_imasel.c @@ -181,9 +181,13 @@ void imasel_buttons(void) uiBlockEndAlign(block); } } - - uiDefButBitS(block, TOG, FILE_STRINGCODE, 0, "Relative Paths", xco+=XIC+20,0,100,YIC, &simasel->flag, 0, 0, 0, 0, "Makes sure returned paths are relative to the current .blend file"); - xco+=90; + + if(simasel->type==FILE_BLENDER) { + xco+=20; + } else { + uiDefButBitS(block, TOG, FILE_STRINGCODE, 0, "Relative Paths", xco+=XIC+20,0,100,YIC, &simasel->flag, 0, 0, 0, 0, "Makes sure returned paths are relative to the current .blend file"); + xco+=90; + } if(simasel->type==FILE_LOADLIB) { uiBlockBeginAlign(block); diff --git a/source/blender/src/header_view3d.c b/source/blender/src/header_view3d.c index 8102e60c7fb..1c39d286989 100644 --- a/source/blender/src/header_view3d.c +++ b/source/blender/src/header_view3d.c @@ -113,6 +113,7 @@ #include "BIF_meshtools.h" #include "BIF_poselib.h" #include "BIF_poseobject.h" +#include "BIF_radialcontrol.h" #include "BIF_renderwin.h" #include "BIF_resources.h" #include "BIF_retopo.h" @@ -1767,6 +1768,9 @@ static void do_view3d_transformmenu(void *arg, int event) case 19: G.scene->snap_target = SCE_SNAP_TARGET_MEDIAN; break; + case 20: + G.scene->snap_target = SCE_SNAP_TARGET_ACTIVE; + break; } allqueue(REDRAWVIEW3D, 0); } @@ -1838,19 +1842,28 @@ static uiBlock *view3d_transformmenu(void *arg_unused) switch(G.scene->snap_target) { case SCE_SNAP_TARGET_CLOSEST: - uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Snap Closest", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 17, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Snap Closest", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 17, ""); uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Snap Center", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 18, ""); uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Snap Median", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 19, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Snap Active", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 20, ""); break; case SCE_SNAP_TARGET_CENTER: uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Snap Closest", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 17, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Snap Center", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 18, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Snap Center", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 18, ""); uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Snap Median", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 19, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Snap Active", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 20, ""); break; case SCE_SNAP_TARGET_MEDIAN: uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Snap Closest", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 17, ""); uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Snap Center", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 18, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Snap Median", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 19, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Snap Median", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 19, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Snap Active", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 20, ""); + break; + case SCE_SNAP_TARGET_ACTIVE: + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Snap Closest", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 17, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Snap Center", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 18, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Snap Median", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 19, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Snap Active", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 20, ""); break; } } @@ -4402,6 +4415,7 @@ void do_view3d_sculptmenu(void *arg, int event) { SculptData *sd= &G.scene->sculptdata; BrushData *br= sculptmode_brush(); + switch(event) { case 0: case 1: @@ -4445,13 +4459,13 @@ void do_view3d_sculptmenu(void *arg, int event) add_blockhandler(curarea, VIEW3D_HANDLER_OBJECT, UI_PNL_UNSTOW); break; case 15: - sculptmode_propset_init(PropsetTexRot); + sculpt_radialcontrol_start(RADIALCONTROL_ROTATION); break; case 16: - sculptmode_propset_init(PropsetStrength); + sculpt_radialcontrol_start(RADIALCONTROL_STRENGTH); break; case 17: - sculptmode_propset_init(PropsetSize); + sculpt_radialcontrol_start(RADIALCONTROL_SIZE); break; case 18: br->dir= br->dir==1 ? 2 : 1; @@ -5482,7 +5496,7 @@ void view3d_buttons(void) if (G.scene->snap_flag & SCE_SNAP) { uiDefIconButBitS(block, TOG, SCE_SNAP, B_REDR, ICON_SNAP_GEO,xco,0,XIC,YIC, &G.scene->snap_flag, 0, 0, 0, 0, "Use Snap or Grid (Shift Tab)"); xco+= XIC; - uiDefButS(block, MENU, B_NOP, "Mode%t|Closest%x0|Center%x1|Median%x2",xco,0,70,YIC, &G.scene->snap_target, 0, 0, 0, 0, "Snap Target Mode"); + uiDefButS(block, MENU, B_NOP, "Mode%t|Closest%x0|Center%x1|Median%x2|Active%x3",xco,0,70,YIC, &G.scene->snap_target, 0, 0, 0, 0, "Snap Target Mode"); xco+= 70; } else { uiDefIconButBitS(block, TOG, SCE_SNAP, B_REDR, ICON_SNAP_GEAR,xco,0,XIC,YIC, &G.scene->snap_flag, 0, 0, 0, 0, "Snap while Ctrl is held during transform (Shift Tab)"); diff --git a/source/blender/src/outliner.c b/source/blender/src/outliner.c index f0d23f9988a..ed910607040 100644 --- a/source/blender/src/outliner.c +++ b/source/blender/src/outliner.c @@ -444,6 +444,10 @@ static void outliner_add_passes(SpaceOops *soops, TreeElement *tenla, ID *id, Sc te->name= "UV"; te->directdata= &srl->passflag; + te= outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, SCE_PASS_MIST); + te->name= "Mist"; + te->directdata= &srl->passflag; + te= outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, SCE_PASS_INDEXOB); te->name= "Index Object"; te->directdata= &srl->passflag; diff --git a/source/blender/src/poselib.c b/source/blender/src/poselib.c index 441ba0eab52..44277e17804 100644 --- a/source/blender/src/poselib.c +++ b/source/blender/src/poselib.c @@ -27,6 +27,7 @@ #include #include +#include #include #include @@ -345,7 +346,7 @@ void poselib_add_current_pose (Object *ob, int val) /* get/initialise poselib */ act= poselib_validate(ob); - /* validate name and get frame */ + /* get frame */ frame= poselib_get_free_index(act); /* add pose to poselib - replaces any existing pose there */ @@ -363,6 +364,9 @@ void poselib_add_current_pose (Object *ob, int val) BLI_addtail(&act->markers, marker); } + + /* validate name */ + BLI_uniquename(&act->markers, marker, "Pose", offsetof(TimeMarker, name), 64); } /* loop through selected posechannels, keying their pose to the action */ @@ -504,8 +508,9 @@ void poselib_rename_pose (Object *ob) if (sbutton(name, 0, sizeof(name)-1, "Name: ") == 0) return; - /* copy name */ + /* copy name and validate it */ BLI_strncpy(marker->name, name, sizeof(marker->name)); + BLI_uniquename(&act->markers, marker, "Pose", offsetof(TimeMarker, name), 64); /* undo and update */ BIF_undo_push("PoseLib Rename Pose"); diff --git a/source/blender/src/radialcontrol.c b/source/blender/src/radialcontrol.c new file mode 100644 index 00000000000..5e44d28f08f --- /dev/null +++ b/source/blender/src/radialcontrol.c @@ -0,0 +1,267 @@ +/* + * $Id: multires.c 13015 2007-12-27 07:27:03Z nicholasbishop $ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2006 by Nicholas Bishop + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + * + * Implements the multiresolution modeling tools. + * + * multires.h + * + */ + +#include "MEM_guardedalloc.h" + +#include "BIF_gl.h" +#include "BIF_glutil.h" +#include "BIF_mywindow.h" +#include "BIF_screen.h" +#include "BIF_space.h" +#include "BIF_radialcontrol.h" + +#include "BKE_global.h" +#include "BLI_arithb.h" + +#include "mydevice.h" +#include "transform.h" + +#include "math.h" + +/* Prints the value being edited in the view header */ +static void radialcontrol_header(const RadialControl *rc) +{ + if(rc) { + char str[512]; + const char *name= ""; + + if(rc->mode == RADIALCONTROL_SIZE) + name= "Size"; + else if(rc->mode == RADIALCONTROL_STRENGTH) + name= "Strength"; + else if(rc->mode == RADIALCONTROL_ROTATION) + name= "Angle"; + + sprintf(str, "%s: %d", name, (int)(rc->new_value)); + headerprint(str); + } +} + +/* Creates, initializes, and returns the control */ +RadialControl *radialcontrol_start(const int mode, RadialControlCallback callback, + const int original_value, const int max_value, + const unsigned int tex) +{ + RadialControl *rc= MEM_callocN(sizeof(RadialControl), "radial control"); + short mouse[2]; + + getmouseco_areawin(mouse); + rc->origloc[0]= mouse[0]; + rc->origloc[1]= mouse[1]; + + if(mode == RADIALCONTROL_SIZE) + rc->origloc[0]-= original_value; + else if(mode == RADIALCONTROL_STRENGTH) + rc->origloc[0]-= 200 - 2*original_value; + else if(mode == RADIALCONTROL_ROTATION) { + rc->origloc[0]-= 200 * cos(original_value * M_PI / 180.0); + rc->origloc[1]-= 200 * sin(original_value * M_PI / 180.0); + } + + rc->callback = callback; + rc->original_value = original_value; + rc->max_value = max_value; + + rc->tex = tex; + + /* NumInput is used for keyboard input */ + rc->num = MEM_callocN(sizeof(NumInput), "radialcontrol numinput"); + rc->num->idx_max= 0; + + rc->mode= mode; + radialcontrol_header(rc); + + allqueue(REDRAWVIEW3D, 0); + + return rc; +} + + +static void radialcontrol_end(RadialControl *rc) +{ + if(rc) { + rc->callback(rc->mode, rc->new_value); + BIF_undo_push("Brush property set"); + + /* Free everything */ + glDeleteTextures(1, (GLuint*)(&rc->tex)); + MEM_freeN(rc->num); + MEM_freeN(rc); + + allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWBUTSEDIT, 0); + allqueue(REDRAWHEADERS, 0); + } +} + +void radialcontrol_do_events(RadialControl *rc, unsigned short event) +{ + short mouse[2]; + short tmp[2]; + float dist; + char valset= 0; + + if(!rc) + return; + + handleNumInput(rc->num, event); + + if(hasNumInput(rc->num)) { + float val; + applyNumInput(rc->num, &val); + rc->new_value = val; + valset= 1; + allqueue(REDRAWVIEW3D, 0); + } + + switch(event) { + case MOUSEX: + case MOUSEY: + if(!hasNumInput(rc->num)) { + char ctrl= G.qual & LR_CTRLKEY; + getmouseco_areawin(mouse); + tmp[0]= rc->origloc[0]-mouse[0]; + tmp[1]= rc->origloc[1]-mouse[1]; + dist= sqrt(tmp[0]*tmp[0]+tmp[1]*tmp[1]); + if(rc->mode == RADIALCONTROL_SIZE) + rc->new_value = dist; + else if(rc->mode == RADIALCONTROL_STRENGTH) { + float fin= (200.0f - dist) * 0.5f; + rc->new_value= fin>=0 ? fin : 0; + } else if(rc->mode == RADIALCONTROL_ROTATION) + rc->new_value= ((int)(atan2(tmp[1], tmp[0]) * (180.0 / M_PI)) + 180); + + if(ctrl) + rc->new_value= (rc->new_value + 5) / 10*10; + + valset= 1; + allqueue(REDRAWVIEW3D, 0); + } + break; + case ESCKEY: + case RIGHTMOUSE: + rc->new_value = rc->original_value; + case LEFTMOUSE: + while(get_mbut()==L_MOUSE); + case RETKEY: + case PADENTER: + radialcontrol_end(rc); + return; + default: + break; + }; + + if(valset) { + if(rc->new_value > rc->max_value) + rc->new_value = rc->max_value; + } + + radialcontrol_header(rc); +} + +static void rot_line(const short o[2], const float ang) +{ + sdrawXORline(o[0], o[1], o[0] + 200*cos(ang), o[1] + 200*sin(ang)); +} + +void radialcontrol_draw(RadialControl *rc) +{ + short r1, r2, r3; + float angle = 0; + + if(rc && rc->mode) { + if(rc->mode == RADIALCONTROL_SIZE) { + r1= rc->new_value; + r2= rc->original_value; + r3= r1; + } else if(rc->mode == RADIALCONTROL_STRENGTH) { + r1= 200 - rc->new_value * 2; + r2= 200; + r3= 200; + } else if(rc->mode == RADIALCONTROL_ROTATION) { + r1= r2= 200; + r3= 200; + angle = rc->new_value; + } + + /* Draw brush with texture */ + glPushMatrix(); + glTranslatef(rc->origloc[0], rc->origloc[1], 0); + glRotatef(angle, 0, 0, 1); + + if(rc->tex) { + const float str = rc->mode == RADIALCONTROL_STRENGTH ? (rc->new_value / 200.0 + 0.5) : 1; + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glBindTexture(GL_TEXTURE_2D, rc->tex); + + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + glEnable(GL_TEXTURE_2D); + glBegin(GL_QUADS); + glColor4f(0,0,0, str); + glTexCoord2f(0,0); + glVertex2f(-r3, -r3); + glTexCoord2f(1,0); + glVertex2f(r3, -r3); + glTexCoord2f(1,1); + glVertex2f(r3, r3); + glTexCoord2f(0,1); + glVertex2f(-r3, r3); + glEnd(); + glDisable(GL_TEXTURE_2D); + } + + glPopMatrix(); + + if(r1 != r2) + fdrawXORcirc(rc->origloc[0], rc->origloc[1], r1); + fdrawXORcirc(rc->origloc[0], rc->origloc[1], r2); + + if(rc->mode == RADIALCONTROL_ROTATION) { + float ang1= rc->original_value * (M_PI/180.0f); + float ang2= rc->new_value * (M_PI/180.0f); + + if(rc->new_value > 359) + ang2 = 0; + + rot_line(rc->origloc, ang1); + if(ang1 != ang2) + rot_line(rc->origloc, ang2); + } + } +} diff --git a/source/blender/src/renderwin.c b/source/blender/src/renderwin.c index e97fdef27ff..46af717f2e3 100644 --- a/source/blender/src/renderwin.c +++ b/source/blender/src/renderwin.c @@ -1301,7 +1301,7 @@ void BIF_do_ogl_render(View3D *v3d, int anim) do_ogl_view3d_render(re, v3d, winx, winy); glReadPixels(0, 0, winx, winy, GL_RGBA, GL_UNSIGNED_BYTE, rr->rect32); if((G.scene->r.scemode & R_STAMP_INFO) && (G.scene->r.stamp & R_STAMP_DRAW)) { - BKE_stamp_buf((unsigned char *)rr->rect32, rr->rectf, rr->rectx, rr->recty); + BKE_stamp_buf((unsigned char *)rr->rect32, rr->rectf, rr->rectx, rr->recty, 3); } window_swap_buffers(render_win->win); @@ -1343,7 +1343,7 @@ void BIF_do_ogl_render(View3D *v3d, int anim) do_ogl_view3d_render(re, v3d, winx, winy); glReadPixels(0, 0, winx, winy, GL_RGBA, GL_UNSIGNED_BYTE, rr->rect32); if((G.scene->r.scemode & R_STAMP_INFO) && (G.scene->r.stamp & R_STAMP_DRAW)) { - BKE_stamp_buf((unsigned char *)rr->rect32, rr->rectf, rr->rectx, rr->recty); + BKE_stamp_buf((unsigned char *)rr->rect32, rr->rectf, rr->rectx, rr->recty, 3); } window_swap_buffers(render_win->win); } diff --git a/source/blender/src/resources.c b/source/blender/src/resources.c index 25295f4cd3c..0d22ce8744e 100644 --- a/source/blender/src/resources.c +++ b/source/blender/src/resources.c @@ -453,6 +453,8 @@ void BIF_InitTheme(void) SETCOL(btheme->tact.hilite, 17, 27, 60, 100); // bar SETCOL(btheme->tact.strip_select, 0xff, 0xff, 0xaa, 255); SETCOL(btheme->tact.strip, 0xe4, 0x9c, 0xc6, 255); + SETCOL(btheme->tact.group, 0x39, 0x7d, 0x1b, 255); + SETCOL(btheme->tact.group_active, 0x7d, 0xe9, 0x60, 255); /* space nla */ btheme->tnla= btheme->tv3d; @@ -643,6 +645,8 @@ char *BIF_ThemeColorsPup(int spacetype) str += sprintf(str, "View Sliders %%x%d|", TH_SHADE1); str += sprintf(str, "Channels %%x%d|", TH_SHADE2); str += sprintf(str, "Channels Selected %%x%d|", TH_HILITE); + str += sprintf(str, "Channel Group %%x%d|", TH_GROUP); + str += sprintf(str, "Active Channel Group %%x%d|", TH_GROUP_ACTIVE); str += sprintf(str, "Long Key %%x%d|", TH_STRIP); str += sprintf(str, "Long Key selected %%x%d|", TH_STRIP_SELECT); str += sprintf(str, "Current Frame %%x%d", TH_CFRAME); diff --git a/source/blender/src/sculptmode.c b/source/blender/src/sculptmode.c index a1341fd60c3..55626be8cfa 100644 --- a/source/blender/src/sculptmode.c +++ b/source/blender/src/sculptmode.c @@ -76,6 +76,7 @@ #include "BIF_gl.h" #include "BIF_interface.h" #include "BIF_mywindow.h" +#include "BIF_radialcontrol.h" #include "BIF_resources.h" #include "BIF_screen.h" #include "BIF_space.h" @@ -672,7 +673,7 @@ void flip_coord(float co[3], const char symm) } /* Use the warpfac field in MTex to store a rotation value for sculpt textures. Value is in degrees */ -float tex_angle(void) +float sculpt_tex_angle(void) { SculptData *sd= sculpt_data(); if(sd->texact!=-1 && sd->mtex[sd->texact]) @@ -737,7 +738,7 @@ float tex_strength(EditData *e, float *point, const float len,const unsigned vin else if(ss->texcache) { const short bsize= sculptmode_brush()->size * 2; const short half= sculptmode_brush()->size; - const float rot= to_rad(tex_angle()); + const float rot= to_rad(sculpt_tex_angle()); const unsigned tcw = ss->texcache_w, tch = ss->texcache_h; int px, py; unsigned i, *p; @@ -1224,147 +1225,85 @@ void sculptmode_set_strength(const int delta) sculptmode_brush()->strength= val; } -void sculptmode_propset_calctex() +static void sculpt_radialcontrol_callback(const int mode, const int val) +{ + SculptSession *ss = sculpt_session(); + BrushData *br = sculptmode_brush(); + + if(mode == RADIALCONTROL_SIZE) + br->size = val; + else if(mode == RADIALCONTROL_STRENGTH) + br->strength = val; + else if(mode == RADIALCONTROL_ROTATION) + set_tex_angle(val); + + ss->radialcontrol = NULL; +} + +/* Returns GL handle to brush texture */ +static GLuint sculpt_radialcontrol_calctex() { SculptData *sd= sculpt_data(); SculptSession *ss= sculpt_session(); - PropsetData *pd= sculpt_session()->propset; - if(pd) { - int i, j; - const int tsz = 128; - float *d; - if(!pd->texdata) { - pd->texdata= MEM_mallocN(sizeof(float)*tsz*tsz, "Brush preview"); - if(sd->texrept!=SCULPTREPT_3D) - sculptmode_update_tex(); - for(i=0; itexfade) - pd->texdata[i*tsz+j]= curve_strength(magn,tsz/2); - else - pd->texdata[i*tsz+j]= magn < tsz/2 ? 1 : 0; - } - if(sd->texact != -1 && ss->texcache) { - for(i=0; itexcache[i*tsz+j]; - pd->texdata[i*tsz+j]*= (((char*)&col)[0]+((char*)&col)[1]+((char*)&col)[2])/3.0f/255.0f; - } - } + int i, j; + const int tsz = 128; + float *texdata= MEM_mallocN(sizeof(float)*tsz*tsz, "Brush preview"); + GLuint tex; + + if(sd->texrept!=SCULPTREPT_3D) + sculptmode_update_tex(); + for(i=0; itexfade) + texdata[i*tsz+j]= curve_strength(magn,tsz/2); + else + texdata[i*tsz+j]= magn < tsz/2 ? 1 : 0; } - - /* Adjust alpha with brush strength */ - d= MEM_dupallocN(pd->texdata); + if(sd->texact != -1 && ss->texcache) { for(i=0; istrength/200.0f+0.5f; - - - if(!pd->tex) - glGenTextures(1, (GLuint *)&pd->tex); - glBindTexture(GL_TEXTURE_2D, pd->tex); - - glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, tsz, tsz, 0, GL_ALPHA, GL_FLOAT, d); - MEM_freeN(d); + for(j=0; jtexcache[i*tsz+j]; + texdata[i*tsz+j]*= (((char*)&col)[0]+((char*)&col)[1]+((char*)&col)[2])/3.0f/255.0f; + } } + + glGenTextures(1, &tex); + glBindTexture(GL_TEXTURE_2D, tex); + glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, tsz, tsz, 0, GL_ALPHA, GL_FLOAT, texdata); + MEM_freeN(texdata); + + return tex; } -void sculptmode_propset_header() +void sculpt_radialcontrol_start(int mode) { - SculptSession *ss= sculpt_session(); - PropsetData *pd= ss ? ss->propset : NULL; - if(pd) { - char str[512]; - const char *name= ""; - int val= 0; - if(pd->mode == PropsetSize) { - name= "Size"; - val= sculptmode_brush()->size; - } - else if(pd->mode == PropsetStrength) { - name= "Strength"; - val= sculptmode_brush()->strength; - } - else if(pd->mode == PropsetTexRot) { - name= "Texture Angle"; - val= tex_angle(); - } - sprintf(str, "Brush %s: %d", name, val); - headerprint(str); + SculptData *sd = sculpt_data(); + SculptSession *ss = sculpt_session(); + BrushData *br = sculptmode_brush(); + int orig=1, max=100; + + if(mode == RADIALCONTROL_SIZE) { + orig = br->size; + max = 200; } -} - -void sculptmode_propset_end(SculptSession *ss, int cancel) -{ - if(ss && ss->propset) { - PropsetData *pd= ss->propset; - - if(cancel) { - sculptmode_brush()->size= pd->origsize; - sculptmode_brush()->strength= pd->origstrength; - set_tex_angle(pd->origtexrot); - } else { - if(pd->mode != PropsetSize) - sculptmode_brush()->size= pd->origsize; - if(pd->mode != PropsetStrength) - sculptmode_brush()->strength= pd->origstrength; - if(pd->mode != PropsetTexRot) - set_tex_angle(pd->origtexrot); - - BIF_undo_push("Brush property set"); - } - glDeleteTextures(1, &pd->tex); - MEM_freeN(pd->num); - MEM_freeN(pd->texdata); - MEM_freeN(pd); - ss->propset= NULL; - allqueue(REDRAWVIEW3D, 0); - allqueue(REDRAWBUTSEDIT, 0); - allqueue(REDRAWHEADERS, 0); + else if(mode == RADIALCONTROL_STRENGTH) { + orig = br->strength; + max = 100; } -} - -void sculptmode_propset_init(PropsetMode mode) -{ - SculptSession *ss= sculpt_session(); - PropsetData *pd= ss->propset; - const float ang= tex_angle(); - - if(!pd) { - short mouse[2]; - - pd= MEM_callocN(sizeof(PropsetData),"PropsetSize"); - ss->propset= pd; - - getmouseco_areawin(mouse); - pd->origloc[0]= mouse[0]; - pd->origloc[1]= mouse[1]; - - if(mode == PropsetSize) - pd->origloc[0]-= sculptmode_brush()->size; - else if(mode == PropsetStrength) - pd->origloc[0]-= 200 - 2*sculptmode_brush()->strength; - else if(mode == PropsetTexRot) { - pd->origloc[0]-= 200 * cos(to_rad(ang)); - pd->origloc[1]-= 200 * sin(to_rad(ang)); + else if(mode == RADIALCONTROL_ROTATION) { + if(sd->texact!=-1 && sd->mtex[sd->texact]) { + orig = sculpt_tex_angle(); + max = 360; } - - pd->origsize= sculptmode_brush()->size; - pd->origstrength= sculptmode_brush()->strength; - pd->origtexrot= ang; - - sculptmode_propset_calctex(); - - if(!pd->num) - pd->num = MEM_callocN(sizeof(NumInput), "propset numinput"); - pd->num->idx_max= 0; + else + mode = RADIALCONTROL_NONE; } - pd->mode= mode; - sculptmode_propset_header(); - - allqueue(REDRAWVIEW3D, 0); + if(mode != RADIALCONTROL_NONE) { + ss->radialcontrol= radialcontrol_start(mode, sculpt_radialcontrol_callback, orig, max, + sculpt_radialcontrol_calctex()); + } } void sculpt_paint_brush(char clear) @@ -1387,90 +1326,6 @@ void sculpt_paint_brush(char clear) } } -void sculptmode_propset(unsigned short event) -{ - PropsetData *pd= sculpt_session()->propset; - short mouse[2]; - short tmp[2]; - float dist; - BrushData *brush= sculptmode_brush(); - char valset= 0; - - handleNumInput(pd->num, event); - - if(hasNumInput(pd->num)) { - float val; - applyNumInput(pd->num, &val); - if(pd->mode==PropsetSize) - brush->size= val; - else if(pd->mode==PropsetStrength) - brush->strength= val; - else if(pd->mode==PropsetTexRot) - set_tex_angle(val); - valset= 1; - allqueue(REDRAWVIEW3D, 0); - } - - switch(event) { - case MOUSEX: - case MOUSEY: - if(!hasNumInput(pd->num)) { - char ctrl= G.qual & LR_CTRLKEY; - getmouseco_areawin(mouse); - tmp[0]= pd->origloc[0]-mouse[0]; - tmp[1]= pd->origloc[1]-mouse[1]; - dist= sqrt(tmp[0]*tmp[0]+tmp[1]*tmp[1]); - if(pd->mode == PropsetSize) { - brush->size= dist; - if(ctrl) brush->size= (brush->size+5)/10*10; - } else if(pd->mode == PropsetStrength) { - float fin= (200.0f - dist) * 0.5f; - brush->strength= fin>=0 ? fin : 0; - if(ctrl) brush->strength= (brush->strength+5)/10*10; - } else if(pd->mode == PropsetTexRot) { - set_tex_angle((int)to_deg(atan2(tmp[1], tmp[0])) + 180); - if(ctrl) - set_tex_angle(((int)(tex_angle())+5)/10*10); - } - valset= 1; - allqueue(REDRAWVIEW3D, 0); - } - break; - case ESCKEY: - case RIGHTMOUSE: - brush->size= pd->origsize; - brush->strength= pd->origstrength; - set_tex_angle(pd->origtexrot); - case LEFTMOUSE: - while(get_mbut()==L_MOUSE); - case RETKEY: - case PADENTER: - sculptmode_propset_end(sculpt_session(), 0); - break; - default: - break; - }; - - if(valset) { - if(pd->mode == PropsetSize) { - if(brush->size<1) brush->size= 1; - if(brush->size>200) brush->size= 200; - } - else if(pd->mode == PropsetStrength) { - if(brush->strength > 100) brush->strength= 100; - sculptmode_propset_calctex(); - } - else if(pd->mode == PropsetTexRot) { - if(tex_angle() < 0) - set_tex_angle(0); - else if(tex_angle() > 360) - set_tex_angle(360); - } - } - - sculptmode_propset_header(); -} - void sculptmode_selectbrush_menu(void) { SculptData *sd= sculpt_data(); @@ -1699,7 +1554,7 @@ void sculpt(void) glGetIntegerv(GL_SCISSOR_BOX, scissor_box); /* For raking, get the original angle*/ - offsetRot=tex_angle(); + offsetRot=sculpt_tex_angle(); while (get_mbut() & mousebut) { getmouseco_areawin(mouse); diff --git a/source/blender/src/sequence.c b/source/blender/src/sequence.c index a12501b6735..fce967973cd 100644 --- a/source/blender/src/sequence.c +++ b/source/blender/src/sequence.c @@ -1108,7 +1108,9 @@ static void do_build_seq_ibuf(Sequence * seq, TStripElem *se, int cfra) IMB_freeImBuf(se->ibuf); } se->ibuf = se->se1->ibuf_comp; - IMB_refImBuf(se->ibuf); + if(se->ibuf) { + IMB_refImBuf(se->ibuf); + } } } else if(seq->type & SEQ_EFFECT) { /* should the effect be recalculated? */ diff --git a/source/blender/src/space.c b/source/blender/src/space.c index 9f3754f32da..1e764d98e9e 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -129,6 +129,7 @@ #include "BIF_poselib.h" #include "BIF_poseobject.h" #include "BIF_outliner.h" +#include "BIF_radialcontrol.h" #include "BIF_resources.h" #include "BIF_retopo.h" #include "BIF_screen.h" @@ -1199,8 +1200,8 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) if(!mouse_in_header(sa)) { if(!G.obedit && (G.f & G_SCULPTMODE)) { SculptSession *ss= sculpt_session(); - if(ss && ss->propset) { - sculptmode_propset(event); + if(ss && ss->radialcontrol) { + radialcontrol_do_events(ss->radialcontrol, event); return; } else if(event!=LEFTMOUSE && event!=MIDDLEMOUSE && (event==MOUSEY || event==MOUSEX)) { @@ -1211,6 +1212,10 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) else if(!G.obedit && OBACT && G.f&G_PARTICLEEDIT){ ParticleSystem *psys=PE_get_current(OBACT); ParticleEditSettings *pset=PE_settings(); + if(*PE_radialcontrol()) { + radialcontrol_do_events(*PE_radialcontrol(), event); + return; + } if(psys && psys->edit){ if(pset->brushtype>=0 && event!=LEFTMOUSE && event!=RIGHTMOUSE && event!=MIDDLEMOUSE && @@ -1366,7 +1371,7 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) case LEFTMOUSE: if(G.qual==LR_SHIFTKEY+LR_CTRLKEY) sculptmode_pmv(0); - else if(!(ss && ss->propset)) + else if(!(ss && ss->radialcontrol)) sculpt(); break; /* View */ @@ -1444,12 +1449,12 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) br->airbrush= !br->airbrush; update_prop= 1; break; case FKEY: - if(G.qual==0) - sculptmode_propset_init(PropsetSize); - if(G.qual==LR_SHIFTKEY) - sculptmode_propset_init(PropsetStrength); - if(G.qual==LR_CTRLKEY) - sculptmode_propset_init(PropsetTexRot); + if(ss) { + sculpt_radialcontrol_start(G.qual == 0 ? RADIALCONTROL_SIZE : + G.qual == LR_SHIFTKEY ? RADIALCONTROL_STRENGTH : + G.qual == LR_CTRLKEY ? RADIALCONTROL_ROTATION : + RADIALCONTROL_NONE); + } break; case VKEY: br->dir= br->dir==1 ? 2 : 1; @@ -1914,6 +1919,8 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) pose_activate_flipped_bone(); else if(G.f & G_WEIGHTPAINT) pose_activate_flipped_bone(); + else if(G.f & G_PARTICLEEDIT) + PE_radialcontrol_start(RADIALCONTROL_STRENGTH); else fly(); } @@ -1922,6 +1929,8 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) G.f ^= G_FACESELECT; allqueue(REDRAWVIEW3D, 1); } + else if(G.f & G_PARTICLEEDIT) + PE_radialcontrol_start(RADIALCONTROL_SIZE); } break; @@ -4087,6 +4096,10 @@ void drawinfospace(ScrArea *sa, void *spacedata) 0, 0, 0, 0, 0, "Select the default texture plugin location"); uiBlockEndAlign(block); + uiDefButBitI(block, TOG, USER_RELPATHS, B_DRAWINFO, "Relative Paths Default", + (xpos+edgsp+(5*mpref)+(5*midsp)),y3,mpref,buth, + &(U.flag), 0, 0, 0, 0, "Default relative path option for the file selector"); + uiBlockBeginAlign(block); uiDefBut(block, TEX, 0, "Seq Plugins: ", (xpos+edgsp+(3*lpref)+(3*midsp)),y2,(lpref-smfileselbut),buth, @@ -4785,6 +4798,13 @@ static void winqreadseqspace(ScrArea *sa, void *spacedata, BWinEvent *evt) doredraw= 1; } break; + case HKEY: /* hide==mute? - not that nice but MKey us used for meta :/ */ + if((G.qual==0)) { + seq_mute_sel(1); + } else if((G.qual==LR_ALTKEY)) { + seq_mute_sel(0); + } + break; case XKEY: case DELKEY: if(G.qual==0) { diff --git a/source/blender/src/toolbox.c b/source/blender/src/toolbox.c index 615cb1900bc..401b36d4587 100644 --- a/source/blender/src/toolbox.c +++ b/source/blender/src/toolbox.c @@ -1777,6 +1777,8 @@ static void do_group_addmenu(void *arg, int event) ob->dup_group= BLI_findlink(&G.main->group, event); if(ob->dup_group) { + rename_id(&ob->id, ob->dup_group->id.name+2); + id_us_plus((ID *)ob->dup_group); ob->transflag |= OB_DUPLIGROUP; DAG_scene_sort(G.scene); diff --git a/source/blender/src/transform.c b/source/blender/src/transform.c index 32c152488d1..22b10e0a3f0 100644 --- a/source/blender/src/transform.c +++ b/source/blender/src/transform.c @@ -365,7 +365,7 @@ int addMatrixSpace(float mat[3][3], char name[]) { BIF_undo_push("Add/Update Transform Orientation"); - return BIF_countTransformOrientation() - 1; + return index; } void BIF_removeTransformOrientation(TransformOrientation *target) { diff --git a/source/blender/src/transform_conversions.c b/source/blender/src/transform_conversions.c index f9abfd69cdd..9160bf2f563 100644 --- a/source/blender/src/transform_conversions.c +++ b/source/blender/src/transform_conversions.c @@ -1953,6 +1953,7 @@ static void createTransEditVerts(TransInfo *t) EditMesh *em = G.editMesh; EditVert *eve; EditVert **nears = NULL; + EditVert *eve_act = NULL; float *vectors = NULL, *mappedcos = NULL, *quats= NULL; float mtx[3][3], smtx[3][3], (*defmats)[3][3] = NULL, (*defcos)[3] = NULL; int count=0, countsel=0, a, totleft; @@ -2003,6 +2004,15 @@ static void createTransEditVerts(TransInfo *t) /* note: in prop mode we need at least 1 selected */ if (countsel==0) return; + /* check active */ + if (G.editMesh->selected.last) { + EditSelection *ese = G.editMesh->selected.last; + if ( ese->type == EDITVERT ) { + eve_act = (EditVert *)ese->data; + } + } + + if(propmode) { t->total = count; @@ -2058,8 +2068,13 @@ static void createTransEditVerts(TransInfo *t) if(eve->h==0) { if(propmode || eve->f1) { VertsToTransData(tob, eve); - + + /* selected */ if(eve->f1) tob->flag |= TD_SELECTED; + + /* active */ + if(eve == eve_act) tob->flag |= TD_ACTIVE; + if(propmode) { if (eve->f2) { float vec[3]; @@ -2884,6 +2899,13 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob) Mat3One(td->smtx); Mat3One(td->mtx); } + + /* set active flag */ + if (BASACT && BASACT->object == ob) + { + td->flag |= TD_ACTIVE; + } + #ifdef WITH_VERSE if(ob->vnode) { td->verse = (void*)ob; diff --git a/source/blender/src/transform_snap.c b/source/blender/src/transform_snap.c index 3279e6e6f09..c0f634a3f67 100644 --- a/source/blender/src/transform_snap.c +++ b/source/blender/src/transform_snap.c @@ -85,12 +85,15 @@ void CalcSnapGeometry(TransInfo *t, float *vec); void TargetSnapMedian(TransInfo *t); void TargetSnapCenter(TransInfo *t); void TargetSnapClosest(TransInfo *t); +void TargetSnapActive(TransInfo *t); float RotationBetween(TransInfo *t, float p1[3], float p2[3]); float TranslationBetween(TransInfo *t, float p1[3], float p2[3]); -// Trickery -int findNearestVertFromObjects(int *dist, float *loc, int selected); +/* Modes */ +#define NOT_SELECTED 0 +#define NOT_ACTIVE 1 +int findNearestVertFromObjects(int *dist, float *loc, int mode); /****************** IMPLEMENTATIONS *********************/ @@ -277,6 +280,11 @@ void setSnappingCallback(TransInfo *t) t->tsnap.modeTarget = SNAP_MEDIAN; t->tsnap.targetSnap = TargetSnapMedian; break; + case SCE_SNAP_TARGET_ACTIVE: + t->tsnap.modeTarget = SNAP_ACTIVE; + t->tsnap.targetSnap = TargetSnapActive; + break; + } switch (t->mode) @@ -391,6 +399,7 @@ void CalcSnapGrid(TransInfo *t, float *vec) void CalcSnapGeometry(TransInfo *t, float *vec) { + /* Object mode */ if (G.obedit == NULL) { if (t->spacetype == SPACE_VIEW3D) @@ -399,7 +408,7 @@ void CalcSnapGeometry(TransInfo *t, float *vec) int found = 0; int dist = 40; // Use a user defined value here - found = findNearestVertFromObjects(&dist, vec, 0); + found = findNearestVertFromObjects(&dist, vec, NOT_SELECTED); if (found == 1) { VECCOPY(t->tsnap.snapPoint, vec); @@ -412,6 +421,7 @@ void CalcSnapGeometry(TransInfo *t, float *vec) } } } + /* Mesh edit mode */ else if (G.obedit != NULL && G.obedit->type==OB_MESH) { /*if (G.scene->selectmode & B_SEL_VERT)*/ @@ -426,7 +436,7 @@ void CalcSnapGeometry(TransInfo *t, float *vec) // use findnearestverts in vert mode, others in other modes nearest = findnearestvert(&dist, SELECT, 1); - found = findNearestVertFromObjects(&dist, vec, SELECT); + found = findNearestVertFromObjects(&dist, vec, NOT_ACTIVE); if (found == 1) { VECCOPY(t->tsnap.snapPoint, vec); @@ -513,6 +523,45 @@ void TargetSnapCenter(TransInfo *t) } } +void TargetSnapActive(TransInfo *t) +{ + // Only need to calculate once + if ((t->tsnap.status & TARGET_INIT) == 0) + { + TransData *td = NULL; + TransData *active_td = NULL; + int i; + + for(td = t->data, i = 0 ; i < t->total && td->flag & TD_SELECTED ; i++, td++) + { + if (td->flag & TD_ACTIVE) + { + active_td = td; + break; + } + } + + if (active_td) + { + VECCOPY(t->tsnap.snapTarget, active_td->center); + + if(t->flag & (T_EDIT|T_POSE)) { + Object *ob= G.obedit?G.obedit:t->poseobj; + Mat4MulVecfl(ob->obmat, t->tsnap.snapTarget); + } + + t->tsnap.status |= TARGET_INIT; + } + /* No active, default to median */ + else + { + t->tsnap.modeTarget = SNAP_MEDIAN; + t->tsnap.targetSnap = TargetSnapMedian; + TargetSnapMedian(t); + } + } +} + void TargetSnapMedian(TransInfo *t) { // Only need to calculate once @@ -628,7 +677,7 @@ void TargetSnapClosest(TransInfo *t) } /*================================================================*/ -int findNearestVertFromObjects(int *dist, float *loc, int selected) { +int findNearestVertFromObjects(int *dist, float *loc, int mode) { Base *base; int retval = 0; short mval[2]; @@ -637,7 +686,7 @@ int findNearestVertFromObjects(int *dist, float *loc, int selected) { base= FIRSTBASE; for ( base = FIRSTBASE; base != NULL; base = base->next ) { - if ( base != BASACT && BASE_SELECTABLE(base) && (base->flag & SELECT) == selected ) { + if ( BASE_SELECTABLE(base) && ((mode == NOT_SELECTED && (base->flag & SELECT) == 0) || (mode == NOT_ACTIVE && base != BASACT)) ) { Object *ob = base->object; if (ob->type == OB_MESH) { diff --git a/source/blender/src/usiblender.c b/source/blender/src/usiblender.c index 88df4c8d34f..51079995a2f 100644 --- a/source/blender/src/usiblender.c +++ b/source/blender/src/usiblender.c @@ -397,6 +397,14 @@ static void init_userdef_file(void) SETCOL(btheme->ttime.cframe, 0x60, 0xc0, 0x40, 255); } } + if ((G.main->versionfile < 245) || (G.main->versionfile == 245 && G.main->subversionfile < 13)) { + bTheme *btheme; + for (btheme= U.themes.first; btheme; btheme= btheme->next) { + /* action channel groups (recolour anyway) */ + SETCOL(btheme->tact.group, 0x39, 0x7d, 0x1b, 255); + SETCOL(btheme->tact.group_active, 0x7d, 0xe9, 0x60, 255); + } + } /* GL Texture Garbage Collection (variable abused above!) */ if (U.textimeout == 0) { @@ -681,6 +689,9 @@ static void readBlog(void) fsmenu_append_separator(); } +#else + /* add home dir on linux systems */ + fsmenu_insert_entry(BLI_gethome(), 0, 0); #endif BLI_make_file_string(G.sce, name, BLI_gethome(), ".Bfs"); diff --git a/source/blender/src/view.c b/source/blender/src/view.c index 655fa59a4c1..abb49c0ec9d 100644 --- a/source/blender/src/view.c +++ b/source/blender/src/view.c @@ -69,6 +69,7 @@ #include "BKE_sculpt.h" #include "BKE_utildefines.h" +#include "BIF_transform.h" #include "BIF_editparticle.h" #include "BIF_gl.h" #include "BIF_previewrender.h" @@ -88,6 +89,7 @@ #include "mydevice.h" #include "blendef.h" +#include "transform.h" #include "PIL_time.h" /* smoothview */ diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index a34ed069b02..7b9da71a501 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -42,12 +42,17 @@ INCLUDE_DIRECTORIES(../../intern/guardedalloc ../blender/makesdna ../kernel/gen_messaging ../kernel/gen_system + ../../extern/binreloc/include ) IF(WITH_QUICKTIME) ADD_DEFINITIONS(-DWITH_QUICKTIME) ENDIF(WITH_QUICKTIME) +IF(WITH_BINRELOC) + ADD_DEFINITIONS(-DWITH_BINRELOC) +endif(WITH_VINRELOC) + IF(YESIAMSTUPID) ADD_DEFINITIONS(-DYESIAMSTUPID) ENDIF(YESIAMSTUPID) diff --git a/source/creator/Makefile b/source/creator/Makefile index 02c22aa4da8..a7f2dfeecb6 100644 --- a/source/creator/Makefile +++ b/source/creator/Makefile @@ -42,6 +42,7 @@ CFLAGS += $(LEVEL_1_C_WARNINGS) CPPFLAGS += -I../blender/render/extern/include CPPFLAGS += -I../blender/radiosity/extern/include + # two needed for the kernel CPPFLAGS += -I../blender/imbuf CPPFLAGS += -I../blender/makesdna @@ -59,6 +60,10 @@ ifeq ($(WITH_QUICKTIME), true) CPPFLAGS += -I$(NAN_QUICKTIME)/include -DWITH_QUICKTIME endif +ifeq ($(WITH_BINRELOC), true) + CPPFLAGS += -I$(OCGDIR)/extern/binreloc/include -DWITH_BINRELOC +endif + ifeq ($(NAN_YESIAMSTUPID), true) CPPFLAGS += -DYESIAMSTUPID endif diff --git a/source/creator/SConscript b/source/creator/SConscript index 9bc49b2fc30..833b56eccd8 100644 --- a/source/creator/SConscript +++ b/source/creator/SConscript @@ -15,4 +15,8 @@ if env['WITH_BF_QUICKTIME']==1: incs += ' ' + env['BF_QUICKTIME_INC'] defs.append('WITH_QUICKTIME') +if env['WITH_BF_BINRELOC']==1: + incs += ' ../../extern/binreloc/include' + defs.append('WITH_BINRELOC') + env.BlenderLib ( libname = 'blender_creator', sources = Split(sources), includes = Split(incs), defines = defs, libtype='core', priority = 1 ) diff --git a/source/creator/creator.c b/source/creator/creator.c index 9b5a151b56b..11065155f12 100644 --- a/source/creator/creator.c +++ b/source/creator/creator.c @@ -97,6 +97,10 @@ # include #endif +#ifdef WITH_BINRELOC +#include "binreloc.h" +#endif + // from buildinfo.c #ifdef BUILD_DATE extern char * build_date; @@ -253,6 +257,11 @@ int main(int argc, char **argv) int audio = 0; #endif + +#ifdef WITH_BINRELOC + br_init( NULL ); +#endif + setCallbacks(); #ifdef __APPLE__ /* patch to ignore argument finder gives us (pid?) */ diff --git a/source/nan_definitions.mk b/source/nan_definitions.mk index 246be668f5b..36b140c1ffb 100644 --- a/source/nan_definitions.mk +++ b/source/nan_definitions.mk @@ -416,6 +416,8 @@ endif # enable freetype2 support for text objects export WITH_FREETYPE2 ?= true + export WITH_BINRELOC ?= true + # enable ffmpeg support ifndef NAN_NO_FFMPEG export WITH_FFMPEG ?= true diff --git a/tools/btools.py b/tools/btools.py index 8e4848a39be..a1a953296d9 100755 --- a/tools/btools.py +++ b/tools/btools.py @@ -48,6 +48,7 @@ def validate_arguments(args, bc): 'WITH_BF_STATICOPENGL', 'BF_OPENGL', 'BF_OPENGL_INC', 'BF_OPENGL_LIB', 'BF_OPENGL_LIBPATH', 'BF_OPENGL_LIB_STATIC', 'BF_OPENGL_LINKFLAGS', 'WITH_BF_FTGL', 'BF_FTGL', 'BF_FTGL_INC', 'BF_FTGL_LIB', 'WITH_BF_PLAYER', + 'WITH_BF_BINRELOC', 'CFLAGS', 'CCFLAGS', 'CPPFLAGS', 'REL_CFLAGS', 'REL_CCFLAGS', 'C_WARN', 'CC_WARN', 'LLIBS', 'PLATFORM_LINKFLAGS', @@ -305,6 +306,7 @@ def read_opts(cfg, args): (BoolOption('BF_SPLIT_SRC', 'Split src lib into several chunks if true', 'false')), (BoolOption('WITHOUT_BF_INSTALL', 'dont install if true', 'false')), (BoolOption('BF_FANCY', 'Enable fancy output if true', 'true')), + (BoolOption('WITH_BF_BINRELOC', 'Enable relocatable binary (linux only)', 'false')), ) # end of opts.AddOptions()