diff --git a/CMakeLists.txt b/CMakeLists.txt index 0227c51f39d..eabcdde1dde 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -65,8 +65,9 @@ OPTION(WITH_ELBEEM "Enable Elbeem (Fluid Simulation)" ON) OPTION(WITH_QUICKTIME "Enable Quicktime Support" OFF) OPTION(WITH_OPENEXR "Enable OpenEXR Support (http://www.openexr.com)" OFF) 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_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) IF(NOT WITH_GAMEENGINE AND WITH_PLAYER) MESSAGE("WARNING: WITH_PLAYER needs WITH_GAMEENGINE") @@ -186,6 +187,12 @@ IF(UNIX) SET(PLATFORM_CFLAGS "-pipe -fPIC -funsigned-char -fno-strict-aliasing -DXP_UNIX -Wno-char-subscripts") + IF(WITH_OPENMP) + SET(LLIBS ${LLIBS} gomp) + SET(CMAKE_C_FLAGS ${CMAKE_C_FLAGS} "-fopenmp") + SET(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} "-fopenmp") + ENDIF(WITH_OPENMP) + SET(PLATFORM_LINKFLAGS "-pthread") INCLUDE_DIRECTORIES(/usr/include /usr/local/include) @@ -270,6 +277,11 @@ IF(WIN32) SET(CMAKE_C_FLAGS_MINSIZEREL "/D_CRT_NONSTDC_NO_DEPRECATE /D_CRT_SECURE_NO_DEPRECATE /D_SCL_SECURE_NO_DEPRECATE /wd4800 /wd4244 /wd4305 /O1 /Ob1 /DNDEBUG /EHsc /MT /W3 /nologo /J" CACHE STRING "MSVC MT flags " FORCE) SET(CMAKE_C_FLAGS_RELWITHDEBINFO "/D_CRT_NONSTDC_NO_DEPRECATE /D_CRT_SECURE_NO_DEPRECATE /D_SCL_SECURE_NO_DEPRECATE /wd4800 /wd4244 /wd4305 /O2 /Ob1 /DNDEBUG /EHsc /MT /W3 /nologo /Zi /J" CACHE STRING "MSVC MT flags " FORCE) + IF(WITH_OPENMP) + SET(CMAKE_C_FLAGS ${CMAKE_C_FLAGS} "/openmp") + SET(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} "/openmp") + ENDIF(WITH_OPENMP) + SET(SDL ${LIBDIR}/sdl) SET(SDL_INC ${SDL}/include) SET(SDL_LIB SDL) @@ -347,6 +359,12 @@ IF(APPLE) SET(PLATFORM_CFLAGS "-pipe -fPIC -funsigned-char -fno-strict-aliasing") SET(PLATFORM_LINKFLAGS "-fexceptions -framework CoreServices -framework Foundation -framework IOKit -framework AppKit -framework Carbon -framework AGL -framework AudioUnit -framework AudioToolbox -framework CoreAudio -framework QuickTime") + IF(WITH_OPENMP) + SET(LLIBS ${LLIBS} gomp) + SET(CMAKE_C_FLAGS ${CMAKE_C_FLAGS} "-fopenmp") + SET(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} "-fopenmp") + ENDIF(WITH_OPENMP) + SET(SDL ${LIBDIR}/sdl) SET(SDL_INC ${SDL}/include) SET(SDL_LIB SDL) diff --git a/intern/elbeem/CMakeLists.txt b/intern/elbeem/CMakeLists.txt index 86a60180b05..ac35b8ce00f 100644 --- a/intern/elbeem/CMakeLists.txt +++ b/intern/elbeem/CMakeLists.txt @@ -36,5 +36,9 @@ IF(WINDOWS) ADD_DEFINITIONS(-DUSE_MSVC6FIXES) ENDIF(WINDOWS) +IF(WITH_OPENMP) + ADD_DEFINITIONS(-DPARALLEL) +ENDIF(WITH_OPENMP) + BLENDERLIB_NOLIST(bf_elbeem "${SRC}" "${INC}") #, libtype='blender', priority=0 ) diff --git a/intern/elbeem/extern/elbeem.h b/intern/elbeem/extern/elbeem.h index b3feda8bbe8..2a594dd07e6 100644 --- a/intern/elbeem/extern/elbeem.h +++ b/intern/elbeem/extern/elbeem.h @@ -154,7 +154,7 @@ typedef struct elbeemMesh { short volumeInitType; /* name of the mesh, mostly for debugging */ - char *name; + const char *name; } elbeemMesh; // API functions diff --git a/intern/elbeem/intern/attributes.cpp b/intern/elbeem/intern/attributes.cpp index 8e337a92a4e..464486f2500 100644 --- a/intern/elbeem/intern/attributes.cpp +++ b/intern/elbeem/intern/attributes.cpp @@ -103,7 +103,7 @@ void AttributeList::readMat4Gfx(string name, ntlMat4Gfx defaultValue, string sou // set that a parameter can be given, and will be ignored... bool AttributeList::ignoreParameter(string name, string source) { - name=source=(""); // remove warning + name = source = (""); return false; } diff --git a/intern/elbeem/intern/loop_tools.h b/intern/elbeem/intern/loop_tools.h index 3c15a609210..70ecb9ce3e0 100644 --- a/intern/elbeem/intern/loop_tools.h +++ b/intern/elbeem/intern/loop_tools.h @@ -54,15 +54,84 @@ -#define unused_GRID_REGION_END() \ - } /* main_region */ \ - // end unusedGRID_REGION_END - // ----------------------------------------------------------------------------------- #else // PARALLEL==1 -#include "paraloop.h" +//#include "paraloop.h" +#define PERFORM_USQRMAXCHECK USQRMAXCHECK(usqr,ux,uy,uz, calcMaxVlen, calcMxvx,calcMxvy,calcMxvz); +#define LIST_EMPTY(x) calcListEmpty.push_back( x ); +#define LIST_FULL(x) calcListFull.push_back( x ); +#define FSGR_ADDPART(x) calcListParts.push_back( x ); + + +// parallel region +//was: # pragma omp parallel default(shared) +#if COMPRESSGRIDS!=1 + // requires compressed grids...! + ERROR! +#endif + +// loop start +#define GRID_REGION_START() \ + { \ + \ + \ + if(mSizez<2) { \ + mPanic = 1; \ + errFatal("ParaLoop::2D","Not valid...!", SIMWORLD_GENERICERROR); \ + } \ + \ + \ + vector calcListFull; \ + vector calcListEmpty; \ + vector calcListParts; \ + LbmFloat calcMxvx, calcMxvy, calcMxvz, calcMaxVlen; \ + calcMxvx = calcMxvy = calcMxvz = calcMaxVlen = 0.0; \ + calcListEmpty.reserve(mListEmpty.capacity() / omp_get_num_threads() ); \ + calcListFull.reserve( mListFull.capacity() / omp_get_num_threads() ); \ + calcListParts.reserve(mSizex); \ + \ + \ + const int id = omp_get_thread_num(); \ + const int Nthrds = omp_get_num_threads(); \ + \ + \ + \ + \ + \ + int kdir = 1; \ + \ + int kstart=getForZMinBnd(), kend=getForZMaxBnd(mMaxRefine); \ + if(gridLoopBound>0){ kstart=getForZMin1(); kend=getForZMax1(mMaxRefine); } \ + LbmFloat *ccel = NULL, *tcel = NULL; \ + CellFlagType *pFlagSrc=NULL, *pFlagDst=NULL; \ + \ + \ + if(mLevel[mMaxRefine].setCurr==1) { \ + kdir = -1; \ + int temp = kend; \ + kend = kstart-1; \ + kstart = temp-1; \ + } \ + \ + const int Nj = mLevel[mMaxRefine].lSizey; \ + int jstart = 0+( id * (Nj / Nthrds) ); \ + int jend = 0+( (id+1) * (Nj / Nthrds) ); \ + if( ((Nj/Nthrds) *Nthrds) != Nj) { \ + errMsg("LbmFsgrSolver","Invalid domain size Nj="< #include #include +#include // hack for MSVC6.0 compiler #ifdef _MSC_VER diff --git a/intern/elbeem/intern/paraloop.h b/intern/elbeem/intern/paraloop.h deleted file mode 100644 index fba0ae44b91..00000000000 --- a/intern/elbeem/intern/paraloop.h +++ /dev/null @@ -1,50 +0,0 @@ - -#define PERFORM_USQRMAXCHECK \ -_Pragma("omp critical") {\ -USQRMAXCHECK(usqr,ux,uy,uz, mMaxVlen, mMxvx,mMxvy,mMxvz); \ -} \ - - -#define LIST_EMPTY(x) \ -_Pragma("omp critical") {\ -mListEmpty.push_back( x ); } - -#define LIST_FULL(x) \ -_Pragma("omp critical") {\ -mListFull.push_back( x ); } - -#define FSGR_ADDPART(x) \ -_Pragma("omp critical") { \ -mpParticles->addFullParticle( x ); } \ - - -#define MAX_THREADS 2 - -#define GRID_REGION_START() \ -{ /* main_region */ \ - int kstart=getForZMinBnd(), kend=getForZMaxBnd(mMaxRefine); \ - if(gridLoopBound>0){ kstart=getForZMin1(), kend=getForZMax1(mMaxRefine); } \ - int kdir = 1; \ - const int id=omp_get_thread_num(); \ - int jstart = (id*((mLevel[mMaxRefine].lSizey-gridLoopBound) / MAX_THREADS))+gridLoopBound; \ - int jend = (id+1)*((mLevel[mMaxRefine].lSizey-gridLoopBound)/ MAX_THREADS); \ - if(id+1 == MAX_THREADS) \ - { \ - jend = mLevel[mMaxRefine].lSizey-gridLoopBound; \ - } \ - LbmFloat *ccel = NULL, *tcel = NULL; \ - CellFlagType *pFlagSrc=NULL, *pFlagDst=NULL; \ - if(mLevel[mMaxRefine].setCurr==1) { \ - kdir = -1; \ - int temp = kend; \ - kend = kstart-1; \ - kstart = temp-1; \ - temp = id; /* dummy remove warning */ \ -} \ - -// if(jstart<1) jstart = 1; - -#define unused_GRID_REGION_END() \ -} /* main_region */ \ - // end unusedGRID_REGION_END - diff --git a/intern/elbeem/intern/paraloopend.h b/intern/elbeem/intern/paraloopend.h index 889e2930818..81fc329d159 100644 --- a/intern/elbeem/intern/paraloopend.h +++ b/intern/elbeem/intern/paraloopend.h @@ -7,7 +7,7 @@ /* COMPRESSGRIDS!=1 */ /* int i=0; */ /* ADVANCE_POINTERS(mLevel[lev].lSizex*2); */ -} /* all cell loop k,j,i */ +} /* all cell loop k,j,i */ if(doReduce) { } /* dummy remove warning */ } /* main_region */ diff --git a/intern/elbeem/intern/paraloopstart.h b/intern/elbeem/intern/paraloopstart.h deleted file mode 100644 index e5940815dc8..00000000000 --- a/intern/elbeem/intern/paraloopstart.h +++ /dev/null @@ -1,3 +0,0 @@ - -#pragma omp parallel num_threads(MAX_THREADS) \ -reduction(+: calcCurrentMass, calcCurrentVolume, calcCellsFilled, calcCellsEmptied, calcNumUsedCells) diff --git a/intern/elbeem/intern/particletracer.cpp b/intern/elbeem/intern/particletracer.cpp index c9da808543a..819fcdd0b9a 100644 --- a/intern/elbeem/intern/particletracer.cpp +++ b/intern/elbeem/intern/particletracer.cpp @@ -325,7 +325,7 @@ void ParticleTracer::getTriangles(double time, vector *triangles, // suppress warnings... vertices = NULL; triangles = NULL; normals = NULL; objectId = 0; - time = 0.0; + time = 0.; #else // ELBEEM_PLUGIN int pcnt = 0; // currently not used in blender diff --git a/intern/elbeem/intern/simulation_object.cpp b/intern/elbeem/intern/simulation_object.cpp index 2ff600a36d4..9b47ae696af 100644 --- a/intern/elbeem/intern/simulation_object.cpp +++ b/intern/elbeem/intern/simulation_object.cpp @@ -15,7 +15,6 @@ #include "solver_interface.h" #include "particletracer.h" #include "elbeem.h" -#include /* exit(3) - also in linux */ #ifdef _WIN32 #else @@ -69,6 +68,7 @@ SimulationObject::~SimulationObject() /*! init tree for certain geometry init */ /*****************************************************************************/ void SimulationObject::initGeoTree() { + // unused!! overriden by solver interface if(mpGlob == NULL) { errFatal("SimulationObject::initGeoTree error","Requires globals!", SIMWORLD_INITERROR); return; @@ -80,7 +80,7 @@ void SimulationObject::initGeoTree() { char treeFlag = (1<<(mGeoInitId+4)); mpGiTree = new ntlTree( 20, 4, // warning - fixed values for depth & maxtriangles here... scene, treeFlag ); - exit(1); // unused!? overriden by solver interface + // unused!! overriden by solver interface } /*****************************************************************************/ @@ -310,7 +310,7 @@ void SimulationObject::step( void ) // dont advance for stopped time mpLbm->step(); mTime += mpParam->getTimestep(); -//if(mTime>0.001) { errMsg("DEBUG!!!!!!!!","quit mlsu..."); exit(1); } // PROFILE DEBUG TEST! + //if(mTime>0.001) { errMsg("DEBUG!!!!!!!!","quit mlsu..."); xit(1); } // PROFILE DEBUG TEST! } if(mpLbm->getPanic()) mPanic = true; diff --git a/intern/elbeem/intern/solver_class.h b/intern/elbeem/intern/solver_class.h index 930c1863aa7..d46f065adfd 100644 --- a/intern/elbeem/intern/solver_class.h +++ b/intern/elbeem/intern/solver_class.h @@ -101,7 +101,7 @@ // sirdude fix for solaris #if !defined(linux) && defined(sun) #ifndef expf -#define expf(a) exp((double)(a)) +#define expf(x) exp((double)(x)) #endif #endif diff --git a/intern/elbeem/intern/solver_init.cpp b/intern/elbeem/intern/solver_init.cpp index abec4a89c89..b0ce130c136 100644 --- a/intern/elbeem/intern/solver_init.cpp +++ b/intern/elbeem/intern/solver_init.cpp @@ -655,6 +655,7 @@ bool LbmFsgrSolver::initializeSolverMemory() int orgSz = mSizez; double sizeReduction = 1.0; double memEstFromFunc = -1.0; + double memEstFine = -1.0; string memreqStr(""); bool firstMInit = true; int minitTries=0; @@ -672,7 +673,7 @@ bool LbmFsgrSolver::initializeSolverMemory() firstMInit=false; calculateMemreqEstimate( mSizex, mSizey, mSizez, - mMaxRefine, mFarFieldSize, &memEstFromFunc, &memreqStr ); + mMaxRefine, mFarFieldSize, &memEstFromFunc, &memEstFine, &memreqStr ); double memLimit; string memLimStr("-"); @@ -685,13 +686,36 @@ bool LbmFsgrSolver::initializeSolverMemory() memLimit = 16.0* 1024.0*1024.0*1024.0; memLimStr = string("16GB"); } - if(memEstFromFunc>memLimit) { + + // restrict max. chunk of 1 mem block to 1GB for windos + bool memBlockAllocProblem = false; + double maxWinMemChunk = 1100.*1024.*1024.; + double maxMacMemChunk = 1200.*1024.*1024.; + double maxDefaultMemChunk = 2.*1024.*1024.*1024.; + //std::cerr<<" memEstFine "<< memEstFine <<" maxWin:" < maxWinMemChunk) { + memBlockAllocProblem = true; + } +#endif // WIN32 +#ifdef __APPLE__ + if(memEstFine> maxMacMemChunk) { + memBlockAllocProblem = true; + } +#endif // Mac + if(sizeof(int)==4 && memEstFine>maxDefaultMemChunk) { + // max memory chunk for 32bit systems 2gig + memBlockAllocProblem = true; + } + + if(memEstFromFunc>memLimit || memBlockAllocProblem) { sizeReduction *= 0.9; mSizex = (int)(orgSx * sizeReduction); mSizey = (int)(orgSy * sizeReduction); mSizez = (int)(orgSz * sizeReduction); debMsgStd("LbmFsgrSolver::initialize",DM_WARNING,"initGridSizes: memory limit exceeded "<< //memEstFromFunc<<"/"<getCellSize(); mLevel[ mMaxRefine ].lcellfactor = 1.0; LONGINT rcellSize = ((mLevel[mMaxRefine].lSizex*mLevel[mMaxRefine].lSizey*mLevel[mMaxRefine].lSizez) *dTotalNum); - // +4 for safety ? - mLevel[ mMaxRefine ].mprsFlags[0] = new CellFlagType[ rcellSize/dTotalNum +4 ]; - mLevel[ mMaxRefine ].mprsFlags[1] = new CellFlagType[ rcellSize/dTotalNum +4 ]; - ownMemCheck += 2 * sizeof(CellFlagType) * (rcellSize/dTotalNum +4); #if COMPRESSGRIDS==0 mLevel[ mMaxRefine ].mprsCells[0] = new LbmFloat[ rcellSize +4 ]; @@ -789,11 +809,34 @@ bool LbmFsgrSolver::initializeSolverMemory() ownMemCheck += 2 * sizeof(LbmFloat) * (rcellSize+4); #else // COMPRESSGRIDS==0 LONGINT compressOffset = (mLevel[mMaxRefine].lSizex*mLevel[mMaxRefine].lSizey*dTotalNum*2); + // D int tmp = ( (rcellSize +compressOffset +4)/(1024*1024) )*4; + // D printf("Debug MEMMMM excee: %d\n", tmp); mLevel[ mMaxRefine ].mprsCells[1] = new LbmFloat[ rcellSize +compressOffset +4 ]; mLevel[ mMaxRefine ].mprsCells[0] = mLevel[ mMaxRefine ].mprsCells[1]+compressOffset; ownMemCheck += sizeof(LbmFloat) * (rcellSize +compressOffset +4); #endif // COMPRESSGRIDS==0 + if(!mLevel[ mMaxRefine ].mprsCells[1] || !mLevel[ mMaxRefine ].mprsCells[0]) { + errFatal("LbmFsgrSolver::initialize","Fatal: Couldnt allocate memory (1)! Aborting...",SIMWORLD_INITERROR); + return false; + } + + // +4 for safety ? + mLevel[ mMaxRefine ].mprsFlags[0] = new CellFlagType[ rcellSize/dTotalNum +4 ]; + mLevel[ mMaxRefine ].mprsFlags[1] = new CellFlagType[ rcellSize/dTotalNum +4 ]; + ownMemCheck += 2 * sizeof(CellFlagType) * (rcellSize/dTotalNum +4); + if(!mLevel[ mMaxRefine ].mprsFlags[1] || !mLevel[ mMaxRefine ].mprsFlags[0]) { + errFatal("LbmFsgrSolver::initialize","Fatal: Couldnt allocate memory (2)! Aborting...",SIMWORLD_INITERROR); + +#if COMPRESSGRIDS==0 + delete[] mLevel[ mMaxRefine ].mprsCells[0]; + delete[] mLevel[ mMaxRefine ].mprsCells[1]; +#else // COMPRESSGRIDS==0 + delete[] mLevel[ mMaxRefine ].mprsCells[1]; +#endif // COMPRESSGRIDS==0 + return false; + } + LbmFloat lcfdimFac = 8.0; if(LBMDIM==2) lcfdimFac = 4.0; for(int i=mMaxRefine-1; i>=0; i--) { diff --git a/intern/elbeem/intern/solver_interface.cpp b/intern/elbeem/intern/solver_interface.cpp index 2539556617b..d25850a003b 100644 --- a/intern/elbeem/intern/solver_interface.cpp +++ b/intern/elbeem/intern/solver_interface.cpp @@ -17,7 +17,6 @@ #include "ntl_world.h" #include "elbeem.h" -#include /* getenv(3) - also in linux */ @@ -142,7 +141,7 @@ void initGridSizes(int &sizex, int &sizey, int &sizez, void calculateMemreqEstimate( int resx,int resy,int resz, int refine, float farfield, - double *reqret, string *reqstr) { + double *reqret, double *reqretFine, string *reqstr) { // debug estimation? const bool debugMemEst = true; // COMPRESSGRIDS define is not available here, make sure it matches @@ -150,6 +149,7 @@ void calculateMemreqEstimate( int resx,int resy,int resz, // make sure we can handle bid numbers here... all double double memCnt = 0.0; double ddTotalNum = (double)dTotalNum; + if(reqretFine) *reqretFine = -1.; double currResx = (double)resx; double currResy = (double)resy; @@ -159,10 +159,12 @@ void calculateMemreqEstimate( int resx,int resy,int resz, if(debugMemEst) debMsgStd("calculateMemreqEstimate",DM_MSG,"res:"<=0; i--) { diff --git a/intern/elbeem/intern/solver_interface.h b/intern/elbeem/intern/solver_interface.h index 1dfdf156ee5..c3dc4983cac 100644 --- a/intern/elbeem/intern/solver_interface.h +++ b/intern/elbeem/intern/solver_interface.h @@ -21,7 +21,7 @@ #if LBM_USE_GUI==1 #define USE_GLUTILITIES // for debug display -#include +//#include #include "../gui/guifuncs.h" #endif @@ -596,8 +596,10 @@ class LbmSolverInterface void initGridSizes(int &mSizex, int &mSizey, int &mSizez, ntlVec3Gfx &mvGeoStart, ntlVec3Gfx &mvGeoEnd, int mMaxRefine, bool parallel); +// return the amount of memory required in total (reqret) +// and for the finest grid only (reqretFine, can be NULL) void calculateMemreqEstimate(int resx,int resy,int resz, int refine, - float farfieldsize, double *reqret, string *reqstr); + float farfieldsize, double *reqret, double *reqretFine, string *reqstr); //! helper function to convert flag to string (for debuggin) string convertCellFlagType2String( CellFlagType flag ); diff --git a/intern/elbeem/intern/solver_main.cpp b/intern/elbeem/intern/solver_main.cpp index 270e8867b3c..afc883972e2 100644 --- a/intern/elbeem/intern/solver_main.cpp +++ b/intern/elbeem/intern/solver_main.cpp @@ -7,11 +7,11 @@ * *****************************************************************************/ -#include /* rand(3) - also in linux */ #include "solver_class.h" #include "solver_relax.h" #include "particletracer.h" #include "loop_tools.h" +#include /*****************************************************************************/ /*! perform a single LBM step */ @@ -375,7 +375,11 @@ LbmFsgrSolver::mainLoop(int lev) const int gridLoopBound=1; GRID_REGION_INIT(); #if PARALLEL==1 -#include "paraloopstart.h" +#pragma omp parallel default(shared) \ + reduction(+: \ + calcCurrentMass,calcCurrentVolume, \ + calcCellsFilled,calcCellsEmptied, \ + calcNumUsedCells ) GRID_REGION_START(); #else // PARALLEL==1 GRID_REGION_START(); @@ -1112,7 +1116,11 @@ LbmFsgrSolver::preinitGrids() GRID_REGION_INIT(); #if PARALLEL==1 -#include "paraloopstart.h" +#pragma omp parallel default(shared) \ + reduction(+: \ + calcCurrentMass,calcCurrentVolume, \ + calcCellsFilled,calcCellsEmptied, \ + calcNumUsedCells ) #endif // PARALLEL==1 GRID_REGION_START(); GRID_LOOP_START(); @@ -1145,7 +1153,11 @@ LbmFsgrSolver::standingFluidPreinit() GRID_REGION_INIT(); #if PARALLEL==1 -#include "paraloopstart.h" +#pragma omp parallel default(shared) \ + reduction(+: \ + calcCurrentMass,calcCurrentVolume, \ + calcCellsFilled,calcCellsEmptied, \ + calcNumUsedCells ) #endif // PARALLEL==1 GRID_REGION_START(); diff --git a/intern/elbeem/intern/solver_util.cpp b/intern/elbeem/intern/solver_util.cpp index 65cc2200d4e..a6685babe68 100644 --- a/intern/elbeem/intern/solver_util.cpp +++ b/intern/elbeem/intern/solver_util.cpp @@ -15,8 +15,7 @@ #include "ntl_world.h" #include "simulation_object.h" -#include /* rand(3) */ - +#include #include #ifndef sqrtf #define sqrtf sqrt diff --git a/intern/elbeem/intern/utilities.cpp b/intern/elbeem/intern/utilities.cpp index 332052e91b6..551c4d0d384 100644 --- a/intern/elbeem/intern/utilities.cpp +++ b/intern/elbeem/intern/utilities.cpp @@ -10,7 +10,6 @@ #include #include -#include /* getenv(3), strtol(3) */ #ifdef WIN32 // for timing #include @@ -482,7 +481,7 @@ double elbeemEstimateMemreq(int res, double memreq = -1.0; string memreqStr(""); // ignore farfield for now... - calculateMemreqEstimate(resx,resy,resz, refine, 0., &memreq, &memreqStr ); + calculateMemreqEstimate(resx,resy,resz, refine, 0., &memreq, NULL, &memreqStr ); if(retstr) { // copy at max. 32 characters diff --git a/intern/elbeem/intern/utilities.h b/intern/elbeem/intern/utilities.h index 0f65408d23c..825e92251fe 100644 --- a/intern/elbeem/intern/utilities.h +++ b/intern/elbeem/intern/utilities.h @@ -9,11 +9,6 @@ #ifndef UTILITIES_H #include "ntl_vector3dim.h" -// Solaris requires ieeefp.h for finite(3C) -#if !defined(linux) && defined(sun) -#include -#endif - /* debugging outputs , debug level 0 (off) to 10 (max) */ #ifdef ELBEEM_PLUGIN diff --git a/projectfiles_vc7/blender/blenlib/BLI_blenlib.vcproj b/projectfiles_vc7/blender/blenlib/BLI_blenlib.vcproj index f7038e610f1..0951c40d891 100644 --- a/projectfiles_vc7/blender/blenlib/BLI_blenlib.vcproj +++ b/projectfiles_vc7/blender/blenlib/BLI_blenlib.vcproj @@ -364,6 +364,9 @@ + + @@ -434,6 +437,9 @@ + + diff --git a/release/scripts/bpymodules/BPyMessages.py b/release/scripts/bpymodules/BPyMessages.py index 0ff8e178ac1..8ee1aa6c707 100644 --- a/release/scripts/bpymodules/BPyMessages.py +++ b/release/scripts/bpymodules/BPyMessages.py @@ -11,6 +11,8 @@ def Error_NoMeshUvActive(): Draw.PupMenu('Error%t|Active object is not a mesh with texface') def Error_NoMeshMultiresEdit(): Draw.PupMenu('Error%t|Unable to complete action with multires enabled') +def Error_NoMeshFaces(): + Draw.PupMenu('Error%t|Mesh has no faces') # File I/O messages def Error_NoFile(path): diff --git a/release/scripts/flt_export.py b/release/scripts/flt_export.py index 283c24a3ad0..d2e90bc27b8 100644 --- a/release/scripts/flt_export.py +++ b/release/scripts/flt_export.py @@ -1,45 +1,25 @@ #!BPY """ Registration info for Blender menus: Name: 'OpenFlight (.flt)...' -Blender: 237 +Blender: 245 Group: 'Export' Tip: 'Export to OpenFlight v16.0 (.flt)' """ -__author__ = "Greg MacDonald" -__version__ = "1.2 10/20/05" +__author__ = "Greg MacDonald, Geoffrey Bantle" +__version__ = "2.0 11/21/07" __url__ = ("blender", "elysiun", "Author's homepage, http://sourceforge.net/projects/blight/") __bpydoc__ = """\ This script exports v16.0 OpenFlight files. OpenFlight is a registered trademark of MultiGen-Paradigm, Inc. -Run from "File->Export" menu. - -Options are available from Blender's "Scripts Config Editor," accessible through -the "Scripts->System" menu from the scripts window. - -Features:
-* Heirarchy retained.
-* Normals retained.
-* First texture exported.
-* Diffuse material color is exported as the face color, material color, or both -depending on the option settings.
-* Double sided faces are exported as two faces.
-* Object transforms exported. - -Things To Be Aware Of:
-* Object names are exported, not mesh or data names. -* Material indices that don't have a material associated with them will confuse the -exporter. If a warning appears about this, correct it by deleting the offending -material indices in Blender. - -What's Not Handled:
-* Animations.
-* Vetex colors.
+Feature overview and more availible at: +http://wiki.blender.org/index.php/Scripts/Manual/Export/openflight_flt """ # flt_export.py is an OpenFlight exporter for blender. -# Copyright (C) 2005 Greg MacDonald +# +# Copyright (C) 2005 Greg MacDonald, 2007 Blender Foundation. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -56,29 +36,87 @@ What's Not Handled:
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. import Blender +from Blender import Modifier +import os.path +import flt_properties +import flt_defaultp as defaultp from flt_filewalker import FltOut +from flt_filewalker import FileFinder +from flt_properties import * +import shutil + +FF = FileFinder() +records = process_recordDefs() class ExporterOptions: def __init__(self): - self.defaults = { 'Diffuse Color To OpenFlight Material': False, - 'Diffuse Color To OpenFlight Face': True} - - d = Blender.Registry.GetKey('flt_export', True) - - if d == None or d.keys() != self.defaults.keys(): - d = self.defaults - Blender.Registry.SetKey('flt_export', d, True) - self.verbose = 1 self.tolerance = 0.001 - self.use_mat_color = d['Diffuse Color To OpenFlight Material'] - self.use_face_color = d['Diffuse Color To OpenFlight Face'] + self.writevcol = True + #new stuff + self.export_shading = 0 + self.shading_default = 45.0 + self.basepath = os.path.dirname(Blender.Get('filename')) + self.scale = 1.0 + + #set externals path + if(os.path.exists(os.path.join(self.basepath,'externals'))): + self.externalspath = os.path.join(self.basepath,'externals') + else: + self.externalspath = self.basepath + + self.doxrefs = 1 + + #texture options + if(os.path.exists(os.path.join(self.basepath,'textures'))): + self.texturespath = os.path.join(self.basepath,'textures') + else: + self.texturespath = self.basepath + + #misc + self.write_attrib_files = 0 + self.copy_textures = 0 + self.export_transform = 0 + self.flattenmesh = False + + self.xapp = 1 + reg = Blender.Registry.GetKey('flt_export',1) + if(reg and 'xappath' in reg.keys()): + self.xappath = reg['xappath'] + else: + self.xappath = '' options = ExporterOptions() +tex_files = dict() #a list of (possibly) modified texture path names + +tex_layers = ['Layer0', 'Layer1', 'Layer2', 'Layer3', 'Layer4', 'Layer5', 'Layer6', 'Layer7'] +mask = 2147483648 +mtexmasks = [] +for i in xrange(7): + mtexmasks.append(mask) + mask = mask / 2 FLOAT_TOLERANCE = options.tolerance +#need to move all this stuff to flt_properties.py. identity_matrix = [[1.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 0.0, 1.0]] +alltypes = [2,4,11,73,63,111] +childtypes = { + 2 : [111,2,73,4,14,63], + 4 : [111], + 73 : [111,2,73,4,14,63], + 63 : [], + 14 : [111,2,73,4,14,63], + 111 : [] +} +recordlen = { + 2: 44, + 4: 28, + 73: 80, + 63: 216, + 14: 384, + 111: 156 +} def is_identity(m): for i in xrange(4): @@ -102,13 +140,47 @@ class MaterialDesc: self.alpha = 1.0 # Range is [0.0, 1.0] class VertexDesc: - def __init__(self, co=None, no=None, uv=None): + def __init__(self, co=None, no=None, uv=None, fltindex=None,cindex=None): if co: self.x, self.y, self.z = tuple(co) else: self.x = self.y = self.z = 0.0 if no: self.nx, self.ny, self.nz = tuple(no) else: self.nx = self.ny = self.nz = 0.0 if uv: self.u, self.v = tuple(uv) else: self.u = self.v = 0.0 + if cindex: self.cindex = cindex + else: self.cindex = 127 + self.fltindex = fltindex + self.accum = 0 + +class shadowVert: + def __init__(self,bvert,object,world,normal): + global options + + self.co = Blender.Mathutils.Vector(bvert.co[0],bvert.co[1],bvert.co[2]) + #if world: + # vec = self.co + # vec = Blender.Mathutils.Vector(vec[0] * options.scale, vec[1] * options.scale, vec[2] * options.scale) #scale + # self.co = Blender.Mathutils.TranslationMatrix(vec) * (self.co * object.getMatrix('worldspace')) + + if normal: + #if world: + # self.no = Blender.Mathutils.Vector(normal * object.getMatrix('worldspace')).normalize() + #else: + self.no = Blender.Mathutils.Vector(normal[0],normal[1],normal[2]) + + else: + #if world: + #self.no = Blender.Mathutils.Vector(bvert.no * object.getMatrix('worldspace')).normalize() + #else: + self.no = Blender.Mathutils.Vector(bvert.no[0],bvert.no[1],bvert.no[2]) + + #do scaling factor + #if options.scale != 1.0: + #self.co[0] = self.co[0] * options.scale + #self.co[1] = self.co[1] * options.scale + #self.co[2] = self.co[2] * options.scale + + self.index = bvert.index class GlobalResourceRepository: def new_face_name(self): @@ -121,44 +193,98 @@ class GlobalResourceRepository: def request_vertex_desc(self, i): return self.vertex_lst[i] - def request_vertex_index(self, desc): - match = None - for i, v in enumerate(self.vertex_lst): - if\ - abs(v.x - desc.x) > FLOAT_TOLERANCE or\ - abs(v.y - desc.y) > FLOAT_TOLERANCE or\ - abs(v.z - desc.z) > FLOAT_TOLERANCE or\ - abs(v.nx - desc.nx) > FLOAT_TOLERANCE or\ - abs(v.ny - desc.ny) > FLOAT_TOLERANCE or\ - abs(v.nz - desc.nz) > FLOAT_TOLERANCE or\ - abs(v.u - desc.u) > FLOAT_TOLERANCE or\ - abs(v.v - desc.v) > FLOAT_TOLERANCE: - pass - else: - match = i - break + def request_vertex_index(self, object, mesh, face, vfindex, uvok,cindex): - if match != None: - return match + flatShadeNorm = None + + if type(face) is list: + vertex = face[vfindex] + elif str(type(face)) == "": + vertex = face + elif str(type(face)) == "": + if vfindex == 1: + vertex = face.v1 + elif vfindex == 2: + vertex = face.v2 + elif str(type(face)) == "": + if not face.smooth: + flatShadeNorm = face.no + vertex = face.v[vfindex] + else: + return None + + if not self.namehash.has_key(object.name): + self.namehash[object.name] = dict() + indexhash = self.namehash[object.name] + + #export in global space? THIS HAS BEEN MADE REDUNDANT... REMOVE ME + if not options.export_transform: + vertex = shadowVert(vertex,object,True,flatShadeNorm) else: - self.vertex_lst.append(desc) - return len(self.vertex_lst) - 1 - - def request_texture_index(self, filename): + vertex = shadowVert(vertex,object,False,flatShadeNorm) + + + #Check to see if this vertex has been visited before. If not, add + if not indexhash.has_key(vertex.index): + if uvok: + newvdesc = VertexDesc(vertex.co, vertex.no, face.uv[vfindex], self.nextvindex,cindex=cindex) + else: + newvdesc = VertexDesc(co=vertex.co, no=vertex.no,fltindex=self.nextvindex,cindex=cindex) + + indexhash[vertex.index] = [newvdesc] + self.vertex_lst.append(newvdesc) + self.nextvindex = self.nextvindex + 1 + return newvdesc.fltindex + + else: + desclist = indexhash[vertex.index] + if uvok: + faceu = face.uv[vfindex][0] + facev = face.uv[vfindex][1] + else: + faceu = 0.0 + facev = 0.0 + for vdesc in desclist: + if\ + abs(vdesc.x - vertex.co[0]) > FLOAT_TOLERANCE or\ + abs(vdesc.y - vertex.co[1]) > FLOAT_TOLERANCE or\ + abs(vdesc.z - vertex.co[2]) > FLOAT_TOLERANCE or\ + abs(vdesc.nx - vertex.no[0]) > FLOAT_TOLERANCE or\ + abs(vdesc.ny - vertex.no[1]) > FLOAT_TOLERANCE or\ + abs(vdesc.nz - vertex.no[2]) > FLOAT_TOLERANCE or\ + vdesc.cindex != cindex or\ + abs(vdesc.u - faceu) > FLOAT_TOLERANCE or\ + abs(vdesc.v - facev) > FLOAT_TOLERANCE: + pass + else: + return vdesc.fltindex + + #if we get this far, we didnt find a match. Add a new one and return + if uvok: + newvdesc = VertexDesc(vertex.co, vertex.no, face.uv[vfindex], self.nextvindex,cindex=cindex) + else: + newvdesc = VertexDesc(co=vertex.co, no=vertex.no,fltindex=self.nextvindex,cindex=cindex) + indexhash[vertex.index].append(newvdesc) + self.vertex_lst.append(newvdesc) + self.nextvindex = self.nextvindex + 1 + return newvdesc.fltindex + + + def request_texture_index(self, image): match = None for i in xrange(len(self.texture_lst)): - if self.texture_lst[i] != filename: + if self.texture_lst[i] != image: continue match = i break if match != None: return match else: - self.texture_lst.append(filename) + self.texture_lst.append(image) return len(self.texture_lst) - 1 def request_texture_filename(self, index): - return self.texture_lst[index] + return Blender.sys.expandpath(self.texture_lst[index].getFilename()) def texture_count(self): return len(self.texture_lst) @@ -239,7 +365,11 @@ class GlobalResourceRepository: return len(self.color_lst) def __init__(self): + #Vertex handling self.vertex_lst = [] + self.nextvindex = 0 + self.namehash = dict() + self.texture_lst = [] self.material_lst = [] self.color_lst = [[255, 255, 255]] @@ -253,7 +383,6 @@ class Node: if self.object: if options.verbose >= 2: print '\t' * level[0], self.name, self.object.type - level[0] += 1 for child in self.children: @@ -288,183 +417,530 @@ class Node: self.header.fw.write_ushort(length+5) # Length of record self.header.fw.write_string(name, length+1) # name + zero terminator + def write_comment(self,comment): + length = len(comment) + if length >= 65535: + comment = comment[:65530] + length = len(comment) + + pad = (length % 4) - 1 + if pad < 0: + pad = None + reclength = length + 5 + else: + reclength = length + 5 + pad + + self.header.fw.write_short(31) # Comment Opcode + self.header.fw.write_ushort(reclength) # Length of record is 4 + comment length + null terminator + pad + self.header.fw.write_string(comment,length+1) # comment + zero terminator + if pad: + self.header.fw.pad(pad) # pad to multiple of 4 bytes + # Initialization sets up basic tree structure. - def __init__(self, parent, header, object, object_lst): + def __init__(self, parent, header, object,props): + global options + self.header = header self.object = object if object: self.name = self.object.name - self.matrix = self.object.getMatrix('localspace') + if not options.export_transform: + oloc = Blender.Mathutils.Vector(object.getLocation('worldspace')) + vec = Blender.Mathutils.Vector(oloc[0] * options.scale, oloc[1] * options.scale, oloc[2] * options.scale) #scale + self.matrix = self.object.getMatrix('worldspace') * Blender.Mathutils.TranslationMatrix(vec - oloc) + else: + self.matrix = self.object.getMatrix('localspace') #do matrix mult here. + self.props = props + self.child_objects = self.header.parenthash[object.name] else: self.name = 'no name' self.matrix = None - + self.props = None + self.child_objects = self.header.child_objects + self.children = [] self.parent = parent if parent: parent.children.append(self) - - left_over = object_lst[:] - self.child_objects = [] - - # Add children to child list and remove from left_over list. - # Pop is faster then remove - i = len(object_lst) - while i: - i-=1 - if object_lst[i].parent == object: - self.child_objects.append(left_over.pop(i)) - # Spawn children. - self.has_object_child = False # For Database class. for child in self.child_objects: - if child.type == 'Mesh': - BlenderMesh(self, header, child, left_over) - self.has_object_child = True - else: # Treat all non meshes as emptys - BlenderEmpty(self, header, child, left_over) - + if(not child.restrictDisplay): + childprops = None + type = None + if not child.properties.has_key('FLT'): + if child.type == 'Empty': + if child.DupGroup: + childprops = FLTXRef.copy() + type = 63 + else: + childprops = FLTGroup.copy() + type = 2 + elif child.type == 'Mesh': + if self.header.childhash[child.name] or not child.parent: + childprops = FLTGroup.copy() + type = 2 + else: + childprops = FLTObject.copy() + type = 4 + + else: + childprops = dict() + for prop in child.properties['FLT']: + childprops[prop] = child.properties['FLT'][prop] + type = child.properties['FLT']['type'] + + if type in self.childtypes and type in alltypes: + Newnode = FLTNode(self,header,child,childprops,type) + if child.type == 'Mesh': + self.header.mnodes.append(Newnode) class FaceDesc: def __init__(self): self.vertex_index_lst = [] + self.mface = None self.texture_index = -1 self.material_index = -1 self.color_index = 127 + self.renderstyle = 0 + self.twoside = 0 + self.name = None #uses next FLT name if not set... fix resolution of conflicts! + + #Multi-Tex info. Dosn't include first UV Layer! + self.uvlayer = list() #list of list of tuples for UV coordinates. + self.images = list() #list of texture indices for seperate UV layers + self.mtex = list() + self.subface = None #can either be 'Push' or 'Pop' + +def edge_get_othervert(vert, edge): + if edge.v1 == vert: + return edge.v2 + elif edge.v2 == vert: + return edge.v1 + return None + +class FLTNode(Node): + def walkLoop(self, targetvert, startvert, startedge, edgelist, visited, vedges, closeloop): + loop = [targetvert] + + curvert = startvert + curedge = startedge + visited[curedge] = True + found = False + + while not found: + loop.append(curvert) + disk = vedges[curvert.index] + if not closeloop: + if len(disk) == 1: + visited[curedge] = True + break + else: + if len(disk) < 2: #what? + visited[curedge] = True + return None + + if disk[0] == curedge: + curedge = disk[1] + else: + curedge = disk[0] + if curedge.v1.index == curvert.index: + curvert = curedge.v2 + else: + curvert = curedge.v1 + + visited[curedge] = True + + if(curvert == targetvert): + found = True + + return loop -class BlenderMesh(Node): - def blender_export(self): - Node.blender_export(self) - - mesh = self.object.getData() - mesh_hasuv = mesh.hasFaceUV() - # Gather materials and textures. - tex_index_lst = [] - mat_index_lst = [] - color_index_lst = [] - materials = mesh.getMaterials() - - if not materials: - materials = [Blender.Material.New()] - - for mat in materials: - # Gather Color. - if options.use_face_color: - color_index_lst.append(self.header.GRR.request_color_index(mat.getRGBCol())) - else: - color_index_lst.append(127) # white - # Gather Texture. - mtex_lst = mat.getTextures() - - index = -1 - mtex = mtex_lst[0] # Not doing multi-texturing at the moment. - if mtex != None: - tex = mtex_lst[0].tex - if tex != None: - image = tex.getImage() - if image != None: - filename = image.getFilename() - index = self.header.GRR.request_texture_index(filename) - - tex_index_lst.append(index) - - # Gather Material - mat_desc = MaterialDesc() - mat_desc.name = mat.name - mat_desc.alpha = mat.getAlpha() - mat_desc.shininess = mat.getSpec() * 64.0 # 2.0 => 128.0 - if options.use_mat_color: - mat_desc.diffuse = mat.getRGBCol() - else: - mat_desc.diffuse = [1.0, 1.0, 1.0] - - mat_desc.specular = mat.getSpecCol() - amb = mat.getAmb() - mat_desc.ambient = [amb, amb, amb] - emit = mat.getEmit() - mat_desc.emissive = [emit, emit, emit] - - mat_index_lst.append(self.header.GRR.request_material_index(mat_desc)) - - # Faces described as lists of indices into the GRR's vertex_lst. - for face in mesh.faces: - - face_v = face.v # Faster access - - # Create vertex description list for each face. - if mesh_hasuv: - vertex_lst = [VertexDesc(v.co, v.no, face.uv[i]) for i, v in enumerate(face_v)] - else: - vertex_lst = [VertexDesc(v.co, v.no) for i, v in enumerate(face_v)] - - index_lst = [] - for vert_desc in vertex_lst: - index_lst.append(self.header.GRR.request_vertex_index(vert_desc)) - - face_desc = FaceDesc() - face_desc.vertex_index_lst = index_lst - - if face.materialIndex < len(materials): - face_desc.color_index = color_index_lst[face.materialIndex] - face_desc.texture_index = tex_index_lst[face.materialIndex] - face_desc.material_index = mat_index_lst[face.materialIndex] - else: - if options.verbose >=1: - print 'Warning: Missing material for material index. Materials will not be imported correctly. Fix by deleting abandoned material indices in Blender.' - - self.face_lst.append(face_desc) - - # Export double sided face as 2 faces with opposite orientations. - if mesh_hasuv and face.mode & Blender.NMesh.FaceModes['TWOSIDE']: - # Create vertex description list for each face. they have a face mode, so we know they have a UV too. - vertex_lst = [VertexDesc(v.co, -v.no, face.uv[i]) for i, v in enumerate(face_v)] - vertex_lst.reverse() # Reversing flips the face. - - index_lst = [] - for vert_desc in vertex_lst: - index_lst.append(self.header.GRR.request_vertex_index(vert_desc)) - + def buildVertFaces(self,vertuse): + for vert in self.exportmesh.verts: + if vertuse[vert.index][0] == False and vertuse[vert.index][1] == 0: face_desc = FaceDesc() - face_desc.vertex_index_lst = index_lst - if face.materialIndex < len(materials): - face_desc.color_index = color_index_lst[face.materialIndex] - face_desc.texture_index = tex_index_lst[face.materialIndex] - face_desc.material_index = mat_index_lst[face.materialIndex] - else: - if options.verbose >=1: - print 'Error: No material for material index. Delete abandoned material indices in Blender.' - + face_desc.vertex_index_lst.append(self.header.GRR.request_vertex_index(self.object, self.exportmesh, vert, 0,0,0)) + face_desc.renderstyle = 3 + face_desc.color_index = 227 self.face_lst.append(face_desc) - def write_faces(self): - for face_desc in self.face_lst: - face_name = self.header.GRR.new_face_name() + def buildEdgeFaces(self,vertuse): + for edge in self.exportmesh.edges: + v1 = vertuse[edge.v1.index] + v2 = vertuse[edge.v2.index] + if v1[0] == False and v2[0] == False: + if v1[1] == 1 and v2[1] == 1: + face_desc = FaceDesc() + face_desc.vertex_index_lst.append(self.header.GRR.request_vertex_index(self.object, self.exportmesh, edge, 1, 0,0)) + face_desc.vertex_index_lst.append(self.header.GRR.request_vertex_index(self.object, self.exportmesh, edge, 2, 0,0)) + face_desc.renderstyle = 3 + face_desc.color_index = 227 + self.face_lst.append(face_desc) + + + def vertwalk(self, startvert, loop, disk, visited): + visited[startvert] = True + for edge in disk[startvert]: + othervert = edge_get_othervert(startvert, edge) + if not visited[othervert]: + loop.append(othervert) + self.vertwalk(othervert,loop,disk,visited) + + def buildOpenFacesNew(self, vertuse): + wireverts = list() + wiredges = list() + visited = dict() + disk = dict() + loops = list() + + for edge in self.exportmesh.edges: + v1 = vertuse[edge.v1.index] + v2 = vertuse[edge.v2.index] + if v1[0] == False and v2[0] == False: + if v1[1] < 3 and v2[1] < 3: + wireverts.append(edge.v1) + wireverts.append(edge.v2) + wiredges.append(edge) + + #build disk data + for vert in wireverts: + visited[vert] = False + disk[vert] = list() + for edge in wiredges: + disk[edge.v1].append(edge) + disk[edge.v2].append(edge) + + #first pass: do open faces + for vert in wireverts: + if not visited[vert] and vertuse[vert.index][1] == 1: + visited[vert] = True + loop = [vert] + othervert = edge_get_othervert(vert, disk[vert][0]) + self.vertwalk(othervert, loop, disk, visited) + if len(loop) > 2: loops.append( ('Open', loop) ) + + for vert in wireverts: + if not visited[vert]: + visited[vert] = True + loop = [vert] + othervert = edge_get_othervert(vert,disk[vert][0]) + self.vertwalk(othervert, loop, disk, visited) + if len(loop) > 2: loops.append( ('closed', loop) ) + + #now go through the loops and append. + for l in loops: + (type, loop) = l + face_desc = FaceDesc() + for i,vert in enumerate(loop): + face_desc.vertex_index_lst.append(self.header.GRR.request_vertex_index(self.object,self.exportmesh,loop,i,0,0)) + if type == 'closed': + face_desc.renderstyle = 2 + else: + face_desc.renderstyle = 3 + face_desc.color_index = 227 + self.face_lst.append(face_desc) + + def sortFLTFaces(self,a,b): + aindex = a.getProperty("FLT_ORIGINDEX") + bindex = b.getProperty("FLT_ORIGINDEX") + + if aindex > bindex: + return 1 + elif aindex < bindex: + return -1 + return 0 + + def buildNormFaces(self): + + global options + meshlayers = self.exportmesh.getUVLayerNames() + oldlayer = self.exportmesh.activeUVLayer + uvok = 0 + subfaceok = 0 + subfacelevel = 0 + + #special case + if self.exportmesh.faceUV and len(meshlayers) == 1: + uvok = 1 + elif self.exportmesh.faceUV and tex_layers[0] in meshlayers: + self.exportmesh.activeUVLayer = tex_layers[0] + uvok = 1 + + #Sort faces according to the subfaces/FLT indices + if "FLT_ORIGINDEX" in self.exportmesh.faces.properties and "FLT_SFLEVEL" in self.exportmesh.faces.properties: + exportfaces = list() + for face in self.exportmesh.faces: + exportfaces.append(face) + exportfaces.sort(self.sortFLTFaces) + subfaceok = 1 + else: + exportfaces = self.exportmesh.faces + # Faces described as lists of indices into the GRR's vertex_lst. + for face in exportfaces: + descs = list() + #first we export the face as normal + index_lst = [] + face_v = face.verts + for i, v in enumerate(face_v): + index_lst.append(self.header.GRR.request_vertex_index(self.object,self.exportmesh,face,i,uvok,0)) + face_desc = FaceDesc() + face_desc.vertex_index_lst = index_lst + face_desc.mface = face + descs.append(face_desc) + + #deal with subfaces + if subfaceok: + fsflevel = face.getProperty("FLT_SFLEVEL") + for face_desc in descs: + if fsflevel > subfacelevel: + face_desc.subface = 'Push' + subfacelevel = fsflevel + elif fsflevel < subfacelevel: + face_desc.subface = 'Pop' + subfacelevel = fsflevel + + + if uvok and (face.mode & Blender.Mesh.FaceModes.TWOSIDE): + face_desc.renderstyle = 1 + for face_desc in descs: + if "FLT_COL" in self.exportmesh.faces.properties: + color_index = face.getProperty("FLT_COL") +# if(color_index < 127): +# color_index = 127 #sanity check for face color indices + if(color_index == 0): + color_index = 127 + face_desc.color_index = color_index + else: + face_desc.color_index = 127 + if "FLT_ID" in self.exportmesh.faces.properties: + face_desc.name = face.getProperty("FLT_ID") #need better solution than this. + + self.face_lst.append(face_desc) + if uvok: + self.exportmesh.activeUVLayer = oldlayer + + def buildTexData(self): + + meshlayers = self.exportmesh.getUVLayerNames() + oldlayer = self.exportmesh.activeUVLayer + uvok = 0 + + if self.exportmesh.faceUV and len(meshlayers) == 1: + uvok = 1 + if self.exportmesh.faceUV and tex_layers[0] in meshlayers: + self.exportmesh.activeUVLayer = tex_layers[0] + uvok = 1 + + if uvok: + #do base layer. UVs have been stored on vertices directly already. + for i, face in enumerate(self.face_lst): + if face.mface: + mface = face.mface + image = mface.image + if image != None and mface.mode & Blender.Mesh.FaceModes["TEX"]: + index = self.header.GRR.request_texture_index(image) + else: + index = -1 + face.texture_index = index + + for i, face in enumerate(self.face_lst): + if face.mface: + mface_v = face.mface.v + for v in mface_v: + face.uvlayer.append([]) + + for layername in tex_layers[1:]: + if layername in meshlayers: + self.exportmesh.activeUVLayer=layername + for i, face in enumerate(self.face_lst): + if face.mface: + + face.mtex.append(layername) + mface = face.mface + mface_v = mface.v + image = mface.image + + if image != None and mface.mode & Blender.Mesh.FaceModes["TEX"]: + index = self.header.GRR.request_texture_index(image) + face.images.append(index) + else: + face.images.append(-1) + + for j, v in enumerate(mface_v): + face.uvlayer[j].append(tuple(mface.uv[j])) + if uvok: + self.exportmesh.activeUVLayer = oldlayer + def blender_export(self): + global options + Node.blender_export(self) + if self.opcode == 111: + self.exportmesh = Blender.Mesh.New() + self.exportmesh.getFromObject(self.object.name) + + for vert in self.exportmesh.verts: + if not options.export_transform: + vec = vert.co + vec = Blender.Mathutils.Vector(vec[0] * options.scale, vec[1] * options.scale, vec[2] * options.scale) #scale + vert.co = Blender.Mathutils.TranslationMatrix(vec) * (vert.co * self.object.getMatrix('worldspace')) + + if options.scale != 1.0: + vert.co = vert.co * options.scale + + if("FLT_VCOL") in self.mesh.verts.properties: + for v in self.exportmesh.verts: + self.vert_lst.append(self.header.GRR.request_vertex_index(self.object,self.exportmesh,v,0,0,v.getProperty("FLT_VCOL"))) + else: + for v in self.mesh.verts: + self.vert_lst.append(self.header.GRR.request_vertex_index(self.object,self.mesh,v,0,0,127)) + + + + elif self.mesh: + orig_mesh = self.object.getData(mesh=True) + self.exportmesh = Blender.Mesh.New() + default = None + + + if options.export_shading: + mods = self.object.modifiers + hasedsplit = False + for mod in mods: + if mod.type == Blender.Modifier.Types.EDGESPLIT: + hasedsplit = True + break + if not hasedsplit: + default = mods.append(Modifier.Types.EDGESPLIT) + default[Modifier.Settings.EDGESPLIT_ANGLE] = options.shading_default + default[Modifier.Settings.EDGESPLIT_FROM_ANGLE] = True + default[Modifier.Settings.EDGESPLIT_FROM_SHARP] = False + self.object.makeDisplayList() + + self.exportmesh.getFromObject(self.object.name) + + #recalculate vertex positions + for vert in self.exportmesh.verts: + if not options.export_transform: + vec = vert.co + vec = Blender.Mathutils.Vector(vec[0] * options.scale, vec[1] * options.scale, vec[2] * options.scale) #scale + vert.co = Blender.Mathutils.TranslationMatrix(vec) * (vert.co * self.object.getMatrix('worldspace')) + + if options.scale != 1.0: + vert.co = vert.co * options.scale + + flipped = self.object.getMatrix('worldspace').determinant() + + if not options.export_transform: + self.exportmesh.calcNormals() + + + if default: + #remove modifier from list + mods.remove(default) + self.object.makeDisplayList() + + #build some adjacency data + vertuse = list() + wiredges = list() + openends = list() + for v in self.exportmesh.verts: + vertuse.append([False,0]) + + #build face incidence data + for face in self.exportmesh.faces: + for i, v in enumerate(face.verts): + vertuse[v.index][0] = True + + for edge in self.exportmesh.edges: #count valance + vertuse[edge.v1.index][1] = vertuse[edge.v1.index][1] + 1 + vertuse[edge.v2.index][1] = vertuse[edge.v2.index][1] + 1 + + #create all face types + self.buildVertFaces(vertuse) + self.buildEdgeFaces(vertuse) + self.buildOpenFacesNew(vertuse) + self.buildNormFaces() + self.buildTexData() + + if not options.export_transform: + if flipped < 0: + for vdesc in self.header.GRR.vertex_lst: + vdesc.accum = 0 + for face in self.face_lst: + face.vertex_index_lst.reverse() + for vert in face.vertex_index_lst: + self.header.GRR.vertex_lst[vert].accum = 1 + + for vdesc in self.header.GRR.vertex_lst: + if vdesc.accum: + vdesc.nx = vdesc.nx * -1 + vdesc.ny = vdesc.ny * -1 + vdesc.nz = vdesc.nz * -1 + + + def write_faces(self): + sublevel = 0 + for face_desc in self.face_lst: + if face_desc.name: + face_name = face_desc.name + else: + face_name = self.header.GRR.new_face_name() + + #grab the alpha value. + alpha = 0 + if face_desc.texture_index > -1: + try: + typestring = os.path.splitext(self.header.GRR.texture_lst[face_desc.texture_index].getFilename())[1] + if typestring == '.inta' or typestring == '.rgba': + alpha = 1 + except: + pass + + if not alpha: + for index in face_desc.images: + try: + typestring = os.path.splitext(self.header.GRR.texture_lst[index].getFilename())[1] + if typestring == '.inta' or typestring == '.rgba': + alpha = 1 + except: + pass + + if face_desc.subface: + if face_desc.subface == 'Push': + self.header.fw.write_short(19) + self.header.fw.write_ushort(4) + sublevel += 1 + else: + self.header.fw.write_short(20) + self.header.fw.write_ushort(4) + sublevel -= 1 self.header.fw.write_short(5) # Face opcode self.header.fw.write_ushort(80) # Length of record self.header.fw.write_string(face_name, 8) # ASCII ID self.header.fw.write_int(-1) # IR color code - self.header.fw.write_short(0) # Relative priority - self.header.fw.write_char(0) # Draw type + self.header.fw.write_short(0) # Relative priority + self.header.fw.write_char(face_desc.renderstyle) # Draw type self.header.fw.write_char(0) # Draw textured white. self.header.fw.write_ushort(0) # Color name index self.header.fw.write_ushort(0) # Alt color name index self.header.fw.write_char(0) # Reserved - self.header.fw.write_char(1) # Template + self.header.fw.write_char(alpha) # Template self.header.fw.write_short(-1) # Detail tex pat index self.header.fw.write_short(face_desc.texture_index) # Tex pattern index self.header.fw.write_short(face_desc.material_index) # material index self.header.fw.write_short(0) # SMC code - self.header.fw.write_short(0) # Feature code + self.header.fw.write_short(0) # Feature code self.header.fw.write_int(0) # IR material code self.header.fw.write_ushort(0) # transparency 0 = opaque self.header.fw.write_uchar(0) # LOD generation control self.header.fw.write_uchar(0) # line style index - self.header.fw.write_int(0x00000000) # Flags + self.header.fw.write_int(0) # Flags self.header.fw.write_uchar(2) # Light mode + #self.header.fw.write_uchar(3) # Light mode + self.header.fw.pad(7) # Reserved - self.header.fw.write_uint(-1) # Packed color - self.header.fw.write_uint(-1) # Packed alt color + self.header.fw.write_uint(0) # Packed color + self.header.fw.write_uint(0) # Packed alt color self.header.fw.write_short(-1) # Tex map index self.header.fw.write_short(0) # Reserved self.header.fw.write_uint(face_desc.color_index) # Color index @@ -473,7 +949,24 @@ class BlenderMesh(Node): self.header.fw.write_short(-1) # Shader index self.write_longid(face_name) - + + + #Write Multitexture field if appropriate + mtex = len(face_desc.mtex) + if mtex: + uvmask = 0 + for layername in face_desc.mtex: + mask = mtexmasks[tex_layers.index(layername)-1] + uvmask |= mask + self.header.fw.write_ushort(52) # MultiTexture Opcode + self.header.fw.write_ushort(8 + (mtex * 8)) # Length + self.header.fw.write_uint(uvmask) # UV mask + for i in xrange(mtex): + self.header.fw.write_ushort(face_desc.images[i]) # Tex pattern index + self.header.fw.write_ushort(0) # Tex effect + self.header.fw.write_ushort(0) # Tex Mapping index + self.header.fw.write_ushort(0) # Tex data. User defined + self.write_push() # Vertex list record @@ -484,72 +977,95 @@ class BlenderMesh(Node): for vert_index in face_desc.vertex_index_lst: # Offset into vertex palette self.header.fw.write_int(vert_index*64+8) - - self.write_pop() - - def write(self): - if self.open_flight_type == 'Object': - self.header.fw.write_short(4) # Object opcode - self.header.fw.write_ushort(28) # Length of record - self.header.fw.write_string(self.name, 8) # ASCII ID - self.header.fw.pad(16) - - self.write_longid(self.name) + #UV list record + if mtex: + #length = 8 + (numverts * multitex * 8) + self.header.fw.write_ushort(53) # UV List Ocode + self.header.fw.write_ushort(8 + (num_verts*mtex*8)) # Record Length + self.header.fw.write_uint(uvmask) # UV mask + for i, vert_index in enumerate(face_desc.vertex_index_lst): + for uv in face_desc.uvlayer[i]: + self.header.fw.write_float(uv[0]) #U coordinate + self.header.fw.write_float(uv[1]) #V coordinate + self.write_pop() + #clean up faces at the end of meshes.... + if sublevel: + self.header.fw.write_short(20) + self.header.fw.write_ushort(4) + + def write_lps(self): + # Vertex list record + self.write_push() + self.header.fw.write_short(72) # Vertex list opcode + num_verts = len(self.vert_lst) + self.header.fw.write_ushort(4*num_verts+4) # Length of record + + for vert_index in self.vert_lst: + # Offset into vertex palette + self.header.fw.write_int(vert_index*64+8) + self.write_pop() + def write(self): + self.header.fw.write_short(self.opcode) + self.header.fw.write_ushort(recordlen[self.opcode]) + exportdict = FLT_Records[self.opcode].copy() + for key in exportdict.keys(): + if self.props.has_key(key): + exportdict[key] = self.props[key] + + if self.opcode == 63 and options.externalspath: + try: + exportdict['3t200!filename'] = os.path.join(options.externalspath,self.object.DupGroup.name+'.flt') + self.header.xrefnames.append(self.object.DupGroup.name) + except: + pass + + for key in records[self.opcode]: + (type,length,propname) = records[self.opcode][key] + write_prop(self.header.fw,type,exportdict[propname],length) + + if self.props.has_key('comment'): + self.write_comment(self.props['comment']) + + self.write_longid(self.name) #fix this! + + if options.export_transform or self.opcode == 63: + #writing transform matrix.... self.write_matrix() - - if self.face_lst != []: - self.write_push() - - self.write_faces() - - self.write_pop() - else: - self.header.fw.write_short(2) # Group opcode - self.header.fw.write_ushort(44) # Length of record - self.header.fw.write_string(self.name, 8) # ASCII ID - self.header.fw.pad(32) - - self.write_longid(self.name) - - # Because a group can contain faces as well as children. - self.write_push() - - self.write_faces() - - for child in self.children: - child.write() - - self.write_pop() - def __init__(self, parent, header, object, object_lst): - Node.__init__(self, parent, header, object, object_lst) - self.face_lst = [] - - if self.children: - self.open_flight_type= 'Group' - else: # Empty list. - self.open_flight_type = 'Object' - - -class BlenderEmpty(Node): - def write(self): - self.header.fw.write_short(2) # Group opcode - self.header.fw.write_ushort(44) # Length of record - self.header.fw.write_string(self.name, 8) # ASCII ID - self.header.fw.pad(32) - - self.write_longid(self.name) - - self.write_matrix() - - if self.children: # != [] + if self.opcode == 111: + self.write_lps() + elif self.face_lst != [] or self.children: self.write_push() - - for child in self.children: - child.write() - + if self.face_lst != []: + #self.write_push() + self.write_faces() + #self.write_pop() + + if self.children: + #self.write_push() + for child in self.children: + child.write() + #self.write_pop() self.write_pop() + + def __init__(self, parent, header, object,props,type): + self.opcode = type #both these next two lines need to be in the node class.... + self.childtypes = childtypes[self.opcode] + Node.__init__(self, parent, header, object,props) + self.face_lst = [] + self.vert_lst = [] #for light points. + self.mesh = None + self.uvlayer = 0 + self.flipx = False + self.flipy = False + self.flipz = False + + + if self.object.type == 'Mesh': + self.mesh = self.object.getData(mesh=True) + if(self.mesh.faceUV): + self.uvLayer = len(self.mesh.getUVLayerNames()) class Database(Node): def write_header(self): @@ -568,8 +1084,19 @@ class Database(Node): self.fw.write_int(0) # projection type, 0 = flat earth self.fw.pad(30) self.fw.write_short(1) # double precision - self.fw.pad(140) + self.fw.write_int(100) # database origin type + self.fw.pad(88) + try: + self.fw.write_double(self.header.scene.properties['FLT']['origin lat']) #database origin lattitude + except: + self.fw.write_double(0) + try: + self.fw.write_double(self.header.scene.properties['FLT']['origin lon']) #database origin longitude + except: + self.fw.write_double(0) + self.fw.pad(32) self.fw.write_int(0) # ellipsoid model, 0 = WSG 1984 + self.fw.pad(52) def write_vert_pal(self): @@ -579,14 +1106,13 @@ class Database(Node): self.fw.write_short(67) # Vertex palette opcode. self.fw.write_short(8) # Length of record self.fw.write_int(self.GRR.vertex_count() * 64 + 8) # Length of everything. - # Write records for individual vertices. for i in xrange(self.GRR.vertex_count()): desc = self.GRR.request_vertex_desc(i) self.fw.write_short(70) # Vertex with color normal and uv opcode. self.fw.write_ushort(64) # Length of record - self.fw.write_ushort(0) # Color name index - self.fw.write_short(0x2000) # Flags set to no color + self.fw.write_ushort(0) # Color name index + self.fw.write_short(0x20000000) # Flags self.fw.write_double(desc.x) self.fw.write_double(desc.y) self.fw.write_double(desc.z) @@ -595,16 +1121,19 @@ class Database(Node): self.fw.write_float(desc.nz) self.fw.write_float(desc.u) self.fw.write_float(desc.v) - self.fw.pad(12) + self.fw.pad(4) + self.fw.write_uint(desc.cindex) + self.fw.pad(4) def write_tex_pal(self): if options.verbose >= 2: print 'Writing texture palette.' # Write record for texture palette - for i in xrange(self.GRR.texture_count()): + for i, img in enumerate(self.GRR.texture_lst): + filename = tex_files[img.name] self.fw.write_short(64) # Texture palette opcode. self.fw.write_short(216) # Length of record - self.fw.write_string(self.GRR.request_texture_filename(i), 200) # Filename + self.fw.write_string(filename, 200) # Filename self.fw.write_int(i) # Texture index self.fw.write_int(0) # X self.fw.write_int(0) # Y @@ -641,13 +1170,17 @@ class Database(Node): self.fw.write_short(32) # Color palette opcode. self.fw.write_short(4228) # Length of record self.fw.pad(128) - count = self.GRR.color_count() + try: + cpalette = self.scene.properties['FLT']['Color Palette'] + except: + cpalette = defaultp.pal + count = len(cpalette) for i in xrange(count): - col = self.GRR.request_max_color(i) - self.fw.write_uchar(255) # alpha - self.fw.write_uchar(col[2]) # b - self.fw.write_uchar(col[1]) # g - self.fw.write_uchar(col[0]) # r + color = struct.unpack('>BBBB',struct.pack('>I',cpalette[i])) + self.fw.write_uchar(color[3]) # alpha + self.fw.write_uchar(color[2]) # b + self.fw.write_uchar(color[1]) # g + self.fw.write_uchar(color[0]) # r self.fw.pad(max(4096-count*4, 0)) def write(self): @@ -657,66 +1190,428 @@ class Database(Node): self.write_mat_pal() self.write_col_pal() - # Wrap everything in a group if it has an object child. - if self.has_object_child: - self.header.fw.write_short(2) # Group opcode - self.header.fw.write_ushort(44) # Length of record - self.header.fw.write_string('g1', 8) # ASCII ID - self.header.fw.pad(32) - self.write_push() - - for child in self.children: - child.write() - + + if options.flattenmesh: + self.mnodes.reverse() + for mnode in self.mnodes: + mnode.write_faces() + else: + for child in self.children: + child.write() self.write_pop() + + def export_textures(self,texturepath): + for i in xrange(self.GRR.texture_count()): + texture = self.GRR.texture_lst[i] + + if options.copy_textures: + filename = os.path.normpath(os.path.join(options.texturespath, os.path.basename(self.GRR.request_texture_filename(i)))) + else: + filename = os.path.normpath(self.GRR.request_texture_filename(i)) + + tex_files[texture.name] = filename + def blender_export(self): + Node.blender_export(self) + self.export_textures(self) + return self.xrefnames def __init__(self, scene, fw): self.fw = fw + self.opcode = 1 + self.childtypes = [73,14,2,63] self.scene = scene - self.all_objects = list(scene.objects) + self.childhash = dict() + self.parenthash = dict() + self.child_objects = list() + self.mnodes = list() + self.xrefnames = list() + for i in self.scene.objects: + self.parenthash[i.name] = list() + self.childhash[i.name] = False + for i in self.scene.objects: + if i.parent: + self.childhash[i.parent.name] = True + self.parenthash[i.parent.name].append(i) + else: + self.child_objects.append(i) + self.GRR = GlobalResourceRepository() + Node.__init__(self, None, self, None,None) - Node.__init__(self, None, self, None, self.all_objects) +def write_attribute_files(): + for imgname in tex_files: + blentex = Blender.Image.Get(imgname) + exportdict = FLT_Records['Image'].copy() + + if blentex.properties.has_key('FLT'): + for key in exportdict.keys(): + if blentex.properties.has_key(key): + exportdict[key] = blentex.properties['FLT'][key] + + # ClampX/Y override + if blentex.clampX: + exportdict['11i!WrapU'] = 1 + if blentex.clampY: + exportdict['12i!WrapV'] = 1 + + exportdict['16i!Enviorment'] = 0 + + # File type + typecode = 0 + try: + typestring = os.path.splitext(blentex.getFilename())[1] + + if typestring == '.rgba': + typecode = 5 + elif typestring == '.rgb': + typecode = 4 + elif typestring == '.inta': + typecode = 3 + elif typestring == '.int': + typecode = 2 + except: + pass + + exportdict['7i!File Format'] = typecode -def fs_callback(filename): + fw = FltOut(tex_files[imgname] + '.attr') + size = blentex.getSize() + fw.write_int(size[0]) + fw.write_int(size[1]) + for key in records['Image']: + (type,length,propname) = records['Image'][key] + write_prop(fw,type,exportdict[propname],length) + fw.close_file() + +#globals used by the scene export function +exportlevel = None +xrefsdone = None + +def dbexport_internal(scene): + global exportlevel + global xrefsdone + global options + + if exportlevel == 0 or not options.externalspath: + fname = os.path.join(options.basepath,scene.name + '.flt') + else: + fname = os.path.join(options.externalspath,scene.name + '.flt') + + fw = FltOut(fname) + db = Database(scene,fw) + + if options.verbose >= 1: + print 'Pass 1: Exporting ', scene.name,'.flt from Blender.\n' + + xreflist = db.blender_export() + if options.verbose >= 1: + print 'Pass 2: Writing %s\n' % fname + db.write() + fw.close_file() + + if options.doxrefs: + for xname in xreflist: + try: + xrefscene = Blender.Scene.Get(xname) + except: + xrefscene = None + if xrefscene and xname not in xrefsdone: + xrefsdone.append(xname) + exportlevel+=1 + dbexport_internal(xrefscene) + exportlevel-=1 + return fname +#main database export function +def dbexport(): + global exportlevel + global xrefsdone + exportlevel = 0 + xrefsdone = list() + Blender.Window.WaitCursor(True) - - if Blender.sys.exists(filename): - r = Blender.Draw.PupMenu('Overwrite ' + filename + '?%t|Yes|No') - if r != 1: - if options.verbose >= 1: - print 'Export cancelled.' - return - time1 = Blender.sys.time() # Start timing - fw = FltOut(filename) - - db = Database(Blender.Scene.GetCurrent(), fw) - if options.verbose >= 1: - print 'Pass 1: Exporting from Blender.\n' + print '\nOpenFlight Exporter' + print 'Version:', __version__ + print 'Author: Greg MacDonald, Geoffrey Bantle' + print __url__[2] + print - db.blender_export() - - if options.verbose >= 1: - print 'Pass 2: Writing %s\n' % filename - - db.write() - - fw.close_file() - if options.verbose >= 1: + fname = dbexport_internal(Blender.Scene.GetCurrent()) + if options.verbose >=1: print 'Done in %.4f sec.\n' % (Blender.sys.time() - time1) - Blender.Window.WaitCursor(False) - -if options.verbose >= 1: - print '\nOpenFlight Exporter' - print 'Version:', __version__ - print 'Author: Greg MacDonald' - print __url__[2] - print -fname = Blender.sys.makename(ext=".flt") -Blender.Window.FileSelector(fs_callback, "Export OpenFlight v16.0", fname) + #optional: Copy textures + if options.copy_textures: + for imgname in tex_files: + #Check to see if texture exists in target directory + if not os.path.exists(tex_files[imgname]): + #Get original Blender file name + origpath = Blender.sys.expandpath(Blender.Image.Get(imgname).getFilename()) + #copy original to new + shutil.copyfile(origpath,tex_files[imgname]) + + #optional: Write attribute files + if options.write_attrib_files: + write_attribute_files() + + if options.xapp: + cmd= options.xappath + " " + fname + status = os.system(cmd) + + +#Begin UI code +FLTExport = None +FLTClose = None +FLTLabel = None + +FLTBaseLabel = None +FLTTextureLabel = None +FLTXRefLabel = None + +FLTBaseString = None +FLTTextureString = None +FLTXRefString = None + +FLTBasePath = None +FLTTexturePath = None +FLTXRefPath = None + +FLTShadeExport = None +FLTShadeDefault = None + +FLTCopyTex = None +FLTDoXRef = None +FLTGlobal = None + +FLTScale = None + +FLTXAPP = None +FLTXAPPath = None +FLTXAPPString = None +FLTXAPPLabel = None +FLTXAPPChooser = None + +FLTAttrib = None + +def setshadingangle(ID,val): + global options + options.shading_default = val +def setBpath(fname): + global options + options.basepath = os.path.dirname(fname) + #update xref and textures path too.... + if(os.path.exists(os.path.join(options.basepath,'externals'))): + options.externalspath = os.path.join(options.basepath,'externals') + if(os.path.exists(os.path.join(options.texturespath,'textures'))): + options.texturespath = os.path.join(options.basepath,'textures') +def setexportscale(ID,val): + global options + options.scale = val + +def setTpath(fname): + global options + options.texturespath = os.path.dirname(fname) +def setXpath(fname): + global options + options.externalspath = os.path.dirname(fname) +def setXApath(fname): + global options + options.xappath = fname + d = dict() + d['xappath'] = options.xappath + Blender.Registry.SetKey('flt_export', d, 1) +def event(evt, val): + x = 1 +def but_event(evt): + global options + + global FLTExport + global FLTClose + global FLTLabel + + global FLTBaseLabel + global FLTTextureLabel + global FLTXRefLabel + + global FLTBaseString + global FLTTextureString + global FLTXRefString + + global FLTBasePath + global FLTTexturePath + global FLTXRefPath + + global FLTShadeExport + global FLTShadeDefault + + global FLTCopyTex + global FLTDoXRef + global FLTGlobal + + global FLTScale + + + global FLTXAPP + global FLTXAPPath + global FLTXAPPString + global FLTXAPPLabel + global FLTXAPPChooser + + global FLTAttrib + + + + #choose base path for export + if evt == 4: + Blender.Window.FileSelector(setBpath, "DB Root", options.basepath) + + #choose XREF path + if evt == 6: + Blender.Window.FileSelector(setXpath,"DB Externals",options.externalspath) + + #choose texture path + if evt == 8: + Blender.Window.FileSelector(setTpath,"DB Textures",options.texturespath) + + #export shading toggle + if evt == 9: + options.export_shading = FLTShadeExport.val + #export Textures + if evt == 11: + options.copy_textures = FLTCopyTex.val + #export XRefs + if evt == 13: + options.doxrefs = FLTDoXRef.val + #export Transforms + if evt == 12: + options.export_transform = FLTGlobal.val + + if evt == 14: + options.xapp = FLTXAPP.val + if evt == 16: + Blender.Window.FileSelector(setXApath,"External Application",options.xappath) + if evt == 20: + options.write_attrib_files = FLTAttrib.val + + #Export DB + if evt == 1: + dbexport() + + #exit + if evt == 2: + Draw.Exit() + +from Blender.BGL import * +from Blender import Draw +def gui(): + + global options + + global FLTExport + global FLTClose + global FLTLabel + + global FLTBaseLabel + global FLTTextureLabel + global FLTXRefLabel + + global FLTBaseString + global FLTTextureString + global FLTXRefString + + global FLTBasePath + global FLTTexturePath + global FLTXRefPath + + global FLTShadeExport + global FLTShadeDefault + + global FLTCopyTex + global FLTDoXRef + global FLTGlobal + + global FLTScale + + global FLTXAPP + global FLTXAPPath + global FLTXAPPString + global FLTXAPPLabel + global FLTXAPPChooser + + global FLTAttrib + + glClearColor(0.880,0.890,0.730,1.0 ) + glClear(GL_COLOR_BUFFER_BIT) + + areas = Blender.Window.GetScreenInfo() + curarea = Blender.Window.GetAreaID() + curRect = None + + for area in areas: + if area['id'] == curarea: + curRect = area['vertices'] + break + + width = curRect[2] - curRect[0] + height = curRect[3] - curRect[1] + #draw from top to bottom.... + cx = 50 + #Draw Title Bar... + #glRasterPos2d(cx, curRect[3]-100) + #FLTLabel = Draw.Text("FLT Exporter V2.0",'large') + cy = height - 80 + + #base path + FLTBaseLabel = Draw.Label("Base Path:",cx,cy,100,20) + FLTBaseString = Draw.String("",3,cx+100,cy,300,20,options.basepath,255,"Folder to export to") + FLTBaseChooser = Draw.PushButton("...",4,cx+400,cy,20,20,"Choose Folder") + + cy = cy-40 + + #externals path + FLTXRefLabel = Draw.Label("XRefs:",cx,cy,100,20) + FLTXRefString = Draw.String("",5,cx+100,cy,300,20,options.externalspath,255,"Folder for external references") + FLTXRefChooser = Draw.PushButton("...",6,cx+400,cy,20,20,"Choose Folder") + cy = cy-40 + #Textures path + FLTTextureLabel = Draw.Label("Textures:",cx,cy,100,20) + FLTTextureString = Draw.String("",7,cx+100,cy,300,20,options.texturespath,255,"Folder for texture files") + FLTTextureChooser = Draw.PushButton("...",8,cx+400,cy,20,20,"Choose Folder") + cy=cy-40 + #External application path + FLTXAPPLabel = Draw.Label("XApp:",cx,cy,100,20) + FLTXAPPString = Draw.String("",15,cx+100,cy,300,20,options.xappath,255,"External application to launch when done") + FLTXAPPChooser = Draw.PushButton("...",16,cx+400, cy,20,20,"Choose Folder") + + cy = cy-60 + #Shading Options + FLTShadeExport = Draw.Toggle("Default Shading",9,cx,cy,100,20,options.export_shading,"Turn on export of custom shading") + FLTShadDefault = Draw.Number("",10,cx + 120,cy,100,20,options.shading_default,0.0,180.0,"Default shading angle for objects with no custom shading assigned",setshadingangle) + + cy = cy-40 + FLTScale = Draw.Number("Export Scale",14,cx,cy,220,20,options.scale,0.0,100.0,"Export scaling factor",setexportscale) + + cy = cy-40 + #misc Options + FLTCopyTex = Draw.Toggle("Copy Textures",11,cx,cy,220,20,options.copy_textures,"Copy textures to folder indicated above") + cy = cy-40 + FLTGlobal = Draw.Toggle("Export Transforms",12,cx,cy,220,20,options.export_transform,"If unchecked, Global coordinates are used (recommended)") + cy = cy-40 + FLTDoXRef = Draw.Toggle("Export XRefs", 13,cx,cy,220,20,options.doxrefs,"Export External references (only those below current scene!)") + cy = cy-40 + FLTXAPP = Draw.Toggle("Launch External App", 14, cx,cy,220,20,options.xapp,"Launch External Application on export") + cy = cy-40 + FLTAttrib = Draw.Toggle("Write Attribute Files", 20, cx, cy, 220,20,options.write_attrib_files, "Write Texture Attribute files") + #FLTXAPPATH = Draw.String("",15,cx,cy,300,20,options.xappath,255,"External application path") + + + #Draw export/close buttons + FLTExport = Draw.PushButton("Export",1,cx,20,100,20,"Export to FLT") + FLTClose = Draw.PushButton("Close", 2, cx+120,20,100,20,"Close window") + + +Draw.Register(gui,event,but_event) \ No newline at end of file diff --git a/release/scripts/flt_filewalker.py b/release/scripts/flt_filewalker.py index 442c9728e91..4a9b86c45d2 100644 --- a/release/scripts/flt_filewalker.py +++ b/release/scripts/flt_filewalker.py @@ -17,6 +17,11 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +__bpydoc__ ="""\ +File read/write module used by OpenFlight I/O and tool scripts. OpenFlight is a +registered trademark of MultiGen-Paradigm, Inc. +""" + import Blender from struct import * import re @@ -199,7 +204,9 @@ class FltOut: self.file.close() def __init__(self, filename): - self.file = open(filename, 'wb') + self.file = open(filename, 'wb') + self.filename = filename + class FileFinder: def add_file_to_search_path(self, filename): diff --git a/release/scripts/flt_import.py b/release/scripts/flt_import.py index ca0db650447..220fc9f355c 100644 --- a/release/scripts/flt_import.py +++ b/release/scripts/flt_import.py @@ -1,72 +1,26 @@ #!BPY """ Registration info for Blender menus: Name: 'OpenFlight (.flt)...' -Blender: 238 +Blender: 245 Group: 'Import' Tip: 'Import OpenFlight (.flt)' """ -__author__ = "Greg MacDonald, Campbell Barton" -__version__ = "1.2 10/20/05" +__author__ = "Greg MacDonald, Campbell Barton, Geoffrey Bantle" +__version__ = "2.0 11/21/07" __url__ = ("blender", "elysiun", "Author's homepage, http://sourceforge.net/projects/blight/") __bpydoc__ = """\ This script imports OpenFlight files into Blender. OpenFlight is a registered trademark of MultiGen-Paradigm, Inc. -Run from "File->Import" menu. +Feature overview and more availible at: +http://wiki.blender.org/index.php/Scripts/Manual/Import/openflight_flt -Options are available from Blender's "Scripts Config Editor," accessible through -the "Scripts->System" menu from the scripts window. - -All global_prefs are toggle switches that let the user choose what is imported. Most -are straight-forward, but one option could be a source of confusion. The -"Diffuse Color From Face" option when set pulls the diffuse color from the face -colors. Otherwise the diffuse color comes from the material. What may be -confusing is that this global_prefs only works if the "Diffuse Color" option is set. - -New Features:
-* Importer is 14 times faster.
-* External triangle module is no longer required, but make sure the importer -has a 3d View screen open while its running or triangulation won't work.
-* Should be able to import all versions of flight files. - -Features:
-* Heirarchy retained.
-* First texture imported.
-* Colors imported from face or material.
-* LOD seperated out into different layers.
-* Asks for location of unfound textures or external references.
-* Searches Blender's texture directory in the user preferences panel.
-* Triangles with more than 4 verts are triangulated if the Triangle python -module is installed.
-* Matrix transforms imported.
-* External references to whole files are imported. - -Things To Be Aware Of:
-* Each new color and face attribute creates a new material and there are only a maximum of 16 -materials per object.
-* For triangulated faces, normals must be recomputed outward manually by typing -CTRL+N in edit mode.
-* You can change global_prefs only after an initial import.
-* External references are imported as geometry and will be exported that way.
-* A work around for not using the Triangle python module is to simply to -triangulate in Creator before importing. This is only necessary if your -model contains 5 or more vertices.
-* You have to manually blend the material color with the texture color. - -What's Not Handled:
-* Special texture repeating modes.
-* Replications and instancing.
-* Comment and attribute fields.
-* Light points.
-* Animations.
-* External references to a node within a file.
-* Multitexturing.
-* Vetex colors.
+Note: This file is a grab-bag of old and new code. It needs some cleanup still. """ # flt_import.py is an OpenFlight importer for blender. -# Copyright (C) 2005 Greg MacDonald +# Copyright (C) 2005 Greg MacDonald, 2007 Blender Foundation # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -87,15 +41,33 @@ import os import BPyMesh import BPyImage import flt_filewalker +import flt_properties +reload(flt_properties) +from flt_properties import * + +#Globals. Should Clean these up and minimize their usage. + +typecodes = ['c','C','s','S','i','I','f','d','t'] +records = dict() + +FLTBaseLabel = None +FLTBaseString = None +FLTBaseChooser = None +FLTExport = None +FLTClose = None +FLTDoXRef = None +FLTScale = None +FLTShadeImport = None +FLTAttrib = None Vector= Blender.Mathutils.Vector +FLOAT_TOLERANCE = 0.01 -def col_to_gray(c): - return 0.3*c[0] + 0.59*c[1] + 0.11*c[2] - +FF = flt_filewalker.FileFinder() +current_layer = 0x01 global_prefs = dict() -global_prefs['verbose']= 1 +global_prefs['verbose']= 4 global_prefs['get_texture'] = True global_prefs['get_diffuse'] = True global_prefs['get_specular'] = False @@ -105,8 +77,41 @@ global_prefs['get_ambient'] = False global_prefs['get_shininess'] = True global_prefs['color_from_face'] = True global_prefs['fltfile']= '' +global_prefs['smoothshading'] = 1 +global_prefs['doxrefs'] = 1 +global_prefs['scale'] = 1.0 +global_prefs['attrib'] = 0 msg_once = False +throw_back_opcodes = [2, 73, 4, 11, 96, 14, 91, 98, 63,111] # Opcodes that indicate its time to return control to parent. +do_not_report_opcodes = [76, 78, 79, 80, 81, 82, 94, 83, 33, 112, 100, 101, 102, 97, 31, 103, 104, 117, 118, 120, 121, 124, 125] + +#Process FLT record definitions +for record in FLT_Records: + props = dict() + for prop in FLT_Records[record]: + position = '' + slice = 0 + (format,name) = prop.split('!') + for i in format: + if i not in typecodes: + position = position + i + slice = slice + 1 + else: + break + type = format[slice:] + length = type[1:] + if len(length) == 0: + length = 1 + else: + type = type[0] + length = int(length) + + props[int(position)] = (type,length,prop) + records[record] = props + +def col_to_gray(c): + return 0.3*c[0] + 0.59*c[1] + 0.11*c[2] class MaterialDesc: # Was going to use int(f*1000.0) instead of round(f,3), but for some reason # round produces better results, as in less dups. @@ -185,16 +190,14 @@ class VertexDesc: self.y = 0.0 self.z = 0.0 - ''' # IGNORE_NORMALS + self.nx = 0.0 - self.ny = 1.0 + self.ny = 0.0 self.nz = 0.0 - ''' + self.uv= Vector(0,0) - self.r = 1.0 - self.g = 1.0 - self.b = 1.0 - self.a = 1.0 + self.cindex = 127 #default/lowest + self.cnorm = False class LightPointAppDesc: def make_key(self): @@ -222,7 +225,7 @@ class LightPointAppDesc: self.props.update({'LOD scale': 0.0}) class GlobalResourceRepository: - def request_lightpoint_app(self, desc): + def request_lightpoint_app(self, desc, scene): match = self.light_point_app.get(desc.make_key()) if match: @@ -231,7 +234,7 @@ class GlobalResourceRepository: # Create empty and fill with properties. name = desc.props['type'] + ': ' + desc.props['id'] object = Blender.Object.New('Empty', name) - scene.link(object) + scene.objects.link(object) object.Layers= current_layer object.sel= 1 @@ -306,6 +309,9 @@ class GlobalResourceRepository: return tex def __init__(self): + + #list of scenes xrefs belong to. + self.xrefs = dict() # material self.mat_dict = dict() mat_lst = Blender.Material.Get() @@ -341,108 +347,6 @@ class GlobalResourceRepository: # light point self.light_point_app = dict() -# Globals -GRR = GlobalResourceRepository() -FF = flt_filewalker.FileFinder() -scene = Blender.Scene.GetCurrent() # just hope they dont chenge scenes once the file selector pops up. -current_layer = 0x01 - - -# Opcodes that indicate its time to return control to parent. -throw_back_opcodes = [2, 73, 4, 11, 96, 14, 91, 98, 63] -do_not_report_opcodes = [76, 78, 79, 80, 81, 82, 94, 83, 33, 112, 100, 101, 102, 97, 31, 103, 104, 117, 118, 120, 121, 124, 125] - -opcode_name = { 0: 'db', - 1: 'head', - 2: 'grp', - 4: 'obj', - 5: 'face', - 10: 'push', - 11: 'pop', - 14: 'dof', - 19: 'push sub', - 20: 'pop sub', - 21: 'push ext', - 22: 'pop ext', - 23: 'cont', - 31: 'comment', - 32: 'color pal', - 33: 'long id', - 49: 'matrix', - 50: 'vector', - 52: 'multi-tex', - 53: 'uv lst', - 55: 'bsp', - 60: 'rep', - 61: 'inst ref', - 62: 'inst def', - 63: 'ext ref', - 64: 'tex pal', - 67: 'vert pal', - 68: 'vert w col', - 69: 'vert w col & norm', - 70: 'vert w col, norm & uv', - 71: 'vert w col & uv', - 72: 'vert lst', - 73: 'lod', - 74: 'bndin box', - 76: 'rot edge', - 78: 'trans', - 79: 'scl', - 80: 'rot pnt', - 81: 'rot and/or scale pnt', - 82: 'put', - 83: 'eyepoint & trackplane pal', - 84: 'mesh', - 85: 'local vert pool', - 86: 'mesh prim', - 87: 'road seg', - 88: 'road zone', - 89: 'morph vert lst', - 90: 'link pal', - 91: 'snd', - 92: 'rd path', - 93: 'snd pal', - 94: 'gen matrix', - 95: 'txt', - 96: 'sw', - 97: 'line styl pal', - 98: 'clip reg', - 100: 'ext', - 101: 'light src', - 102: 'light src pal', - 103: 'reserved', - 104: 'reserved', - 105: 'bndin sph', - 106: 'bndin cyl', - 107: 'bndin hull', - 108: 'bndin vol cntr', - 109: 'bndin vol orient', - 110: 'rsrvd', - 111: 'light pnt', - 112: 'tex map pal', - 113: 'mat pal', - 114: 'name tab', - 115: 'cat', - 116: 'cat dat', - 117: 'rsrvd', - 118: 'rsrvd', - 119: 'bounding hist', - 120: 'rsrvd', - 121: 'rsrvd', - 122: 'push attrib', - 123: 'pop attrib', - 124: 'rsrvd', - 125: 'rsrvd', - 126: 'curv', - 127: 'road const', - 128: 'light pnt appear pal', - 129: 'light pnt anim pal', - 130: 'indexed lp', - 131: 'lp sys', - 132: 'indx str', - 133: 'shdr pal'} - class Handler: def in_throw_back_lst(self, opcode): return opcode in self.throw_back_lst @@ -487,11 +391,11 @@ class Node: print '-', self.props['comment'], print - + for child in self.children: child.blender_import() - - # Import comment. + +# Import comment. # if self.props['comment'] != '': # name = 'COMMENT: ' + self.props['id'] # t = Blender.Text.New(name) @@ -568,8 +472,8 @@ class Node: else: if global_prefs['verbose'] >= 3: print p + ' ignored' - elif global_prefs['verbose'] >= 1 and not opcode in do_not_report_opcodes and opcode in opcode_name: - print opcode_name[opcode], 'not handled' + elif global_prefs['verbose'] >= 1 and not opcode in do_not_report_opcodes and opcode in opcode_name: + print 'not handled' def get_level(self): return self.level @@ -581,7 +485,19 @@ class Node: def parse_comment(self): self.props['comment'] = self.header.fw.read_string(self.header.fw.get_length()-4) return True - + + def parse_record(self): + self.props['type'] = self.opcode + props = records[self.opcode] + propkeys = props.keys() + propkeys.sort() + for position in propkeys: + (type,length,name) = props[position] + self.props[name] = read_prop(self.header.fw,type,length) + try: #remove me! + self.props['id'] = self.props['3t8!id'] + except: + pass def __init__(self, parent, header): self.root_handler = Handler() self.child_handler = Handler() @@ -647,20 +563,16 @@ class VertexPalette(Node): return v def parse_vertex_post_common(self, v): - if not v.flags & 0x2000: # 0x2000 = no color - if v.flags & 0x1000: # 0x1000 = packed color - v.a = self.header.fw.read_uchar() - v.b = self.header.fw.read_uchar() - v.g = self.header.fw.read_uchar() - v.r = self.header.fw.read_uchar() - else: - self.header.fw.read_ahead(4) - - color_index = self.header.fw.read_uint() - v.r, v.g, v.b, v.a= self.header.get_color(color_index) - + #if not v.flags & 0x2000: # 0x2000 = no color + #if v.flags & 0x1000: # 0x1000 = packed color + # v.a = self.header.fw.read_uchar() + # v.b = self.header.fw.read_uchar() + # v.g = self.header.fw.read_uchar() + # v.r = self.header.fw.read_uchar() + #else: + self.header.fw.read_ahead(4) #skip packed color + v.cindex = self.header.fw.read_uint() self.vert_desc_lst.append(v) - return True def parse_vertex_c(self): @@ -672,16 +584,10 @@ class VertexPalette(Node): def parse_vertex_cn(self): v = self.parse_vertex_common() - - ''' + v.cnorm = True v.nx = self.header.fw.read_float() v.ny = self.header.fw.read_float() v.nz = self.header.fw.read_float() - ''' - # Just to advance - self.header.fw.read_float() - self.header.fw.read_float() - self.header.fw.read_float() self.parse_vertex_post_common(v) @@ -698,15 +604,10 @@ class VertexPalette(Node): def parse_vertex_cnuv(self): v = self.parse_vertex_common() - ''' + v.cnorm = True v.nx = self.header.fw.read_float() v.ny = self.header.fw.read_float() v.nz = self.header.fw.read_float() - ''' - # Just to advance - self.header.fw.read_float() - self.header.fw.read_float() - self.header.fw.read_float() v.uv[:] = self.header.fw.read_float(), self.header.fw.read_float() @@ -721,89 +622,370 @@ class InterNode(Node): def __init__(self): self.object = None self.mesh = None - self.isMesh = False + self.hasMesh = False self.faceLs= [] self.matrix = None - - def blender_import_my_faces(self): + self.vis = True + self.hasmtex = False + self.uvlayers = dict() + self.blayernames = dict() + self.subfacelevel = 0 + mask = 2147483648 + for i in xrange(7): + self.uvlayers[mask] = False + mask = mask / 2 + + + def blender_import_my_faces(self): + # Add the verts onto the mesh - mesh = self.mesh blender_verts= self.header.vert_pal.blender_verts vert_desc_lst= self.header.vert_pal.vert_desc_lst - vert_list= [ i for flt_face in self.faceLs for i in flt_face.indices] - - mesh.verts.extend([blender_verts[i] for i in vert_list]) - + vert_list= [ i for flt_face in self.faceLs for i in flt_face.indices] #splitting faces apart. Is this a good thing? + face_edges= [] + face_verts= [] + self.mesh.verts.extend([blender_verts[i] for i in vert_list]) new_faces= [] new_faces_props= [] ngon= BPyMesh.ngon vert_index= 1 + + #add vertex color layer for baked face colors. + self.mesh.addColorLayer("FLT_Fcol") + self.mesh.activeColorLayer = "FLT_Fcol" + + FLT_OrigIndex = 0 for flt_face in self.faceLs: - material_index= flt_face.blen_mat_idx - image= flt_face.blen_image - + if flt_face.tex_index != -1: + try: + image= self.header.tex_pal[flt_face.tex_index][1] + except KeyError: + image= None + else: + image= None face_len= len(flt_face.indices) + #create dummy uvert dicts + if len(flt_face.uverts) == 0: + for i in xrange(face_len): + flt_face.uverts.append(dict()) + #May need to patch up MTex info + if self.hasmtex: + #For every layer in mesh, there should be corresponding layer in the face + for mask in self.uvlayers.keys(): + if self.uvlayers[mask]: + if not flt_face.uvlayers.has_key(mask): #Does the face have this layer? + #Create Layer info for this face + flt_face.uvlayers[mask] = dict() + flt_face.uvlayers[mask]['texture index'] = -1 + flt_face.uvlayers[mask]['texture enviorment'] = 3 + flt_face.uvlayers[mask]['texture mapping'] = 0 + flt_face.uvlayers[mask]['texture data'] = 0 + + #now go through and create dummy uvs for this layer + for uvert in flt_face.uverts: + uv = Vector(0.0,0.0) + uvert[mask] = uv + # Get the indicies in reference to the mesh. - uvs= [vert_desc_lst[j].uv for j in flt_face.indices] - if face_len <=4: # tri or quad + if face_len == 1: + pass + elif face_len == 2: + face_edges.append((vert_index, vert_index+1)) + elif flt_face.props['draw type'] == 2 or flt_face.props['draw type'] == 3: + i = 0 + while i < (face_len-1): + face_edges.append((vert_index + i, vert_index + i + 1)) + i = i + 1 + if flt_face.props['draw type'] == 2: + face_edges.append((vert_index + i,vert_index)) + elif face_len == 3 or face_len == 4: # tri or quad + #if face_len == 1: + # pass + #if face_len == 2: + # face_edges.append((vert_index, vert_index+1)) new_faces.append( [i+vert_index for i in xrange(face_len)] ) - new_faces_props.append((material_index, image, uvs)) + new_faces_props.append((None, image, uvs, flt_face.uverts, flt_face.uvlayers, flt_face.color_index, flt_face.props,FLT_OrigIndex,0, flt_face.subfacelevel)) else: # fgon mesh_face_indicies = [i+vert_index for i in xrange(face_len)] - tri_ngons= ngon(mesh, mesh_face_indicies) + tri_ngons= ngon(self.mesh, mesh_face_indicies) new_faces.extend([ [mesh_face_indicies[t] for t in tri] for tri in tri_ngons]) - new_faces_props.extend( [ (material_index, image, (uvs[tri[0]], uvs[tri[1]], uvs[tri[2]]) ) for tri in tri_ngons ] ) + new_faces_props.extend( [ (None, image, (uvs[tri[0]], uvs[tri[1]], uvs[tri[2]]), [flt_face.uverts[tri[0]], flt_face.uverts[tri[1]], flt_face.uverts[tri[2]]], flt_face.uvlayers, flt_face.color_index, flt_face.props,FLT_OrigIndex,1, flt_face.subfacelevel) for tri in tri_ngons ]) vert_index+= face_len + FLT_OrigIndex+=1 - mesh.faces.extend(new_faces) + self.mesh.faces.extend(new_faces) + self.mesh.edges.extend(face_edges) - try: mesh.faceUV= True - except: pass + #add in the FLT_ORIGINDEX layer + if len(self.mesh.faces): + try: self.mesh.faceUV= True + except: pass - for i, f in enumerate(mesh.faces): - f.mat, f.image, f.uv= new_faces_props[i] - + if self.mesh.faceUV == True: + self.mesh.renameUVLayer(self.mesh.activeUVLayer, 'Layer0') + + #create name layer for faces + self.mesh.faces.addPropertyLayer("FLT_ID",Blender.Mesh.PropertyTypes["STRING"]) + #create layer for face color indices + self.mesh.faces.addPropertyLayer("FLT_COL",Blender.Mesh.PropertyTypes["INT"]) + #create index layer for faces. This is needed by both FGONs and subfaces + self.mesh.faces.addPropertyLayer("FLT_ORIGINDEX",Blender.Mesh.PropertyTypes["INT"]) + #create temporary FGON flag layer. Delete after remove doubles + self.mesh.faces.addPropertyLayer("FLT_FGON",Blender.Mesh.PropertyTypes["INT"]) + self.mesh.faces.addPropertyLayer("FLT_SFLEVEL", Blender.Mesh.PropertyTypes["INT"]) + + for i, f in enumerate(self.mesh.faces): + f.transp |= Blender.Mesh.FaceTranspModes["ALPHA"] #fix this! + f.mode |= Blender.Mesh.FaceModes["LIGHT"] + props = new_faces_props[i] + #f.mat = props[0] + f.image = props[1] + f.uv = props[2] + #set vertex colors + color = self.header.get_color(props[5]) + if not color: + color = [255,255,255,255] + for mcol in f.col: + mcol.a = color[3] + mcol.r = color[0] + mcol.g = color[1] + mcol.b = color[2] + + f.setProperty("FLT_SFLEVEL", props[9]) + f.setProperty("FLT_ORIGINDEX",i) + f.setProperty("FLT_ID",props[6]['id']) + #if props[5] > 13199: + # print "Warning, invalid color index read in! Using default!" + # f.setProperty("FLT_COL",127) + #else: + if(1): #uh oh.... + value = struct.unpack('>i',struct.pack('>I',props[5]))[0] + f.setProperty("FLT_COL",value) + + #if props[8]: + # f.setProperty("FLT_FGON",1) + #else: + # f.setProperty("FLT_FGON",0) + + + #Create multitex layers, if present. + actuvlayer = self.mesh.activeUVLayer + if(self.hasmtex): + #For every multi-tex layer, we have to add a new UV layer to the mesh + for i,mask in enumerate(reversed(sorted(self.uvlayers))): + if self.uvlayers[mask]: + self.blayernames[mask] = "Layer" + str(i+1) + self.mesh.addUVLayer(self.blayernames[mask]) + + #Cycle through availible multi-tex layers and add face UVS + for mask in self.uvlayers: + if self.uvlayers[mask]: + self.mesh.activeUVLayer = self.blayernames[mask] + for j, f in enumerate(self.mesh.faces): + f.transp |= Blender.Mesh.FaceTranspModes["ALPHA"] + f.mode |= Blender.Mesh.FaceModes["LIGHT"] + props = new_faces_props[j] + uvlayers = props[4] + if uvlayers.has_key(mask): #redundant + uverts = props[3] + for k, uv in enumerate(f.uv): + uv[0] = uverts[k][mask][0] + uv[1] = uverts[k][mask][1] + + uvlayer = uvlayers[mask] + tex_index = uvlayer['texture index'] + if tex_index != -1: + try: + f.image = self.header.tex_pal[tex_index][1] + except KeyError: + f.image = None + + if global_prefs['smoothshading'] == True and len(self.mesh.faces): + #We need to store per-face vertex normals in the faces as UV layers and delete them later. + self.mesh.addUVLayer("FLTNorm1") + self.mesh.addUVLayer("FLTNorm2") + self.mesh.activeUVLayer = "FLTNorm1" + for f in self.mesh.faces: + f.smooth = 1 + #grab the X and Y components of normal and store them in UV + for i, uv in enumerate(f.uv): + vert = f.v[i].index + vert_desc = vert_desc_lst[vert_list[vert-1]] + if vert_desc.cnorm: + uv[0] = vert_desc.nx + uv[1] = vert_desc.ny + else: + uv[0] = 0.0 + uv[1] = 0.0 + + #Now go through and populate the second UV Layer with the z component + self.mesh.activeUVLayer = "FLTNorm2" + for f in self.mesh.faces: + for i, uv in enumerate(f.uv): + vert = f.v[i].index + vert_desc = vert_desc_lst[vert_list[vert-1]] + if vert_desc.cnorm: + uv[0] = vert_desc.nz + uv[1] = 0.0 + else: + uv[0] = 0.0 + uv[1] = 0.0 + + + + #Finally, go through, remove dummy vertex, remove doubles and add edgesplit modifier. + Blender.Mesh.Mode(Blender.Mesh.SelectModes['VERTEX']) + self.mesh.verts.delete(0) # remove the dummy vert + self.mesh.sel= 1 + self.header.scene.update(1) #slow! + self.mesh.remDoubles(0.0001) + + edgeHash = dict() + + for edge in self.mesh.edges: + edgeHash[edge.key] = edge.index + + + if global_prefs['smoothshading'] == True and len(self.mesh.faces): + + #rip out the custom vertex normals from the mesh and place them in a face aligned list. Easier to compare this way. + facenorms = [] + self.mesh.activeUVLayer = "FLTNorm1" + for face in self.mesh.faces: + facenorm = [] + for uv in face.uv: + facenorm.append(Vector(uv[0],uv[1],0.0)) + facenorms.append(facenorm) + self.mesh.activeUVLayer = "FLTNorm2" + for i, face in enumerate(self.mesh.faces): + facenorm = facenorms[i] + for j, uv in enumerate(face.uv): + facenorm[j][2] = uv[0] + self.mesh.removeUVLayer("FLTNorm1") + self.mesh.removeUVLayer("FLTNorm2") + + #find hard edges + #store edge data for lookup by faces + #edgeHash = dict() + #for edge in self.mesh.edges: + # edgeHash[edge.key] = edge.index + + edgeNormHash = dict() + #make sure to align the edgenormals to key value! + for i, face in enumerate(self.mesh.faces): + + facenorm = facenorms[i] + faceEdges = [] + faceEdges.append((face.v[0].index,face.v[1].index,facenorm[0],facenorm[1],face.edge_keys[0])) + faceEdges.append((face.v[1].index,face.v[2].index,facenorm[1],facenorm[2],face.edge_keys[1])) + if len(face.v) == 3: + faceEdges.append((face.v[2].index,face.v[0].index,facenorm[2],facenorm[0],face.edge_keys[2])) + elif len(face.v) == 4: + faceEdges.append((face.v[2].index,face.v[3].index,facenorm[2],facenorm[3],face.edge_keys[2])) + faceEdges.append((face.v[3].index,face.v[0].index,facenorm[3],facenorm[0],face.edge_keys[3])) + + #check to see if edgeNormal has been placed in the edgeNormHash yet + #this is a redundant test, and should be optimized to not be called as often as it is. + for j, faceEdge in enumerate(faceEdges): + #the value we are looking for is (faceEdge[2],faceEdge[3]) + hashvalue = (faceEdge[2],faceEdge[3]) + if (faceEdge[0],faceEdge[1]) != faceEdge[4]: + hashvalue = (hashvalue[1],hashvalue[0]) + assert (faceEdge[1],faceEdge[0]) == faceEdge[4] + if edgeNormHash.has_key(faceEdge[4]): + #compare value in the hash, if different, mark as sharp + edgeNorm = edgeNormHash[faceEdge[4]] + if\ + abs(hashvalue[0][0] - edgeNorm[0][0]) > FLOAT_TOLERANCE or\ + abs(hashvalue[0][1] - edgeNorm[0][1]) > FLOAT_TOLERANCE or\ + abs(hashvalue[0][2] - edgeNorm[0][2]) > FLOAT_TOLERANCE or\ + abs(hashvalue[1][0] - edgeNorm[1][0]) > FLOAT_TOLERANCE or\ + abs(hashvalue[1][1] - edgeNorm[1][1]) > FLOAT_TOLERANCE or\ + abs(hashvalue[1][2] - edgeNorm[1][2]) > FLOAT_TOLERANCE: + edge = self.mesh.edges[edgeHash[faceEdge[4]]] + edge.flag |= Blender.Mesh.EdgeFlags.SHARP + + else: + edgeNormHash[faceEdge[4]] = hashvalue + + #add in edgesplit modifier + mod = self.object.modifiers.append(Blender.Modifier.Types.EDGESPLIT) + mod[Blender.Modifier.Settings.EDGESPLIT_FROM_SHARP] = True + mod[Blender.Modifier.Settings.EDGESPLIT_FROM_ANGLE] = False + + if(actuvlayer): + self.mesh.activeUVLayer = actuvlayer + def blender_import(self): -# name = self.props['type'] + ': ' + self.props['id'] + if self.vis and self.parent: + self.vis = self.parent.vis name = self.props['id'] - if self.isMesh: - self.object = Blender.Object.New('Mesh', name) - #self.mesh = self.object.getData() + + if self.hasMesh: self.mesh = Blender.Mesh.New() - self.mesh.verts.extend( Vector() ) # DUMMYVERT - self.object.link(self.mesh) + self.mesh.name = 'FLT_FaceList' + self.mesh.fakeUser = True + self.mesh.verts.extend( Vector()) #DUMMYVERT + self.object = self.header.scene.objects.new(self.mesh) else: - self.object = Blender.Object.New('Empty', name) + self.object = self.header.scene.objects.new('Empty') - if self.parent: - self.parent.object.makeParent([self.object]) + self.object.name = name + self.header.group.objects.link(self.object) - scene.link(self.object) - self.object.Layer = current_layer - self.object.sel = 1 + #id props import + self.object.properties['FLT'] = dict() + for key in self.props: + try: + self.object.properties['FLT'][key] = self.props[key] + except: #horrible... + pass - Node.blender_import(self) # Attach faces to self.faceLs + if self.parent and self.parent.object and (self.header.scene == self.parent.header.scene): + self.parent.object.makeParent([self.object]) + + if self.vis == False: + self.object.restrictDisplay = True + self.object.restrictRender = True - if self.isMesh: - # Add all my faces into the mesh at once - self.blender_import_my_faces() + else: #check for LOD children and set the proper flags + lodlist = list() + for child in self.children: + if child.props.has_key('type') and child.props['type'] == 73: + lodlist.append(child) + def LODmin(a,b): + if a.props['5d!switch in'] < b.props['5d!switch in']: + return a + return b + + min= None + if len(lodlist) > 1: + for lod in lodlist: + lod.vis = False + min = lodlist[0] + for i in xrange(len(lodlist)): + min= LODmin(min,lodlist[i]) + min.vis = True + if self.matrix: self.object.setMatrix(self.matrix) + + Node.blender_import(self) # Attach faces to self.faceLs - # Attach properties - #for name, value in self.props.items(): - # self.object.addProperty(name, value) - + if self.hasMesh: + # Add all my faces into the mesh at once + self.blender_import_my_faces() + def parse_face(self): - child = Face(self) + child = Face(self, self.subfacelevel) child.parse() return True @@ -838,6 +1020,11 @@ class InterNode(Node): child.parse() return True + def parse_dof(self): + child = DOF(self) + child.parse() + return True + def parse_indexed_light_point(self): child = IndexedLightPoint(self) child.parse() @@ -857,32 +1044,42 @@ class InterNode(Node): m[i].append(f) self.matrix = Blender.Mathutils.Matrix(m[0], m[1], m[2], m[3]) -EDGE_FGON= Blender.Mesh.EdgeFlags['FGON'] -FACE_TEX= Blender.Mesh.FaceModes['TEX'] + def parse_subpush(self): + self.parse_push() + self.subfacelevel+= 1 + return True + def parse_subpop(self): + self.parse_pop() + self.subfacelevel -= 1 + return True + + class Face(Node): - def __init__(self, parent): + def __init__(self, parent,subfacelevel): Node.__init__(self, parent, parent.header) self.root_handler.set_handler({31: self.parse_comment, - 10: self.parse_push}) + 10: self.parse_push, + 52: self.parse_multitex}) self.root_handler.set_throw_back_lst(throw_back_opcodes) self.child_handler.set_handler({72: self.parse_vertex_list, 10: self.parse_push, - 11: self.parse_pop}) + 11: self.parse_pop, + 53: self.parse_uvlist}) if parent: - parent.isMesh = True + parent.hasMesh = True - self.indices = list() # face verts here + self.subfacelevel = subfacelevel + self.indices = list() # face verts here + self.uvlayers = dict() # MultiTexture layers keyed to layer bitmask. + self.uverts = list() # Vertex aligned list of dictionaries keyed to layer bitmask. + self.uvmask = 0 # Bitfield read from MTex record self.comment = '' - self.props = dict.fromkeys(['ir color', 'priority', - 'draw type', 'texture white', 'template billboard', - 'smc', 'fid', 'ir material', 'lod generation control', - 'flags', 'light mode']) - - self.header.fw.read_ahead(8) # face id + self.props = dict() + self.props['id'] = self.header.fw.read_string(8) # Load face. self.props['ir color'] = self.header.fw.read_int() self.props['priority'] = self.header.fw.read_short() @@ -919,186 +1116,14 @@ class Face(Node): self.alt_color_index = self.header.fw.read_uint() #self.header.fw.read_ahead(2) #self.shader_index = self.header.fw.read_short() - - - """ - def blender_import_face(self, material_index, image): - - - mesh = self.parent.mesh - face_len= len(self.indices) - - mesh_vert_len_orig= len(mesh.verts) - mesh.verts.extend([ self.header.vert_pal.blender_verts[i] for i in self.indices]) - - # Exception for an edge - if face_len==2: - mesh.edges.extend((mesh.verts[-1], mesh.verts[-2])) - return - - - mesh_face_indicies = range(mesh_vert_len_orig, mesh_vert_len_orig+face_len) - - #print mesh_face_indicies , 'mesh_face_indicies ' - - # First we need to triangulate NGONS - if face_len>4: - tri_indicies = [[i+mesh_vert_len_orig for i in t] for t in BPyMesh.ngon(mesh, mesh_face_indicies) ] # use range because the verts are in order. - else: - tri_indicies= [mesh_face_indicies] # can be a quad but thats ok - - # Extend face or ngon - - mesh.faces.extend(tri_indicies) - #print mesh.faces, 'mesh.faces' - mesh.faceUV= True - - # Now set UVs - for i in xrange(len(mesh.faces)-len(tri_indicies), len(mesh.faces)): - f= mesh.faces[i] - f_v= f.v - for j, uv in enumerate(f.uv): - vertex_index_flt= self.indices[f_v[j].index - mesh_vert_len_orig] - - vert_desc = self.header.vert_pal.vert_desc_lst[vertex_index_flt] - uv.x, uv.y= vert_desc.u, vert_desc.v - - # Only a bug in 2.42, fixed in cvs - for c in f.col: - c.r=c.g=c.b= 255 - - f.mat = material_index - if image: - f.image = image - else: - f.mode &= ~FACE_TEX - - # FGon - - if face_len>4: - # Add edges we know are not fgon - end_index= len(mesh.verts) - start_index= end_index - len(self.indices) - edge_dict= dict([ ((i, i+1), None) for i in xrange(start_index, end_index-1)]) - edge_dict[(start_index, end_index)]= None # wish this was a set - - fgon_edges= {} - for tri in tri_indicies: - for i in (0,1,2): - i1= tri[i] - i2= tri[i-1] - - # Sort - if i1>i2: - i1,i2= i2,i1 - - if not edge_dict.has_key( (i1,i2) ): # if this works its an edge vert - fgon_edges[i1,i2]= None - - - # Now set fgon flags - for ed in mesh.edges: - i1= ed.v1.index - i2= ed.v2.index - if i1>i2: - i1,i2= i2,i1 - - if fgon_edges.has_key( (i1,i2) ): - # This is an edge tagged for fgonning? - fgon_edges[i1, i2] - ed.flag |= EDGE_FGON - del fgon_edges[i1, i2] # make later searches faster? - - if not fgon_edges: - break - """ - + def parse_comment(self): self.comment = self.header.fw.read_string(self.header.fw.get_length()-4) return True - # returns a tuple (material, image) where material is the blender material and - # image is the blender image or None. - def create_blender_material(self): - # Create face material. - mat_desc = MaterialDesc() - - if self.mat_index != -1: - if not self.mat_index in self.header.mat_desc_pal: - if global_prefs['verbose'] >= 1: - #print 'Warning: Material index', self.mat_index, 'not in material palette.' - pass - else: - mat_pal_desc = self.header.mat_desc_pal[self.mat_index] - mat_desc.alpha = mat_pal_desc.alpha * self.alpha # combine face and mat alphas - mat_desc.ambient = mat_pal_desc.ambient - mat_desc.diffuse = mat_pal_desc.diffuse - mat_desc.specular = mat_pal_desc.specular - mat_desc.emissive = mat_pal_desc.emissive - mat_desc.shininess = mat_pal_desc.shininess - else: - # if no material get alpha from just face. - mat_desc.alpha = self.alpha - - # Color. - if global_prefs['color_from_face']: - color = None - if not self.props['flags'] & 0x40000000: - if self.props['flags'] & 0x10000000: # packed color - color = self.packed_color - else: - color = self.header.get_color(self.color_index) - - if color: - r = float(color[0])/255.0 - g = float(color[1])/255.0 - b = float(color[2])/255.0 - mat_desc.diffuse = [r, g, b] - - # Texture - image = None - if self.tex_index != -1 and self.tex_index in self.header.bl_tex_pal: - mat_desc.tex0 = self.header.bl_tex_pal[self.tex_index] - if mat_desc.tex0: - mat_desc.name = FF.strip_path(self.header.tex_pal[self.tex_index]) - image = mat_desc.tex0.image - - # OpenFlight Face Attributes - mat_desc.face_props = self.props - - # Get material. - mat = GRR.request_mat(mat_desc) - - # Add material to mesh. - mesh = self.parent.mesh - - # Return where it is in the mesh for faces. - mesh_materials= mesh.materials - - material_index= -1 - for i,m in enumerate(mesh_materials): - if m.name==mat.name: - material_index= i - break - - if material_index==-1: - material_index= len(mesh_materials) - if material_index==16: - material_index= 15 - if global_prefs['verbose'] >= 1: - print 'Warning: Too many materials per mesh object. Only a maximum of 16 ' + \ - 'allowed. Using 16th material instead.' - - else: - mesh_materials.append(mat) - mesh.materials= mesh_materials - - return (material_index, image) - - def blender_import(self): vert_count = len(self.indices) - if vert_count < 3: + if vert_count < 1: if global_prefs['verbose'] >= 2: print 'Warning: Ignoring face with no vertices.' return @@ -1106,18 +1131,21 @@ class Face(Node): # Assign material and image self.parent.faceLs.append(self) - self.blen_mat_idx, self.blen_image= self.create_blender_material() - - - + #need to store comment in mesh prop layer! # Store comment info in parent. - if self.comment != '': - if self.parent.props['comment'] != '': - self.parent.props['comment'] += '\n\nFrom Face:\n' + self.comment - else: - self.parent.props['comment'] = self.comment + #if self.comment != '': + # if self.parent.props['comment'] != '': + # self.parent.props['comment'] += '\n\nFrom Face:\n' + self.comment + # else: + # self.parent.props['comment'] = self.comment + if self.uvlayers: + #Make sure that the mesh knows about the layers that this face uses + self.parent.hasmtex = True + for mask in self.uvlayers.keys(): + self.parent.uvlayers[mask] = True + def parse_vertex_list(self): length = self.header.fw.get_length() fw = self.header.fw @@ -1138,8 +1166,49 @@ class Face(Node): ' to vertex index.' % byte_offset ''' return True - - + + def parse_multitex(self): + #Parse MultiTex Record. + length = self.header.fw.get_length() + fw = self.header.fw + #num layers == (length - 8) / 4 + uvmask = fw.read_uint() + mask = 2147483648 + for i in xrange(7): + if mask & uvmask: + uvlayer = dict() + self.uvlayers[mask] = uvlayer + mask = mask / 2 + + #read in record for each individual layer. + for key in reversed(sorted(self.uvlayers)): + uvlayer = self.uvlayers[key] + uvlayer['texture index'] = fw.read_ushort() + uvlayer['texture enviorment'] = fw.read_ushort() + uvlayer['texture mapping'] = fw.read_ushort() + uvlayer['texture data'] = fw.read_ushort() + + self.uvmask = uvmask + + def parse_uvlist(self): + #for each uvlayer, add uv vertices + length = self.header.fw.get_length() + fw = self.header.fw + uvmask = fw.read_uint() + if uvmask != self.uvmask: #This should never happen! + fw.read_ahead(self.length - 4) #potentially unnessecary? + else: + #need to store in uvverts dictionary for each vertex. + totverts = len(self.indices) + for i in xrange(totverts): + uvert = dict() + for key in reversed(sorted(self.uvlayers)): + uv = Vector(0.0,0.0) + uv[0] = fw.read_float() + uv[1] = fw.read_float() + uvert[key] = uv + self.uverts.append(uvert) + class Object(InterNode): def __init__(self, parent): Node.__init__(self, parent, parent.header) @@ -1152,15 +1221,15 @@ class Object(InterNode): self.root_handler.set_throw_back_lst(throw_back_opcodes) self.child_handler.set_handler({5: self.parse_face, - #130: self.parse_indexed_light_point, - #111: self.parse_inline_light_point, + 19: self.parse_subpush, + 20: self.parse_subpop, + 111: self.parse_inline_light_point, 10: self.parse_push, 11: self.parse_pop}) - self.props['type'] = 'Object' - self.props['id'] = self.header.fw.read_string(8) - - + self.props = dict() + self.props['comment'] = '' + self.parse_record() class Group(InterNode): def __init__(self, parent): @@ -1174,15 +1243,16 @@ class Group(InterNode): self.root_handler.set_throw_back_lst(throw_back_opcodes) self.child_handler.set_handler({5: self.parse_face, - #130: self.parse_indexed_light_point, - #111: self.parse_inline_light_point, + 19: self.parse_subpush, + 20: self.parse_subpop, + 111: self.parse_inline_light_point, 2: self.parse_group, 73: self.parse_lod, 4: self.parse_object, 10: self.parse_push, 11: self.parse_pop, 96: self.parse_unhandled, - 14: self.parse_unhandled, + 14: self.parse_dof, 91: self.parse_unhandled, 98: self.parse_unhandled, 63: self.parse_xref}) @@ -1190,49 +1260,20 @@ class Group(InterNode): 'special2', 'significance', 'layer code', 'loop count', 'loop duration', 'last frame duration']) - self.props['type'] = 'Group' self.props['comment'] = '' - self.props['id'] = self.header.fw.read_string(8) - self.props['priority'] = self.header.fw.read_short() - self.header.fw.read_ahead(2) - self.props['flags'] = self.header.fw.read_int() - self.props['special1'] = self.header.fw.read_short() - self.props['special2'] = self.header.fw.read_short() - self.props['significance'] = self.header.fw.read_short() - self.props['layer code'] = self.header.fw.read_char() - self.header.fw.read_ahead(5) - self.props['loop count'] = self.header.fw.read_int() - self.props['loop duration'] = self.header.fw.read_float() - self.props['last frame duration'] = self.header.fw.read_float() - -class XRef(InterNode): - def parse(self): - if self.xref: - self.xref.parse() - Node.parse(self) - - def __init__(self, parent): - Node.__init__(self, parent, parent.header) - InterNode.__init__(self) - - self.root_handler.set_handler({49: self.parse_matrix}) - self.root_handler.set_throw_back_lst(throw_back_opcodes) + self.parse_record() - xref_filename = self.header.fw.read_string(200) - filename = FF.find(xref_filename) + #self.props['type'] = str(self.opcode) + ':' + opcode_name[self.opcode] + #props = records[self.opcode] + #propkeys = props.keys() + #propkeys.sort() + #for position in propkeys: + # (type,length,name) = props[position] + # self.props[name] = read_prop(self.header.fw,type,length) + #self.props['id'] = self.props['3t8!id'] - self.props['type'] = 'XRef' - - if filename != None: - self.xref = Database(filename, self) - self.props['id'] = 'X: ' + Blender.sys.splitext(Blender.sys.basename(filename))[0] - else: - self.xref = None - self.props['id'] = 'X: broken' - -class LOD(InterNode): +class DOF(InterNode): def blender_import(self): - self.move_to_next_layer() InterNode.blender_import(self) def __init__(self, parent): @@ -1245,19 +1286,113 @@ class LOD(InterNode): 49: self.parse_matrix}) self.root_handler.set_throw_back_lst(throw_back_opcodes) + self.child_handler.set_handler({#130: self.parse_indexed_light_point, + 111: self.parse_inline_light_point, + 2: self.parse_group, + 73: self.parse_lod, + 4: self.parse_object, + 10: self.parse_push, + 11: self.parse_pop, + 96: self.parse_unhandled, + 14: self.parse_dof, + 91: self.parse_unhandled, + 98: self.parse_unhandled, + 63: self.parse_xref}) + self.props = dict() + self.props['comment'] = '' + self.parse_record() + + +class XRef(InterNode): + def parse(self): + if self.xref: + self.xref.parse() + Node.parse(self) + + def __init__(self, parent): + Node.__init__(self, parent, parent.header) + InterNode.__init__(self) + + self.root_handler.set_handler({49: self.parse_matrix}) + self.root_handler.set_throw_back_lst(throw_back_opcodes) + + self.props = dict() + self.props['comment'] = '' + self.parse_record() + + xref_filename = self.props['3t200!filename'] + self.props['id'] = 'X: ' + Blender.sys.splitext(Blender.sys.basename(xref_filename))[0] #this is really wrong as well.... + + if global_prefs['doxrefs'] and os.path.exists(xref_filename) and not self.header.grr.xrefs.has_key(xref_filename): + self.xref = Database(xref_filename, self.header.grr, self) + self.header.grr.xrefs[xref_filename] = self.xref + else: + self.xref = None + + + def blender_import(self): + #name = self.props['type'] + ': ' + self.props['id'] + name = self.props['id'] + self.object = self.header.scene.objects.new('Empty') + self.object.name = name + self.object.enableDupGroup = True + self.header.group.objects.link(self.object) + + #for broken links its ok to leave this empty! they purely for visual purposes anyway..... + try: + self.object.DupGroup = self.header.grr.xrefs[self.props['3t200!filename']].group + except: + pass + + if self.parent and self.parent.object: + self.parent.object.makeParent([self.object]) + + #id props import + self.object.properties['FLT'] = dict() + for key in self.props: + try: + self.object.properties['FLT'][key] = self.props[key] + except: #horrible... + pass + + self.object.Layer = current_layer + self.object.sel = 1 + if self.matrix: + self.object.setMatrix(self.matrix) + Node.blender_import(self) + + +class LOD(InterNode): + def blender_import(self): + #self.move_to_next_layer() + InterNode.blender_import(self) + #self.object.properties['FLT'] = self.props.copy() + + def __init__(self, parent): + Node.__init__(self, parent, parent.header) + InterNode.__init__(self) + + self.root_handler.set_handler({33: self.parse_long_id, + 31: self.parse_comment, + 10: self.parse_push, + 49: self.parse_matrix}) + self.root_handler.set_throw_back_lst(throw_back_opcodes) + self.child_handler.set_handler({2: self.parse_group, + 111: self.parse_inline_light_point, 73: self.parse_lod, 4: self.parse_object, 10: self.parse_push, 11: self.parse_pop, 96: self.parse_unhandled, # switch - 14: self.parse_unhandled, # DOF + 14: self.parse_dof, # DOF 91: self.parse_unhandled, # sound 98: self.parse_unhandled, # clip 63: self.parse_xref}) - self.props['type'] = 'LOD' - self.props['id'] = self.header.fw.read_string(8) + self.props = dict() + self.props['comment'] = '' + self.parse_record() class InlineLightPoint(InterNode): def __init__(self, parent): @@ -1274,119 +1409,49 @@ class InlineLightPoint(InterNode): 11: self.parse_pop}) self.indices = list() - - self.props = dict.fromkeys(['id', 'type', 'comment', 'draw order', 'appearance']) - self.app_props = dict() - + self.props = dict() self.props['comment'] = '' - self.props['type'] = 'Light Point' - self.props['id'] = self.header.fw.read_string(8) - - self.app_props.update({'smc': self.header.fw.read_short()}) - self.app_props.update({'fid': self.header.fw.read_short()}) - self.app_props.update({'back color: a': self.header.fw.read_uchar()}) - self.app_props.update({'back color: b': self.header.fw.read_uchar()}) - self.app_props.update({'back color: g': self.header.fw.read_uchar()}) - self.app_props.update({'back color: r': self.header.fw.read_uchar()}) - self.app_props.update({'display mode': self.header.fw.read_int()}) - self.app_props.update({'intensity': self.header.fw.read_float()}) - self.app_props.update({'back intensity': self.header.fw.read_float()}) - self.app_props.update({'minimum defocus': self.header.fw.read_float()}) - self.app_props.update({'maximum defocus': self.header.fw.read_float()}) - self.app_props.update({'fading mode': self.header.fw.read_int()}) - self.app_props.update({'fog punch mode': self.header.fw.read_int()}) - self.app_props.update({'directional mode': self.header.fw.read_int()}) - self.app_props.update({'range mode': self.header.fw.read_int()}) - self.app_props.update({'min pixel size': self.header.fw.read_float()}) - self.app_props.update({'max pixel size': self.header.fw.read_float()}) - self.app_props.update({'actual size': self.header.fw.read_float()}) - self.app_props.update({'trans falloff pixel size': self.header.fw.read_float()}) - self.app_props.update({'trans falloff exponent': self.header.fw.read_float()}) - self.app_props.update({'trans falloff scalar': self.header.fw.read_float()}) - self.app_props.update({'trans falloff clamp': self.header.fw.read_float()}) - self.app_props.update({'fog scalar': self.header.fw.read_float()}) - self.app_props.update({'fog intensity': self.header.fw.read_float()}) - self.app_props.update({'size threshold': self.header.fw.read_float()}) - self.app_props.update({'directionality': self.header.fw.read_int()}) - self.app_props.update({'horizontal lobe angle': self.header.fw.read_float()}) - self.app_props.update({'vertical lobe angle': self.header.fw.read_float()}) - self.app_props.update({'lobe roll angle': self.header.fw.read_float()}) - self.app_props.update({'dir falloff exponent': self.header.fw.read_float()}) - self.app_props.update({'dir ambient intensity': self.header.fw.read_float()}) - self.header.fw.read_ahead(12) # Animation settings. - self.app_props.update({'significance': self.header.fw.read_float()}) - self.props['draw order'] = self.header.fw.read_int() - self.app_props.update({'flags': self.header.fw.read_int()}) - #self.fw.read_ahead(12) # More animation settings. - - # return dictionary: lp_app name => index list - def group_points(self, props): - - name_to_indices = {} - - for i in self.indices: - vert_desc = self.header.vert_pal.vert_desc_lst[i] - app_desc = LightPointAppDesc() - app_desc.props.update(props) - # add vertex normal and color - app_desc.props.update({'nx': vert_desc.nx}) - app_desc.props.update({'ny': vert_desc.ny}) - app_desc.props.update({'nz': vert_desc.nz}) - - app_desc.props.update({'r': vert_desc.r}) - app_desc.props.update({'g': vert_desc.g}) - app_desc.props.update({'b': vert_desc.b}) - app_desc.props.update({'a': vert_desc.a}) - - app_name = GRR.request_lightpoint_app(app_desc) + self.parse_record() - if name_to_indices.get(app_name): - name_to_indices[app_name].append(i) - else: - name_to_indices.update({app_name: [i]}) - - return name_to_indices def blender_import(self): - name = '%s: %s' % (self.props['type'], self.props['id']) + - name_to_indices = self.group_points(self.app_props) + name = self.props['id'] + self.mesh= Blender.Mesh.New() + self.mesh.name = 'FLT_LP' + self.object = self.header.scene.objects.new(self.mesh) + self.object.name = name + #self.mesh.verts.extend(Vector() ) # DUMMYVERT + self.object.Layer = current_layer + self.object.sel= 1 + + self.object.properties['FLT'] = dict() + for key in self.props: + try: + self.object.properties['FLT'][key] = self.props[key] + except: #horrible... + pass - for app_name, indices in name_to_indices.iteritems(): - self.object = Blender.Object.New('Mesh', name) - #self.mesh = self.object.getData() - self.mesh= Blender.Mesh.New() - self.mesh.verts.extend( Vector() ) # DUMMYVERT - self.object.link(self.mesh) + if self.parent and self.parent.object and self.header.scene == self.parent.header.scene: + self.parent.object.makeParent([self.object]) - if self.parent: - self.parent.object.makeParent([self.object]) + if self.matrix: + self.object.setMatrix(self.matrix) + + self.mesh.verts.extend([self.header.vert_pal.blender_verts[i] for i in self.indices]) + + #add color index information. + self.mesh.verts.addPropertyLayer("FLT_VCOL",Blender.Mesh.PropertyTypes["INT"]) + for i, vindex in enumerate(self.indices): + vdesc = self.header.vert_pal.vert_desc_lst[vindex] + v = self.mesh.verts[i] + v.setProperty("FLT_VCOL",vdesc.cindex) + #for i, v in enumerate(self.mesh.verts): + # vdesc = self.header.vert_pal.vert_desc_lst[i] + # v.setProperty("FLT_VCOL",vdesc.cindex) + self.mesh.update() - for i in indices: - vert = self.header.vert_pal.blender_verts[i] - self.mesh.verts.append(vert) - - scene.link(self.object) - self.object.Layer = current_layer - self.object.sel= 1 - - if self.matrix: - self.object.setMatrix(self.matrix) - - # Import comment. - if self.props['comment'] != '': - name = 'COMMENT: ' + self.props['id'] - t = Blender.Text.New(name) - t.write(self.props['comment']) - self.props['comment'] = name - - # Attach properties. - self.props.update({'appearance': app_name}) - for name, value in self.props.iteritems(): - self.object.addProperty(name, value) - - self.mesh.update() - def parse_vertex_list(self): length = self.header.fw.get_length() fw = self.header.fw @@ -1432,7 +1497,7 @@ class IndexedLightPoint(InterNode): app_desc.props.update({'b': vert_desc.b}) app_desc.props.update({'a': vert_desc.a}) - app_name = GRR.request_lightpoint_app(app_desc) + app_name = self.header.grr.request_lightpoint_app(app_desc, self.header.scene) if name_to_indices.get(app_name): name_to_indices[app_name].append(i) @@ -1448,7 +1513,6 @@ class IndexedLightPoint(InterNode): for app_name, indices in name_to_indices.iteritems(): self.object = Blender.Object.New('Mesh', name) - #self.mesh = self.object.getData() self.mesh= Blender.Mesh.New() self.mesh.verts.extend( Vector() ) # DUMMYVERT self.object.link(self.mesh) @@ -1460,7 +1524,7 @@ class IndexedLightPoint(InterNode): vert = self.header.vert_pal.blender_verts[i] self.mesh.verts.append(vert) - scene.link(self.object) + self.header.scene.objects.link(self.object) self.object.Layer = current_layer @@ -1543,7 +1607,7 @@ class Unhandled(InterNode): 10: self.parse_push, 11: self.parse_pop, 96: self.parse_unhandled, # switch - 14: self.parse_unhandled, # DOF + 14: self.parse_dof, # DOF 91: self.parse_unhandled, # sound 98: self.parse_unhandled, # clip 63: self.parse_xref}) @@ -1552,30 +1616,31 @@ class Unhandled(InterNode): class Database(InterNode): def blender_import(self): - self.tex_pal = dict(self.tex_pal_lst) - del self.tex_pal_lst - - # Setup Textures - bl_tex_pal_lst = list() - for i in self.tex_pal.iterkeys(): - path_filename = FF.find(self.tex_pal[i]) + for key in self.tex_pal.keys(): + path_filename= FF.find(self.tex_pal[key][0]) if path_filename != None: - img = GRR.request_image(path_filename) + img = self.grr.request_image(path_filename) if img: - tex = GRR.request_texture(img) - tex.setName(FF.strip_path(self.tex_pal[i])) - bl_tex_pal_lst.append( (i, tex) ) - else: - bl_tex_pal_lst.append( (i, None) ) + self.tex_pal[key][1] = img elif global_prefs['verbose'] >= 1: - print 'Warning: Unable to find', self.tex_pal[i] - - self.bl_tex_pal = dict(bl_tex_pal_lst) - - # Setup Materials - self.mat_desc_pal = dict(self.mat_desc_pal_lst) - - InterNode.blender_import(self) + print 'Warning: Unable to find', self.tex_pal[key][0] + + self.scene.properties['FLT'] = dict() + for key in self.props: + try: + self.scene.properties['FLT'][key] = self.props[key] + except: #horrible... + pass + + self.scene.properties['FLT']['Main'] = 0 + self.scene.properties['FLT']['Filename'] = self.bname + + #import color palette + carray = list() + for color in self.col_pal: + carray.append(struct.unpack('>i',struct.pack('>BBBB',color[0],color[1],color[2],color[3]))[0]) + self.scene.properties['FLT']['Color Palette'] = carray + Node.blender_import(self) def parse_appearance_palette(self): props = dict() @@ -1696,9 +1761,10 @@ class Database(InterNode): return True def get_color(self, color_index): + color = None index = color_index / 128 intensity = float(color_index - 128.0 * index) / 127.0 - + if index >= 0 and index <= 1023: brightest = self.col_pal[index] r = int(brightest[0] * intensity) @@ -1707,7 +1773,7 @@ class Database(InterNode): a = int(brightest[3]) color = [r, g, b, a] - + return color def parse_color_palette(self): @@ -1728,15 +1794,56 @@ class Database(InterNode): def parse_texture_palette(self): name = self.fw.read_string(200) index = self.fw.read_int() - self.tex_pal_lst.append( (index, name) ) + self.tex_pal[index]= [name, None] return True - - def __init__(self, filename, parent=None): + + def read_attribute_files(self): + for tex in self.tex_pal.keys(): + [name,image] = self.tex_pal[tex] + basename = os.path.basename(name) + if(image): + basename = basename + ".attr" + dirname = os.path.dirname(Blender.sys.expandpath(image.getFilename())) #can't rely on original info stored in pallette since it might be relative link + newpath = os.path.join(dirname, basename) + if os.path.exists(newpath) and not image.properties.has_key('FLT'): + fw = flt_filewalker.FltIn(newpath) + fw.read_ahead(8) #We dont care what the attribute file says about x/y dimensions + image.properties['FLT']={} + + #need to steal code from parse records.... + props = records['Image'] + propkeys = props.keys() + propkeys.sort() + for position in propkeys: + (type,length,name) = props[position] + image.properties['FLT'][name] = read_prop(fw,type,length) + fw.close_file() + + #copy clamp settings + wrap = image.properties['FLT']['10i!Wrap'] + wrapu = image.properties['FLT']['11i!WrapU'] + wrapv = image.properties['FLT']['12i!WrapV'] + + if wrapu == 3 or wrapv == 3: + wrapuv = (wrap,wrap) + else: + wrapuv = (wrapu, wrapv) + image.clampX = wrapuv[0] + image.clampY = wrapuv[1] + + elif not os.path.exists(newpath): + print "Cannot read attribute file:" + newpath + + def __init__(self, filename, grr, parent=None): if global_prefs['verbose'] >= 1: print 'Parsing:', filename print self.fw = flt_filewalker.FltIn(filename) + self.filename = filename + self.bname = os.path.splitext(os.path.basename(filename))[0] + self.grr = grr + Node.__init__(self, parent, self) InterNode.__init__(self) @@ -1753,23 +1860,26 @@ class Database(InterNode): self.root_handler.set_throw_back_lst(throw_back_opcodes) self.child_handler.set_handler({#130: self.parse_indexed_light_point, - #111: self.parse_inline_light_point, + 111: self.parse_inline_light_point, 2: self.parse_group, 73: self.parse_lod, 4: self.parse_object, 10: self.parse_push, 11: self.parse_pop, 96: self.parse_unhandled, - 14: self.parse_unhandled, + 14: self.parse_dof, 91: self.parse_unhandled, 98: self.parse_unhandled, 63: self.parse_xref}) + self.scene = Blender.Scene.New(self.bname) + self.group = Blender.Group.New(self.bname) + self.vert_pal = None self.lightpoint_appearance_pal = dict() self.tex_pal = dict() - self.tex_pal_lst = list() - self.bl_tex_pal = dict() + #self.tex_pal_lst = list() + #self.bl_tex_pal = dict() self.col_pal = list() self.mat_desc_pal_lst = list() self.mat_desc_pal = dict() @@ -1778,7 +1888,70 @@ class Database(InterNode): 'sw lon', 'ne lat', 'ne lon', 'origin lat', 'origin lon', 'lambert lat1', 'lambert lat2', 'ellipsoid model', 'utm zone', 'radius', 'major axis', 'minor axis']) -def select_file(filename): + +def clearparent(root,childhash): + for child in childhash[root]: + clearparent(child,childhash) + root.clrParent(2,0) + +def fixscale(root,childhash): + for child in childhash[root]: + fixscale(child,childhash) + location = Blender.Mathutils.Vector(root.getLocation('worldspace')) + if location[0] != 0.0 and location[1] != 0.0 and location[2] != 0.0: + #direction = Blender.Mathutils.Vector(0-location[0],0-location[1],0-location[2]) #reverse vector + smat = Blender.Mathutils.ScaleMatrix(global_prefs['scale'],4) + root.setLocation(location * smat) + #if its a mesh, we need to scale all of its vertices too + if root.type == 'Mesh': + smat = Blender.Mathutils.ScaleMatrix(global_prefs['scale'],4) + rmesh = root.getData(mesh=True) + for v in rmesh.verts: + v.co = v.co * smat + + +def reparent(root,childhash,sce): + for child in childhash[root]: + reparent(child,childhash,sce) + + root.makeParent(childhash[root]) + sce.update(1) + +def update_scene(root,sdone): + for object in root.objects: + if object.DupGroup: + try: + child = Blender.Scene.Get(object.DupGroup.name) + except: + child = None + if child and child not in sdone: + update_scene(child,sdone) + root.makeCurrent() + #create a list of children for each object + childhash = dict() + for object in root.objects: + childhash[object] = list() + + for object in root.objects: + if object.parent: + childhash[object.parent].append(object) + + for object in root.objects: + if not object.parent: + #recursivley go through and clear all the children of their transformation, starting at deepest level first. + clearparent(object,childhash) + #now fix the location of everything + fixscale(object,childhash) + #now fix the parenting + reparent(object,childhash,root) + + for object in root.objects: + object.makeDisplayList() + root.update(1) + sdone.append(root) + + +def select_file(filename, grr): if not Blender.sys.exists(filename): msg = 'Error: File ' + filename + ' does not exist.' Blender.Draw.PupMenu(msg) @@ -1801,13 +1974,12 @@ def select_file(filename): global_prefs['get_ambient'] = False global_prefs['get_shininess'] = True global_prefs['color_from_face'] = True + global_prefs['log to blender'] = True + + - # Start loading the file, - # first set the context Blender.Window.WaitCursor(True) Blender.Window.EditMode(0) - for ob in scene.objects: - ob.sel=0 FF.add_file_to_search_path(filename) @@ -1817,7 +1989,7 @@ def select_file(filename): print load_time = Blender.sys.time() - db = Database(filename) + db = Database(filename,grr) db.parse() load_time = Blender.sys.time() - load_time @@ -1828,23 +2000,15 @@ def select_file(filename): import_time = Blender.sys.time() db.blender_import() - import_time = Blender.sys.time() - import_time + + if global_prefs['attrib']: + print "reading attribute files" + db.read_attribute_files() Blender.Window.ViewLayer(range(1,21)) - # FIX UP AFTER DUMMY VERT AND REMOVE DOUBLES - Blender.Mesh.Mode(Blender.Mesh.SelectModes['VERTEX']) - for ob in scene.objects.context: - if ob.type=='Mesh': - me=ob.getData(mesh=1) - me.verts.delete(0) # remove the dummy vert - me.sel= 1 - me.remDoubles(0.0001) - - - - Blender.Window.RedrawAll() - + update_scene(db.scene,[]) + import_time = Blender.sys.time() - import_time if global_prefs['verbose'] >= 1: print 'Done.' print @@ -1854,37 +2018,112 @@ def select_file(filename): Blender.Window.WaitCursor(False) +def setimportscale(ID,val): + global global_prefs + global_prefs['scale'] = val +def setBpath(fname): + global_prefs['fltfile'] = fname -if global_prefs['verbose'] >= 1: - print - print 'OpenFlight Importer' - print 'Version:', __version__ - print 'Author: Greg MacDonald' - print __url__[2] - print +def event(evt,val): + pass +def but_event(evt): + + global FLTBaseLabel + global FLTBaseString + global FLTBaseChooser + global FLTExport + global FLTClose + + global FLTDoXRef + global FLTShadeImport + global FLTAttrib + + #Import DB + if evt == 1: + if global_prefs['verbose'] >= 1: + print + print 'OpenFlight Importer' + print 'Version:', __version__ + print 'Author: Greg MacDonald, Campbell Barton, Geoffrey Bantle' + print __url__[2] + print + + GRR = GlobalResourceRepository() + select_file(global_prefs['fltfile'], GRR) + #choose base path for export + if evt == 4: + Blender.Window.FileSelector(setBpath, "DB Root", global_prefs['fltfile']) + #Import custom shading? + if evt == 9: + global_prefs['smoothshading'] = FLTShadeImport.val + #Import Image attribute files + if evt == 10: + global_prefs['attrib'] = FLTAttrib.val + #export XRefs + if evt == 13: + global_prefs['doxrefs'] = FLTDoXRef.val + + if evt == 2: + Draw.Exit() + -if __name__ == '__main__': - Blender.Window.FileSelector(select_file, "Import OpenFlight", "*.flt") - #select_file('/fe/flt/helnwsflt/helnws.flt') - #select_file('/fe/flt/Container_006.flt') - #select_file('/fe/flt/NaplesORIGINALmesh.flt') - #select_file('/Anti_tank_D30.flt') - #select_file('/metavr/file_examples/flt/cherrypoint/CherryPoint_liter_runway.flt') + +from Blender.BGL import * +from Blender import Draw +def gui(): + + global FLTBaseLabel + global FLTBaseString + global FLTBaseChooser -""" -TIME= Blender.sys.time() -import os -PATH= 'c:\\flt_test' -for FNAME in os.listdir(PATH): - if FNAME.lower().endswith('.flt'): - FPATH= os.path.join(PATH, FNAME) - newScn= Blender.Scene.New(FNAME) - newScn.makeCurrent() - scene= newScn - select_file(FPATH) + global FLTExport + global FLTClose + + global FLTDoXRef + global FLTShadeImport + + global FLTAttrib + + + glClearColor(0.772,0.832,0.847,1.0) + glClear(GL_COLOR_BUFFER_BIT) + + areas = Blender.Window.GetScreenInfo() + curarea = Blender.Window.GetAreaID() + curRect = None + + for area in areas: + if area['id'] == curarea: + curRect = area['vertices'] + break + + width = curRect[2] - curRect[0] + height = curRect[3] - curRect[1] + cx = 50 + cy = height - 80 -print 'TOTAL TIME: %.6f' % (Blender.sys.time() - TIME) -""" - \ No newline at end of file + FLTBaseLabel = Draw.Label("Base file:",cx,cy,100,20) + FLTBaseString = Draw.String("",3,cx+100,cy,300,20,global_prefs['fltfile'],255,"Root DB file") + FLTBaseChooser = Draw.PushButton("...",4,cx+400,cy,20,20,"Choose Folder") + + cy = cy-40 + FLTScale = Draw.Number("Import Scale",14,cx,cy,220,20,global_prefs['scale'],0.0,100.0,"Export scaleing factor",setimportscale) + + cy = cy-40 + FLTDoXRef = Draw.Toggle("Import XRefs", 13,cx,cy,220,20,global_prefs['doxrefs'],"Import External references") + + cy = cy-40 + FLTShadeImport = Draw.Toggle("Import Custom Shading",9,cx,cy,220,20,global_prefs['smoothshading'],"Import custom shading via edgesplit modifiers") + + cy = cy-40 + FLTAttrib = Draw.Toggle("Import Attribute Files", 10,cx,cy,220,20,global_prefs['attrib'],"Import Image Attribute files") + + cy = cy - 40 + FLTExport = Draw.PushButton("Import",1,cx,20,100,20,"Import FLT Database") + FLTClose = Draw.PushButton("Close",2,cx+120,20,100,20,"Close Window") + + + +Draw.Register(gui,event,but_event) \ No newline at end of file diff --git a/release/scripts/import_dxf.py b/release/scripts/import_dxf.py index 3f2fef72aa2..2a1081420e4 100644 --- a/release/scripts/import_dxf.py +++ b/release/scripts/import_dxf.py @@ -7,7 +7,7 @@ Group: 'Import' Tooltip: 'Import for DXF geometry data (Drawing eXchange Format).' """ __author__ = 'Kitsu(Ed Blake) & migius(Remigiusz Fiedler)' -__version__ = '1.0.beta10 - 2007.09.09 by migius' +__version__ = '1.0.11 - 2007.11.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"] @@ -18,69 +18,96 @@ This script imports 2d and 3d Geometery from DXFr12 format files. This version is focused on import of 3d-objects. Supported DXF Objects: -LINE -POINT -SOLID -TRACE -TEXT -INSERT (=block) -MINSERT (=array) -CIRCLE -ARC -3DFACE -2d-POLYLINE (=plane, incl. arc, variable-width, curve, spline) -3d-POLYLINE (=no-plane) -3d-POLYMESH +LINE, +POINT, +SOLID, +TRACE, +TEXT, +INSERT (=block), +MINSERT (=arrays of blocks), +CIRCLE, +ARC, +3DFACE, +2d-POLYLINE (=plane, incl. arc, variable-width, curve, spline), +3d-POLYLINE (=non-plane polylines), +3d-POLYMESH, 3d-POLYFACE -under construction, partly supported DXF>r12: + +under construction, partly supported DXF>r12 Objects: LWPOLYLINE (LightWeight), MLINE, MTEXT, ELLIPSE Unsupported DXF Objects: -DXF r12: DIMENSION, XREF (External Reference) +DXF r12: DIMENSION, XREF (External Reference), 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 +visibility, frozen, +COLOR, LAYER, +thickness, width, (todo: grouped, XDATA) It is recommended to use DXF-object properties for coding 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. -* The Blender curves of imported ARCs and POLYLINE-arc-segments have light malformed ends.(to fix in beta10) +- 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 Spline-curves, Besier-curves - support for real 3d-solids (ACIS) - (to see more, search for "-todo-" in script) +""" +""" History: - v1.0 - 2007.09 by migius: "full 3d"-release + v1.0 - 2007.11. by migius: "full 3d"-release planned tasks: + -- command-line-mode/batch-mode + -- in-place-editing for dupliGroups -- filtering of unused/not-inserted BLOCKs - -- human-formating of data in INI-File - -- suport for MLine - -- suport for Ellipse - -- suport for Mtext + -- support for MLine + -- support for Ellipse + -- support for Mtext -- blender_object.ID.properties[dxf_layer_name] + -- better support for long dxf-layer-names -- Configuration files(.ini) should/can handle various material setups -- added f_layerFilter -- to-check: obj/mat/group/_mapping-idea from ideasman42: - -- better support for long dxf-layer-names - -- support width_force for LINEs/ARCs/CIRCLEs/ELLIPSEs = "solidify" - -- curves: added fill/non-fill option for closed curves: CIRCLEs,ELLIPSEs,POLYLINEs + -- curves: added "fill/non-fill" option for closed curves: CIRCLEs,ELLIPSEs,POLYLINEs -- bug:? object = Object.Get(obname) -> = SCENE.getChildren(obname) - -- command-line-mode/batch-mode - -- fixed malformed endpoints of Blender curves of imported ARCs and POLYLINE-arc segments. - beta10: 2007.09.09 by migius + -- "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 + 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 + c2 added "set elevation" UI-option + c1 rewrite POLYLINE2d-arc-segments Bezier-interpreter + b9 many bugs fixed + b9 rewrite POLYLINE2d-arc-segments trimming (clean-trim) + b8 added "import from frozen layers" UI-option + b8 added "import from paper space" UI-option + b8 support Bezier curves for LINEs incl.thickness(0.0-10.0) + b8 added meshSmooth_on for circle/arc/polyline + b8 added vertexGroups for circle/arc + b7 added width_force for ARCs/CIRCLEs = "thin_box" option + b3 cleanup code, rename f_drawArc/Bulg->f_calcArc/Bulg + 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 + 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 rewrite f_CIRCLE.Draw: from Mesh.Primitive to Mesh a1 bugfix "newScene"-mode: Cylinders/Arcs were drawn at <0,0,0>location @@ -100,13 +127,13 @@ History: d4 added: f_set_thick(cntrolled 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 suport for all Text's parameters + d3 rewrite f_Text.Draw: added support for all Text's parameters d2 redesign: progressbar e- tuning by ideasman42: better use of the Py API. c- tuning by ideasman42 b- rewrite f_Text.Draw rotation/transform b- bugfix: POLYLINE-segment-intersection more reliable now - b- bugfix: circle:_thic, 'Empties':no material_assignement + b- bugfix: circle:_thic, 'Empties':no material_assignment b- added material assignment (from layer and/or color) a- added empty, cylinder and UVsphere for POINTs a- added support for 2d-POLYLINE: splines, fitted curves, fitted surfaces @@ -129,7 +156,7 @@ History: 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) - - added 2d/3d-support for Polyline_Width incl. angleintersection + - added 2d/3d-support for Polyline_Width incl. angle intersection beta07: 2007.06.19 by migius - added 3d-support for LWPolylines - added 2d/3d-support for Points @@ -140,7 +167,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_drawBulge for correct import the arc-segments of Polylines + - rewrote the f_calcBulge for correct import the arc-segments of Polylines beta03: 2007.06.10 by migius - rewrote interface beta02: 2007.06.09 by migius @@ -186,30 +213,34 @@ History: # -------------------------------------------------------------------------- import Blender -import bpy +#import bpy from Blender import * #from Blender.Mathutils import Vector, Matrix #import BPyMessages - -from dxfReader import readDXF # get_name, get_layer +from dxfReader import readDXF +#from dxfReader import get_name, get_layer from dxfReader import Object as dxfObject from dxfColorMap import color_map + from math import * try: import os if os.name:# != 'mac': import psyco - psyco.log() + psyco.log(Blender.Get('tempdir')+"/blender.log-psyco") + #psyco.log() psyco.full(memory=100) psyco.profile(0.05, memory=100) psyco.profile(0.2) + #print 'psyco imported' except ImportError: + #print 'psyco not imported' pass print '\n\n\n\n' -print 'Import DXF to Blender *** START ***' #--------------------- +print 'Import DXF to Blender *** start ***' #--------------------- SCENE = None WORLDX = Mathutils.Vector((1,0,0)) @@ -220,10 +251,14 @@ G_SCALE = 1.0 #(0.0001-1000) global scaling factor for all dxf data 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 -THIN_RESOLUTION = 8 #(4-500) thin_cylinder arc_resolution - number of segments +CURV_RESOLUTION = 12 #(3-50) Bezier curves 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 MIN_WIDTH = MIN_DIST * 10.0 #minimal width by forced width -ANGLECUT_LIMIT = 3.0 #limit for anglecut of polylines-wide-segments (values:1.0 - 5.0) +TRIM_LIMIT = 3.0 #limit for triming of polylines-wide-segments (values:0.0 - 5.0) +ELEVATION = 0.0 #standard elevation = coordinate Z + TARGET_LAYER = 3 #target blender_layer GROUP_BYLAYER = 0 #(0/1) all entities from same layer import into one blender-group @@ -232,6 +267,7 @@ 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' AUTO = BezTriple.HandleTypes.AUTO FREE = BezTriple.HandleTypes.FREE @@ -252,8 +288,8 @@ cur_COUNTER = 0 #counter for progress_bar # from Stani's dxf writer v1.1 (c)www.stani.be (GPL) #---color values -BYBLOCK=0 -BYLAYER=256 +BYBLOCK = 0 +BYLAYER = 256 #---block-type flags (bit coded values, may be combined): ANONYMOUS =1 # This is an anonymous block generated by hatching, associative dimensioning, other internal operations, or an application @@ -310,7 +346,7 @@ EXACT = 2 #taller characters will not override class Layer: #----------------------------------------------------------------- - """Class for objects representing dxf layers. + """Class for objects representing dxf LAYERs. """ def __init__(self, obj, name=None, color=None, frozen=None): """Expects an object of type layer as input. @@ -320,7 +356,7 @@ class Layer: #----------------------------------------------------------------- if name: self.name = name - #self.bfname = name #remi--todo----------- + #self.bfname = name #--todo---see layernamesmap in f_getLayersmap --- else: self.name = obj.get_type(2)[0] #layer name of object @@ -333,7 +369,7 @@ class Layer: #----------------------------------------------------------------- self.frozen = frozen else: self.flags = obj.get_type(70)[0] - self.frozen = self.flags&1 + self.frozen = self.flags & 1 def __repr__(self): @@ -353,7 +389,7 @@ def getit(obj, typ, default=None): #------------------------------------------ it = item[1] break #as soon as the first found except: - # TODO - I found one case where item was a text instance + # --todo-- I found one case where item was a text instance # that failed with no __getitem__ pass else: #else searching in Object with get_type-Methode @@ -368,7 +404,7 @@ def getit(obj, typ, default=None): #------------------------------------------ def get_extrusion(data): #------------------------------------------------- """Find the axis of extrusion. - Used to get from object_data the objects Object Coordinate System (ocs). + Used to get from object_data the objects Object_Coordinate_System (ocs). """ #print 'deb:get_extrusion: data: \n', data #--------------- vec = [0,0,1] @@ -380,10 +416,8 @@ def get_extrusion(data): #------------------------------------------------- - - class Solid: #----------------------------------------------------------------- - """Class for objects representing dxf solid or trace. + """Class for objects representing dxf SOLID or TRACE. """ def __init__(self, obj): """Expects an entity object of type solid or trace as input. @@ -418,7 +452,7 @@ class Solid: #----------------------------------------------------------------- d = [0, 0, 0] a[0] = getit(data, 10, None) # 10 = x a[1] = getit(data, 20, None) # 20 = y - a[2] = getit(data, 30, 0) # 30 = z + a[2] = getit(data, 30, 0) # 30 = z b[0] = getit(data, 11, None) b[1] = getit(data, 21, None) b[2] = getit(data, 31, 0) @@ -492,7 +526,7 @@ class Solid: #----------------------------------------------------------------- ob = SCENE.objects.new(me) # create a new mesh_object if settings.var['vGroup_on']: - # each MeshSite becomes vertexGroup for easier material assignment --------------------- + # each MeshSide becomes vertexGroup for easier material assignment --------------------- replace = Blender.Mesh.AssignModes.ADD #or .AssignModes.ADD/REPLACE if vg_left: me.addVertGroup('side.left') ; me.assignVertsToGroup('side.left', vg_left, 1.0, replace) if vg_right:me.addVertGroup('side.right') ; me.assignVertsToGroup('side.right', vg_right, 1.0, replace) @@ -509,7 +543,7 @@ class Solid: #----------------------------------------------------------------- class Line: #----------------------------------------------------------------- - """Class for objects representing dxf lines. + """Class for objects representing dxf LINEs. """ def __init__(self, obj): """Expects an entity object of type line as input. @@ -558,66 +592,101 @@ class Line: #----------------------------------------------------------------- #settings.var['curves_on']=False points = self.points + 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'] - global activObjectLayer - global activObjectName - #print 'deb:draw:line.ob IN activObjectName: ', activObjectName #--------------------- - - if activObjectLayer == self.layer and settings.var['one_mesh_on']: - obname = activObjectName - #print 'deb:line.draw obname from activObjectName: ', obname #--------------------- - ob = Object.Get(obname) # open an existing mesh_object - #ob = SCENE.getChildren(obname) # open an existing mesh_object - me = Mesh.Get(ob.name) # open objects mesh data - else: + if settings.var['curves_on']: # LINE curve representation------------------------- obname = 'li_%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 - activObjectName = ob.name - activObjectLayer = self.layer - #print ('deb:line.draw new line.ob+mesh:"%s" created!' %ob.name) #--------------------- - #if settings.var['width_force']: # -todo----------- + c = Curve.New(obname) # create new curve data + curve = c.appendNurb(BezTriple.New(points[0])) + curve.append(BezTriple.New(points[1])) + for point in curve: + point.handleTypes = [VECT, VECT] + curve.flagU = 0 # 0 sets the curve not cyclic=open + c.update() #important for handles calculation - faces, edges = [], [] - n = len(me.verts) - thic = set_thick(self.thic, settings) - if thic != 0: - t, e = thic, self.extrusion - #print 'deb:thic, extr: ', t, e #--------------------- - points.extend([[v[0]+t*e[0], v[1]+t*e[1], v[2]+t*e[2]] for v in points[:]]) - faces = [[0+n, 1+n, 3+n, 2+n]] - else: - me.verts.extend(points) # add vertices to mesh - edges = [[0+n, 1+n]] + ob = SCENE.objects.new(c) # create a new curve_object - me.verts.extend(points) # add vertices to mesh - if faces: me.faces.extend(faces) # add faces to the mesh - if edges: me.edges.extend(edges) # add faces to the mesh + #if False: # --todo-- better support for 210-group + if thic != 0.0: #hack: Blender2.45 curve-extrusion + t = thic * 0.5 + if abs(t) > 5.0: t = 5.0 * cmp(t,0) # Blender2.45 accepts only (0.0 - 5.0) + e = self.extrusion + c.setExt1(abs(t)) # curve-extrusion + ob.LocX += t * e[0] + ob.LocY += t * e[1] + ob.LocZ += t * e[2] + #c.setExt1(1.0) # curve-extrusion: Blender2.45 accepts only (0.0 - 5.0) + #ob.LocZ = t + self.loc[2] + #ob.SizeZ *= abs(t) + return ob - if settings.var['vGroup_on']: - # entities with the same color build one vertexGroup for easier material assignment --------------------- - ob.link(me) # link mesh to that object - vG_name = 'color_%s' %self.color_index - if edges: faces = edges - replace = Blender.Mesh.AssignModes.ADD #or .AssignModes.REPLACE or ADD - try: - me.assignVertsToGroup(vG_name, faces[0], 1.0, replace) - #print 'deb: existed vGroup:', vG_name #--------------------- - except: - me.addVertGroup(vG_name) - me.assignVertsToGroup(vG_name, faces[0], 1.0, replace) - #print 'deb: create new vGroup:', vG_name #--------------------- + else: # LINE mesh representation ------------------------------ + global activObjectLayer + global activObjectName + #print 'deb:draw:line.ob IN activObjectName: ', activObjectName #--------------------- + + if activObjectLayer == self.layer and settings.var['one_mesh_on']: + obname = activObjectName + #print 'deb:line.draw obname from activObjectName: ', obname #--------------------- + ob = Object.Get(obname) # open an existing mesh_object + #ob = SCENE.getChildren(obname) # open an existing mesh_object + me = Mesh.Get(ob.name) # open objects mesh data + else: + obname = 'li_%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 + activObjectName = ob.name + activObjectLayer = self.layer + #print ('deb:line.draw new line.ob+mesh:"%s" created!' %ob.name) #--------------------- + + faces, edges = [], [] + n = len(me.verts) + #if settings.var['width_force']: #--todo----------- - #print 'deb:draw:line.ob OUT activObjectName: ', activObjectName #--------------------- - return ob - + if thic != 0: + t, e = thic, self.extrusion + #print 'deb:thic, extr: ', t, e #--------------------- + points.extend([[v[0]+t*e[0], v[1]+t*e[1], v[2]+t*e[2]] for v in points[:]]) + faces = [[0+n, 1+n, 3+n, 2+n]] + else: + edges = [[0+n, 1+n]] + + me.verts.extend(points) # adds vertices to global mesh + if faces: me.faces.extend(faces) # add faces to the mesh + if edges: me.edges.extend(edges) # add faces to the mesh + + if settings.var['vGroup_on']: + # entities with the same color build one vertexGroup for easier material assignment ---- + ob.link(me) # link mesh to that object + vG_name = 'color_%s' %self.color_index + if edges: faces = edges + replace = Blender.Mesh.AssignModes.ADD #or .AssignModes.REPLACE or ADD + try: + me.assignVertsToGroup(vG_name, faces[0], 1.0, replace) + #print 'deb: existed vGroup:', vG_name #--------------------- + except: + me.addVertGroup(vG_name) + me.assignVertsToGroup(vG_name, faces[0], 1.0, replace) + #print 'deb: create new vGroup:', vG_name #--------------------- + + + #print 'deb:draw:line.ob OUT activObjectName: ', activObjectName #--------------------- + return ob + class Point: #----------------------------------------------------------------- - """Class for objects representing dxf points. + """Class for objects representing dxf POINTs. """ def __init__(self, obj): """Expects an entity object of type point as input. @@ -700,7 +769,7 @@ class Point: #----------------------------------------------------------------- class LWpolyline: #----------------------------------------------------------------- - """Class for objects representing dxf LWpolylines. + """Class for objects representing dxf LWPOLYLINEs. """ def __init__(self, obj): """Expects an entity object of type lwpolyline as input. @@ -793,7 +862,7 @@ class LWpolyline: #------------------------------------------------------------ else: point2 = self.points[i+1] arc_res = settings.var['arc_res']/sqrt(settings.var['arc_rad']) - verts = drawBulge(point, point2, arc_res) + verts, center = calcBulge(point, point2, arc_res) # if i == len(self.points)-1: # if self.closed: # verts.pop() #remove last(=first) vertex @@ -835,7 +904,7 @@ class LWpolyline: #------------------------------------------------------------ class Polyline: #----------------------------------------------------------------- - """Class for objects representing dxf Polylines. + """Class for objects representing dxf POLYLINEs. """ def __init__(self, obj): """Expects an entity object of type polyline as input. @@ -910,7 +979,7 @@ class Polyline: #-------------------------------------------------------------- elif self.plmesh: #---- 3dPolyMesh - mesh with ortogonal topology ob = self.drawPlMesh(settings) #---- 2dPolyline - plane polyline with arc/wide/thic segments - #---- 3dPolyline - noplane polyline (thin segments = without arc/wide/thic) + #---- 3dPolyline - non-plane polyline (thin segments = without arc/wide/thic) elif self.poly2d or self.poly3d: if settings.var['curves_on']: # and self.spline: ob = self.drawPolyCurve(settings) @@ -944,9 +1013,12 @@ class Polyline: #-------------------------------------------------------------- me.verts.extend(points) # add vertices to mesh me.faces.extend(faces) # add faces to the mesh + if settings.var['meshSmooth_on']: # ---------------------- + for i in xrange(len(faces)): + me.faces[i].smooth = True + #me.Mode(AUTOSMOOTH) transform(self.extrusion, 0, ob) #print 'deb:polyface.draw.END:----------------' #------------------------ - return ob @@ -987,6 +1059,11 @@ class Polyline: #-------------------------------------------------------------- me.verts.extend([point.loc for point in self.points]) # add vertices to mesh me.faces.extend(faces) # add faces to the mesh + if settings.var['meshSmooth_on']: # ---------------------- + for i in xrange(len(faces)): + me.faces[i].smooth = True + #me.Mode(AUTOSMOOTH) + transform(self.extrusion, 0, ob) #print 'deb:polymesh.draw.END:----------------' #------------------------ return ob @@ -1006,14 +1083,19 @@ class Polyline: #-------------------------------------------------------------- obname = '%s_%s' %(pline_typ, self.layer) # create object_name from layer name obname = obname[:MAX_NAMELENGTH] d_points = [] - #for DXFr10-format: update all points[].loc[2] == None -> 0.0 - for point in self.points: - if point.loc[2] == None: + + if settings.var['Z_force_on']: + self.elevation = settings.var['Z_elev'] + for point in self.points: point.loc[2] = self.elevation - d_points.append(point) + d_points.append(point) + else: #for DXFr10-format: update all points[].loc[2] == None -> 0.0 + for point in self.points: + if point.loc[2] == None: + point.loc[2] = self.elevation + d_points.append(point) thic = set_thick(self.thic, settings) - if thic != 0.0: #hack: Blender<2.45 curve-extrusion LocZ = d_points[0].loc[2] temp_points = [] @@ -1024,6 +1106,7 @@ class Polyline: #-------------------------------------------------------------- #print 'deb:polyline2dCurve.draw d_points=', d_points #--------------- pline = Curve.New(obname) # create new curve data + #pline.setResolu(24) #--todo----- if False: #self.spline: # NURBSplines-----FAKE(with Bezier)----- #print 'deb:polyline2dCurve.draw self.spline!' #--------------- @@ -1039,7 +1122,7 @@ class Polyline: #-------------------------------------------------------------- curve[0].handleTypes = [FREE, ALIGN] #remi--todo----- curve[-1].handleTypes = [ALIGN, FREE] #remi--todo----- - elif self.spline: # NURBSplines-----TODO--:if curvQBspline: generate middlepoints--- + elif self.spline: # NURBSplines-----OK----- #print 'deb:polyline2dCurve.draw self.spline!' #--------------- weight1 = 0.5 weight2 = 1.0 @@ -1111,33 +1194,99 @@ class Polyline: #-------------------------------------------------------------- curve[0].handleTypes = [FREE, ALIGN] #remi--todo----- curve[-1].handleTypes = [ALIGN, FREE] #remi--todo----- - else: #--straight line/arc-segments----OK------ + else: #--straight line- and arc-segments----OK------ + #print 'deb:polyline2dCurve.draw curve:', curve #----- points = [] - d_points.append(d_points[0]) #------ first vertex added ------------- + arc_res = settings.var['curve_arc'] + prevHandleType = VECT + #d_points.append(d_points[0]) #------ first vertex added at the end of list -------- #curve.setType(0) #polygon_type of Blender_curve - for i in xrange(len(d_points)-1): + for i in xrange(len(d_points)): point1 = d_points[i] - point2 = d_points[i+1] - if point1.bulge and (i < len(d_points)-2 or self.closed): - verts = drawBulge(point1, point2, arc_res=8, curve_on=True) #calculate additional points for bulge - if i == 0: curve = pline.appendNurb(BezTriple.New(verts[0])) - else: curve.append(BezTriple.New(verts[0])) - curve[-1].handleTypes = [VECT, VECT] #--todo--calculate bezier-tangents - for p in verts[1:]: - curve.append(BezTriple.New(p)) - curve[-1].handleTypes = [AUTO, AUTO] #--todo--calculate bezier-tangents -# curve[-1].handleTypes = [VECT, VECT] #--todo--calculate bezier-tangents - else: - if i == 0: curve = pline.appendNurb(BezTriple.New(point1.loc)) - else: curve.append(BezTriple.New(point1.loc)) - curve[-1].handleTypes = [VECT, VECT] #--todo--calculate bezier-tangents + #point2 = d_points[i+1] + if False: #-----outdated!- standard calculation ---------------------------------- + if point1.bulge and (i < len(d_points)-2 or self.closed): + verts, center = calcBulge(point1, point2, arc_res, triples=False) + if i == 0: curve = pline.appendNurb(BezTriple.New(verts[0])) + else: curve.append(BezTriple.New(verts[0])) + curve[-1].handleTypes = [VECT, VECT] #--todo--calculation of bezier-tangents + for p in verts[1:]: + curve.append(BezTriple.New(p)) + curve[-1].handleTypes = [AUTO, AUTO] + else: + if i == 0: curve = pline.appendNurb(BezTriple.New(point1.loc)) + else: curve.append(BezTriple.New(point1.loc)) + curve[-1].handleTypes = [VECT, VECT] #--todo--calculation of bezier-tangents + + elif True: #----- optimised Bezier-Handles calculation -------------------------------- + #print 'deb:drawPlineCurve: i:', i #--------- + if point1.bulge and not (i == len(d_points)-1 and point1.bulge and not self.closed): + if i == len(d_points)-1: point2 = d_points[0] + else: point2 = d_points[i+1] + + + # calculate additional points for bulge + VectorTriples = calcBulge(point1, point2, arc_res, triples=True) + + if prevHandleType == FREE: + #print 'deb:drawPlineCurve: VectorTriples[0]:', VectorTriples[0] #--------- + VectorTriples[0][:3] = prevHandleVect + #print 'deb:drawPlineCurve: VectorTriples[0]:', VectorTriples[0] #--------- + + if i == 0: curve = pline.appendNurb(BezTriple.New(VectorTriples[0])) + else: curve.append(BezTriple.New(VectorTriples[0])) + curve[-1].handleTypes = [prevHandleType, FREE] + + for p in VectorTriples[1:-1]: + curve.append(BezTriple.New(p)) + curve[-1].handleTypes = [FREE, FREE] + + prevHandleVect = VectorTriples[-1][:3] + prevHandleType = FREE + #print 'deb:drawPlineCurve: prevHandleVect:', prevHandleVect #--------- + else: + #print 'deb:drawPlineCurve: else' #---------- + if prevHandleType == FREE: + VectorTriples = prevHandleVect + list(point1) + list(point1) + #print 'deb:drawPlineCurve: VectorTriples:', VectorTriples #--------- + curve.append(BezTriple.New(VectorTriples)) + curve[-1].handleTypes = [FREE, VECT] + prevHandleType = VECT + else: + if i == 0: curve = pline.appendNurb(BezTriple.New(point1.loc)) + else: curve.append(BezTriple.New(point1.loc)) + curve[-1].handleTypes = [VECT, VECT] + + + + #print 'deb:drawPlineCurve: curve[-1].vec[0]', curve[-1].vec[0] #---------- + if self.closed: curve.flagU = 1 # Set curve cyclic=close -# curve[0].handleTypes = [VECT, VECT] #--todo--calculate bezier-tangents - else: + if prevHandleType == FREE: + #print 'deb:drawPlineCurve:closed curve[0].vec:', curve[0].vec #---------- + #print 'deb:drawPlineCurve:closed curve[0].handleTypes:', curve[0].handleTypes #---------- + prevHandleType2 = curve[0].handleTypes[1] + p0h1,p0,p0h2 = curve[0].vec + #print 'deb:drawPlineCurve:closed p0h1:', p0h1 #---------- + p0h1 = prevHandleVect + #p0h1 = [0,0,0] + #print 'deb:drawPlineCurve:closed p0h1:', p0h1 #---------- + #curve[0].vec = [p0h1,p0,p0h2] + curve.__setitem__(0,BezTriple.New(p0h1+p0+p0h2)) + + curve[0].handleTypes = [FREE,prevHandleType2] + #print 'deb:drawPlineCurve:closed curve[0].vec:', curve[0].vec #---------- + #print 'deb:drawPlineCurve:closed curve[0].handleTypes:', curve[0].handleTypes #---------- + else: + curve[0].handleTypes[0] = VECT + else: curve.flagU = 0 # Set curve not cyclic=open - curve[0].handleTypes = [FREE, VECT] #--todo--calculate bezier-tangents - curve[-1].handleTypes = [VECT, FREE] #--todo--calculate bezier-tangents + + if settings.var['fill_on']: + pline.setFlag(6) # 2+4 set top and button caps + else: + pline.setFlag(pline.getFlag() & ~6) # dont set top and button caps pline.update() ob = SCENE.objects.new(pline) # create a new curve_object @@ -1155,7 +1304,7 @@ class Polyline: #-------------------------------------------------------------- return ob - def drawPoly2d(self, settings): #---- 2dPolyline - plane wide/thic lines + def drawPoly2d(self, settings): #---- 2dPolyline - plane lines/arcs with wide/thic """Generate the geometery of regular polyline. """ #print 'deb:polyline2d.draw.START:----------------' #------------------------ @@ -1170,28 +1319,39 @@ class Polyline: #-------------------------------------------------------------- elif self.curved: pline_typ = 'pc' else: pline_typ = 'pl' obname = '%s_%s' %(pline_typ, self.layer) # create object_name from layer name -# obname = 'pl_%s' %self.layer # create object name from layer name obname = obname[:MAX_NAMELENGTH] if len(self.points) < 2: #print 'deb:drawPoly2d exit, cause POLYLINE has less than 2 vertices' #--------- return - #d_points = self.points[:] - #for DXFr10-format: update all points[].loc[2] == None -> 0.0 - for point in self.points: - if point.loc[2] == None: + + if settings.var['Z_force_on']: + self.elevation = settings.var['Z_elev'] + for point in self.points: point.loc[2] = self.elevation - d_points.append(point) - #print 'deb:len of d_pointsList ====== ', len(d_points) #------------------------ - - #add duplic of the first vertex at the end of pointslist - d_points.append(d_points[0]) - - #print 'deb:len of d_pointsList ====== ', len(d_points) #------------------------ - #print 'deb:d_pointsList ======:\n ', d_points #------------------------ + d_points.append(point) + else: #for DXFr10-format: update all non-existing LocZ points[].loc[2] == None -> 0.0 elevation + for point in self.points: + if point.loc[2] == None: + point.loc[2] = self.elevation + d_points.append(point) + #print 'deb:drawPoly2d len of d_pointsList ====== ', len(d_points) #------------------------ + #print 'deb:drawPoly2d d_pointsList ======:\n ', d_points #------------------------ - #routine to sort out of "double.vertices" -------- + #if closed polyline, add duplic of the first vertex at the end of pointslist + if self.closed: #new_b8 + if d_points[-1].loc != d_points[0].loc: # if not equal, then set the first at the end of pointslist + d_points.append(d_points[0]) + else: + if d_points[-1].loc == d_points[0].loc: # if equal, then set to closed, and modify the last point + d_points[-1] = d_points[0] + self.closed = True + #print 'deb:drawPoly2d len of d_pointsList ====== ', len(d_points) #------------------------ + #print 'deb:drawPoly2d d_pointsList ======:\n ', d_points #------------------------ + + + # routine to sort out of "double.vertices" ------------------------------------ minimal_dist = settings.var['dist_min'] * 0.1 temp_points = [] for i in xrange(len(d_points)-1): @@ -1201,64 +1361,78 @@ class Polyline: #-------------------------------------------------------------- delta = Mathutils.Vector(point2.loc) - Mathutils.Vector(point.loc) if delta.length > minimal_dist: temp_points.append(point) - #else: print 'deb:double.vertex sort out!' #------------------------ - temp_points.append(d_points[-1]) #------ last vertex added ------------- + #else: print 'deb:drawPoly2d double.vertex sort out!' #------------------------ + temp_points.append(d_points[-1]) #------ incl. last vertex ------------- + #if self.closed: temp_points.append(d_points[1]) #------ loop start vertex ------------- d_points = temp_points #-----vertex.list without "double.vertices" - #print 'deb:d_pointsList =after DV-outsorting=====:\n ', d_points #------------------------ + #print 'deb:drawPoly2d d_pointsList =after DV-outsorting=====:\n ', d_points #------------------------ - #print 'deb:len of d_pointsList ====== ', len(d_points) #------------------------ - if len(d_points) < 2: + #print 'deb:drawPoly2d len of d_pointsList ====== ', len(d_points) #------------------------ + if len(d_points) < 2: #if too few vertex, then return #print 'deb:drawPoly2d corrupted Vertices' #--------- return - #analyse of straight- and bulge-segments (generation of additional points for bulge) - exist_wide_segment = False + # analyze of straight- and bulge-segments + # generation of additional points for bulge segments + arc_res = settings.var['arc_res']/sqrt(settings.var['arc_rad']) + wide_segment_exist = False + bulg_points = [] # for each point set None (or center for arc-subPoints) for i in xrange(len(d_points)-1): point1 = d_points[i] point2 = d_points[i+1] - #print 'deb:pline.tocalc.point1:', point1 #------------------------ - #print 'deb:pline.tocalc.point2:', point2 #------------------------ + #print 'deb:drawPoly2d_bulg tocalc.point1:', point1 #------------------------ + #print 'deb:drawPoly2d_bulg tocalc.point2:', point2 #------------------------ swidth = point1.swidth ewidth = point1.ewidth if swidth == None: swidth = swidth_default if ewidth == None: ewidth = ewidth_default - - if swidth != 0.0 or ewidth != 0.0: exist_wide_segment = True + if swidth != 0.0 or ewidth != 0.0: wide_segment_exist = True if settings.var['width_force']: # force minimal width for thin segments - if swidth < settings.var['width_min']: swidth = settings.var['width_min'] - if ewidth < settings.var['width_min']: ewidth = settings.var['width_min'] + width_min = settings.var['width_min'] + if swidth < width_min: swidth = width_min + if ewidth < width_min: ewidth = width_min if not settings.var['width_on']: # then force minimal width for all segments - swidth = settings.var['width_min'] - ewidth = settings.var['width_min'] + swidth = width_min + ewidth = width_min - if point1.bulge and (i < (len(d_points)-2) or self.closed): - arc_res = settings.var['arc_res']/sqrt(settings.var['arc_rad']) - verts = drawBulge(point1, point2, arc_res) #calculate additional points for bulge + #if point1.bulge and (i < (len(d_points)-1) or self.closed): + if point1.bulge and i < (len(d_points)-1): #10_b8 + verts, center = calcBulge(point1, point2, arc_res) #calculate additional points for bulge points.extend(verts) delta_width = (ewidth - swidth) / len(verts) width_list = [swidth + (delta_width * ii) for ii in xrange(len(verts)+1)] - swidths.extend(width_list[0:-1]) + swidths.extend(width_list[:-1]) ewidths.extend(width_list[1:]) + bulg_list = [center for ii in xrange(len(verts))] + #the last point in bulge has index False for better indexing of bulg_end! + bulg_list[-1] = None + bulg_points.extend(bulg_list) + else: points.append(point1.loc) swidths.append(swidth) ewidths.append(ewidth) + bulg_points.append(None) + points.append(d_points[-1].loc) #--calculate width_vectors: left-side- and right-side-points ---------------- # 1.level:IF width --------------------------------------- - if (settings.var['width_on'] and exist_wide_segment) or settings.var['width_force']: - points.append(d_points[0].loc) #temporarly add first vertex at the end (for better loop) - + if (settings.var['width_on'] and wide_segment_exist) or settings.var['width_force']: + #new_b8 points.append(d_points[0].loc) #temporarly add first vertex at the end (for better loop) + dist_min05 = 0.5 * settings.var['dist_min'] #minimal width for zero_witdh + pointsLs = [] # list of left-start-points pointsLe = [] # list of left-end-points pointsRs = [] # list of right-start-points pointsRe = [] # list of right-end-points - pointsW = [] # list of entire-border-points + pointsW = [] # list of all border-points #rotMatr90 = Mathutils.Matrix(rotate 90 degree around Z-axis) = normalvectorXY rotMatr90 = Mathutils.Matrix([0, -1, 0], [1, 0, 0], [0, 0, 1]) + bulg_in = False + last_bulg_point = False for i in xrange(len(points)-1): point1 = points[i] point2 = points[i+1] @@ -1266,92 +1440,205 @@ class Polyline: #-------------------------------------------------------------- point2vec = Mathutils.Vector(point2) swidth05 = swidths[i] * 0.5 ewidth05 = ewidths[i] * 0.5 - if swidth05 == 0: swidth05 = 0.5 * settings.var['dist_min'] #minimal width - if ewidth05 == 0: ewidth05 = 0.5 * settings.var['dist_min'] #minimal width - + if swidth05 == 0: swidth05 = dist_min05 + if ewidth05 == 0: ewidth05 = dist_min05 normal_vector = rotMatr90 * (point2vec-point1vec).normalize() - swidth05vec = swidth05 * normal_vector - ewidth05vec = ewidth05 * normal_vector - pointsLs.append(point1vec + swidth05vec) #vertex left start - pointsRs.append(point1vec - swidth05vec) #vertex right start - pointsLe.append(point2vec + ewidth05vec) #vertex left end - pointsRe.append(point2vec - ewidth05vec) #vertex right end + if last_bulg_point: + last_bulg_point = False + bulg_in = True + elif bulg_points[i] != None: + centerVec = Mathutils.Vector(bulg_points[i]) + if bulg_points[i+1] == None: last_bulg_point = True + bulg_in = True + else: bulg_in = False - pointsLc, pointsRc = [], [] + if bulg_in: + #makes clean intersections for arc-segments + radius1vec = point1vec - centerVec + radius2vec = point2vec - centerVec + angle = Mathutils.AngleBetweenVecs(normal_vector, radius1vec) + if angle < 90.0: + normal_vector1 = radius1vec.normalize() + normal_vector2 = radius2vec.normalize() + else: + normal_vector1 = - radius1vec.normalize() + normal_vector2 = - radius2vec.normalize() - # 2.level:IF width and corner-intersection activated - if settings.var['pl_section_on']: #optional clean corner-intersections + swidth05vec = swidth05 * normal_vector1 + ewidth05vec = ewidth05 * normal_vector2 + pointsLs.append(point1vec + swidth05vec) #vertex left start + pointsRs.append(point1vec - swidth05vec) #vertex right start + pointsLe.append(point2vec + ewidth05vec) #vertex left end + pointsRe.append(point2vec - ewidth05vec) #vertex right end + + else: + swidth05vec = swidth05 * normal_vector + ewidth05vec = ewidth05 * normal_vector + pointsLs.append(point1vec + swidth05vec) #vertex left start + pointsRs.append(point1vec - swidth05vec) #vertex right start + pointsLe.append(point2vec + ewidth05vec) #vertex left end + pointsRe.append(point2vec - ewidth05vec) #vertex right end + + # additional last point is also calculated + #pointsLs.append(pointsLs[0]) + #pointsRs.append(pointsRs[0]) + #pointsLe.append(pointsLe[0]) + #pointsRe.append(pointsRe[0]) + + pointsLc, pointsRc = [], [] # lists Left/Right corners = intersection points + + # 2.level:IF width and corner-trim + if settings.var['pl_trim_on']: #optional clean corner-intersections + # loop preset + # set STARTpoints of the first point points[0] if not self.closed: pointsLc.append(pointsLs[0]) pointsRc.append(pointsRs[0]) - lenL = len(pointsLs)-2 #without the last point at the end of the list else: pointsLs.append(pointsLs[0]) pointsRs.append(pointsRs[0]) pointsLe.append(pointsLe[0]) pointsRe.append(pointsRe[0]) points.append(points[0]) - lenL = len(pointsLs)-1 #without the duplic of the first point at the end of the list - #print 'deb:pointsLs():\n', pointsLs #---------------- - #print 'deb:lenL, len.pointsLs():', lenL,',', len(pointsLs) #---------------- + vecL3, vecL4 = pointsLs[0], pointsLe[0] + vecR3, vecR4 = pointsRs[0], pointsRe[0] + lenL = len(pointsLs)-1 + #print 'deb:drawPoly2d pointsLs():\n', pointsLs #---------------- + #print 'deb:drawPoly2d lenL, len.pointsLs():', lenL,',', len(pointsLs) #---------------- + bulg_in = False + last_bulg_point = False + + # LOOP: makes (ENDpoints[i],STARTpoints[i+1]) for i in xrange(lenL): - pointVec = Mathutils.Vector(points[i+1]) - #print 'deb:pointVec: ', pointVec #------------- - #compute left-corner-points - vecL1 = pointsLs[i] - vecL2 = pointsLe[i] - vecL3 = pointsLs[i+1] - vecL4 = pointsLe[i+1] - #print 'deb:vectorsL:---------\n', vecL1,'\n',vecL2,'\n',vecL3,'\n',vecL4 #------------- + if bulg_points[i] != None: + if bulg_points[i+1] == None: #makes clean intersections for arc-segments + last_bulg_point = True + if not bulg_in: + bulg_in = True + #pointsLc.extend((points[i], pointsLs[i])) + #pointsRc.extend((points[i], pointsRs[i])) + vecL1, vecL2 = vecL3, vecL4 + vecR1, vecR2 = vecR3, vecR4 + vecL3, vecL4 = pointsLs[i+1], pointsLe[i+1] + vecR3, vecR4 = pointsRs[i+1], pointsRe[i+1] + #compute left- and right-cornerpoints #cornerpointL = Geometry.LineIntersect2D(vec1, vec2, vec3, vec4) cornerpointL = Mathutils.LineIntersect(vecL1, vecL2, vecL3, vecL4) - #print 'deb:cornerpointL: ', cornerpointL #------------- - - #compute right-corner-points - vecR1 = pointsRs[i] - vecR2 = pointsRe[i] - vecR3 = pointsRs[i+1] - vecR4 = pointsRe[i+1] - #print 'deb:vectorsR:---------\n', vecR1,'\n',vecR2,'\n',vecR3,'\n',vecR4 #------------- - #cornerpointR = Geometry.LineIntersect2D(vec1, vec2, vec3, vec4) cornerpointR = Mathutils.LineIntersect(vecR1, vecR2, vecR3, vecR4) - #print 'deb:cornerpointR: ', cornerpointR #------------- + #print 'deb:drawPoly2d cornerpointL: ', cornerpointL #------------- + #print 'deb:drawPoly2d cornerpointR: ', cornerpointR #------------- - #if diststance(cornerL-center-cornerR) < limiter * (seg1_endWidth + seg2_startWidth) - if cornerpointL != None and cornerpointR != None: - cornerpointL = cornerpointL[0] + # IF not cornerpoint THEN check if identic start-endpoints (=collinear segments) + if cornerpointL == None or cornerpointR == None: + if vecL2 == vecL3 and vecR2 == vecR3: + #print 'deb:drawPoly2d pointVec: ####### identic ##########' #---------------- + pointsLc.append(pointsLe[i]) + pointsRc.append(pointsRe[i]) + else: + pointsLc.extend((pointsLe[i],points[i+1],pointsLs[i+1])) + pointsRc.extend((pointsRe[i],points[i+1],pointsRs[i+1])) + else: + cornerpointL = cornerpointL[0] # because Mathutils.LineIntersect() -> (pkt1,pkt2) cornerpointR = cornerpointR[0] + #print 'deb:drawPoly2d cornerpointL: ', cornerpointL #------------- + #print 'deb:drawPoly2d cornerpointR: ', cornerpointR #------------- + pointVec0 = Mathutils.Vector(points[i]) + pointVec = Mathutils.Vector(points[i+1]) + pointVec2 = Mathutils.Vector(points[i+2]) + #print 'deb:drawPoly2d pointVec0: ', pointVec0 #------------- + #print 'deb:drawPoly2d pointVec: ', pointVec #------------- + #print 'deb:drawPoly2d pointVec2: ', pointVec2 #------------- + # if diststance(cornerL-center-cornerR) < limiter * (seg1_endWidth + seg2_startWidth) max_cornerDist = (vecL2 - vecR2).length + (vecL3 - vecR3).length is_cornerDist = (cornerpointL - pointVec).length + (cornerpointR - pointVec).length - # anglecut --------- limited by ANGLECUT_LIMIT (1.0 - 5.0) - if is_cornerDist < max_cornerDist * settings.var['angle_cut']: + #corner_angle = Mathutils.AngleBetweenVecs((pointVec0 - pointVec),(pointVec - pointVec2)) + #print 'deb:drawPoly2d corner_angle: ', corner_angle #------------- + #print 'deb:drawPoly2d max_cornerDist, is_cornerDist: ', max_cornerDist, is_cornerDist #------------- + #if abs(corner_angle) < 90.0: + # intersection --------- limited by TRIM_LIMIT (1.0 - 5.0) + if is_cornerDist < max_cornerDist * settings.var['pl_trim_max']: + # clean corner intersection pointsLc.append(cornerpointL) pointsRc.append(cornerpointR) - else: + elif False: # the standard no-intersection + # --todo-- not optimal, because produces X-face pointsLc.extend((pointsLe[i],pointsLs[i+1])) pointsRc.extend((pointsRe[i],pointsRs[i+1])) - else: - pointsLc.extend((pointsLe[i],pointsLs[i+1])) - pointsRc.extend((pointsRe[i],pointsRs[i+1])) + elif False: # --todo-- the optimised non-intersection + if (cornerpointL - vecL1).length < (cornerpointR - vecR1).length: + left_angle = True + else: + left_angle = False + limit_dist = settings.var['dist_min'] + if left_angle: # if left turning angle + print 'deb:drawPoly2d it is left turning angle' #------------- + # to avoid triangelface/doubleVertex + delta1 = (cornerpointL - vecL1).normalize() * limit_dist + delta4 = (cornerpointL - vecL4).normalize() * limit_dist + pointsLc.extend((cornerpointL - delta1, cornerpointL - delta4)) + pointsRc.extend((pointsRe[i],pointsRs[i+1])) + else: # if right turning angle + print 'deb:drawPoly2d right turning angle' #------------- + delta1 = (cornerpointR - vecR1).normalize() * limit_dist + delta4 = (cornerpointR - vecR4).normalize() * limit_dist + pointsRc.extend((cornerpointR - delta1, cornerpointR - delta4)) + pointsLc.extend((pointsLe[i],pointsLs[i+1])) + else: + pointsLc.extend((pointsLe[i],points[i+1],pointsLs[i+1])) + pointsRc.extend((pointsRe[i],points[i+1],pointsRs[i+1])) if not self.closed: - pointsLc.append(pointsLe[-2]) - pointsRc.append(pointsRe[-2]) - else: - """ """ + pointsLc.append(pointsLe[-1]) + pointsRc.append(pointsRe[-1]) - # 2.level:IF width but not corner-intersection activated + # 2.level:IF width but no-trim else: - # points_multiplexer of start-points and end-points - lenL = len(pointsLs) - 1 #without the duplic of the first point at the end of list - if self.closed: lenL += 1 #inclusive the duplic of the first point at the end of list - for i in xrange(lenL): - pointsLc.extend((pointsLs[i], pointsLe[i])) - pointsRc.extend((pointsRs[i], pointsRe[i])) + # loop preset + # set STARTpoints of the first point points[0] + if not self.closed: + pointsLc.append(pointsLs[0]) + pointsRc.append(pointsRs[0]) + else: + pointsLs.append(pointsLs[0]) + pointsRs.append(pointsRs[0]) + pointsLe.append(pointsLe[0]) + pointsRe.append(pointsRe[0]) + points.append(points[0]) + vecL3, vecL4 = pointsLs[0], pointsLe[0] + vecR3, vecR4 = pointsRs[0], pointsRe[0] + lenL = len(pointsLs)-1 + #print 'deb:drawPoly2d pointsLs():\n', pointsLs #---------------- + #print 'deb:drawPoly2d lenL, len.pointsLs():', lenL,',', len(pointsLs) #---------------- + bulg_in = False + last_bulg_point = False + # LOOP: makes (ENDpoints[i],STARTpoints[i+1]) + for i in xrange(lenL): + vecL1, vecL2 = vecL3, vecL4 + vecR1, vecR2 = vecR3, vecR4 + vecL3, vecL4 = pointsLs[i+1], pointsLe[i+1] + vecR3, vecR4 = pointsRs[i+1], pointsRe[i+1] + if bulg_points[i] != None: + #compute left- and right-cornerpoints + if True: + cornerpointL = Mathutils.LineIntersect(vecL1, vecL2, vecL3, vecL4) + cornerpointR = Mathutils.LineIntersect(vecR1, vecR2, vecR3, vecR4) + pointsLc.append(cornerpointL[0]) + pointsRc.append(cornerpointR[0]) + else: + pointVec = Mathutils.Vector(point[i]) + + else: # IF non-bulg + pointsLc.extend((pointsLe[i],points[i+1],pointsLs[i+1])) + pointsRc.extend((pointsRe[i],points[i+1],pointsRs[i+1])) + if not self.closed: + pointsLc.append(pointsLe[-1]) + pointsRc.append(pointsRe[-1]) + + len1 = len(pointsLc) + #print 'deb:drawPoly2d len1:', len1 #----------------------- + #print 'deb:drawPoly2d len1 len(pointsLc),len(pointsRc):', len(pointsLc),len(pointsRc) #----------------------- pointsW = pointsLc + pointsRc # all_points_List = left_side + right_side - #print 'deb:pointsW():\n', pointsW #---------------- - len1 = int(len(pointsW) * 0.5) - #print 'deb:len1:', len1 #----------------------- + #print 'deb:drawPoly2d pointsW():\n', pointsW #---------------- # 2.level:IF width and thickness --------------------- if thic != 0: @@ -1378,7 +1665,7 @@ class Polyline: #-------------------------------------------------------------- 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_bottom + f_top + f_left + f_right + f_start + f_end + faces = f_left + f_right + f_bottom + f_top + f_start + f_end #faces = f_bottom + f_top #faces = f_left + f_right + f_start + f_end #print 'deb:faces_list:\n', faces #----------------------- @@ -1387,12 +1674,12 @@ class Polyline: #-------------------------------------------------------------- me.verts.extend(pointsW) # add vertices to mesh me.faces.extend(faces) # add faces to the mesh - # each MeshSite becomes vertexGroup for easier material assignment --------------------- + # each MeshSide becomes vertexGroup for easier material assignment --------------------- # The mesh must first be linked to an object so the method knows which object to update. # This is because vertex groups in Blender are stored in the object -- not in the mesh, # which may be linked to more than one object. if settings.var['vGroup_on']: - # each MeshSite becomes vertexGroup for easier material assignment --------------------- + # 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) @@ -1407,6 +1694,13 @@ class Polyline: #-------------------------------------------------------------- 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) + if settings.var['meshSmooth_on']: # left and right side become smooth ---------------------- + #if self.spline or self.curved: + if True: + smooth_len = len(f_left) + len(f_right) + for i in xrange(smooth_len): + me.faces[i].smooth = True + #me.Modes(AUTOSMOOTH) # 2.level:IF width, but no-thickness --------------------- else: @@ -1439,6 +1733,13 @@ class Polyline: #-------------------------------------------------------------- me.verts.extend(points) # add vertices to mesh me.faces.extend(faces) # add faces to the mesh + if settings.var['meshSmooth_on']: # left and right side become smooth ---------------------- + #if self.spline or self.curved: + if True: + for i in xrange(len(faces)): + me.faces[i].smooth = True + #me.Modes(AUTOSMOOTH) + # 1.level:IF no-width and no-thickness --------------------- else: edges = [[num, num+1] for num in xrange(len(points)-1)] @@ -1457,7 +1758,7 @@ class Polyline: #-------------------------------------------------------------- class Vertex(object): #----------------------------------------------------------------- - """Generic vertex object used by polylines (and maybe others). + """Generic vertex object used by POLYLINEs (and maybe others). """ def __init__(self, obj=None): @@ -1570,7 +1871,7 @@ class Vertex(object): #-------------------------------------------------------- class Text: #----------------------------------------------------------------- - """Class for objects representing dxf Text. + """Class for objects representing dxf TEXT. """ def __init__(self, obj): """Expects an entity object of type text as input. @@ -1705,7 +2006,7 @@ def set_thick(thickness, settings): if settings.var['thick_force']: if settings.var['thick_on']: if abs(thickness) < settings.var['thick_min']: - thic = settings.var['thick_min'] * cmp(self.thic,0) + thic = settings.var['thick_min'] * cmp(thickness,0) else: thic = thickness else: thic = settings.var['thick_min'] else: @@ -1717,7 +2018,7 @@ def set_thick(thickness, settings): class Mtext: #----------------------------------------------------------------- - """Class for objects representing dxf Mtext. + """Class for objects representing dxf MTEXT. """ def __init__(self, obj): @@ -1816,7 +2117,7 @@ class Mtext: #----------------------------------------------------------------- class Circle: #----------------------------------------------------------------- - """Class for objects representing dxf Circles. + """Class for objects representing dxf CIRCLEs. """ def __init__(self, obj): @@ -1867,28 +2168,56 @@ class Circle: #---------------------------------------------------------------- thic = set_thick(self.thic, settings) if settings.var['curves_on']: - c = Curve.New(obname) # create new curve data - p1 = (0, -radius, 0) - p2 = (radius, 0, 0) - p3 = (0, radius, 0) - p4 = (-radius, 0, 0) + 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 + arc_res = settings.var['curve_arc'] + #arc_res = 3 + start, end = 0.0, 360.0 + VectorTriples = calcArc(None, radius, start, end, arc_res, True) + c = Curve.New(obname) # create new curve data + curve = c.appendNurb(BezTriple.New(VectorTriples[0])) + for p in VectorTriples[1:-1]: + curve.append(BezTriple.New(p)) + for point in curve: + point.handleTypes = [FREE, FREE] + else: # standard version + c = Curve.New(obname) # create new curve data + p1 = (0, -radius, 0) + p2 = (radius, 0, 0) + p3 = (0, radius, 0) + p4 = (-radius, 0, 0) + + p1 = BezTriple.New(p1) + p2 = BezTriple.New(p2) + p3 = BezTriple.New(p3) + p4 = BezTriple.New(p4) + + curve = c.appendNurb(p1) + curve.append(p2) + curve.append(p3) + curve.append(p4) + for point in curve: + point.handleTypes = [AUTO, AUTO] - p1 = BezTriple.New(p1) - p2 = BezTriple.New(p2) - p3 = BezTriple.New(p3) - p4 = BezTriple.New(p4) + curve.flagU = 1 # 1 sets the curve cyclic=closed + if settings.var['fill_on']: + c.setFlag(6) # 2+4 set top and button caps + else: + c.setFlag(c.getFlag() & ~6) # dont set top and button caps - curve = c.appendNurb(p1) - curve.append(p2) - curve.append(p3) - curve.append(p4) - for point in curve: - point.handleTypes = [AUTO, AUTO] - curve.flagU = 1 # Set curve cyclic=closed c.update() #remi --todo-----to check--------------------------- - ob = SCENE.objects.new(c) # create a new circle_mesh_object + 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 thic = thic * 0.5 @@ -1899,7 +2228,7 @@ class Circle: #---------------------------------------------------------------- ob.SizeZ *= abs(thic) return ob - elif False: + elif False: # create a new mesh_object with buildin_circle_primitive verts_num = settings.var['arc_res'] * sqrt(radius / settings.var['arc_rad']) if verts_num > 100: verts_num = 100 # Blender accepts only values [3:500] if verts_num < 4: verts_num = 4 # Blender accepts only values [3:500] @@ -1917,17 +2246,15 @@ class Circle: #---------------------------------------------------------------- transform(self.extrusion, 0, ob) return ob - else: + else: # draw CIRCLE as mesh ----------------------------------------------- cir = Mesh.New(obname) # create a new mesh - ob = SCENE.objects.new(cir) # create a new arc_object + ob = SCENE.objects.new(cir) # create a new circle_object # set a number of segments in entire circle arc_res = settings.var['arc_res'] * sqrt(radius) / sqrt(settings.var['arc_rad']) start, end = 0.0 , 360.0 - verts, edges = drawArc(None, radius, start, end, arc_res) - verts = verts[:-2] #list without last point (cause first piont equal) - edges = edges[:-1] - edges[-1][1] = 0 - print 'deb:edges:', edges #remi-todo----- why is this List inhomogene ? ---------- + 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 #--------------- if thic != 0: len1 = len(verts) thic_verts = [] @@ -1938,8 +2265,11 @@ class Circle: #---------------------------------------------------------------- else: verts.extend(thic_verts) faces = [] - faces = [[num, num+1, num+len1+1, num+len1] for num in xrange(len1 - 1)] - faces.append([len1 - 1, 0, len1, len1 + len1 -1]) + f_band = [[num, num+1, num+len1+1, num+len1] for num in xrange(len1 - 1)] + #f_band = [[num, num+1, num+len1+1, num+len1] for num in xrange(len1)] + f_band.append([len1 - 1, 0, len1, len1 + len1 -1]) + faces = f_band + smooth_len = len(f_band) if settings.var['fill_on']: if thic < 0.0: verts.append([0,0,thic]) #center of top side @@ -1949,17 +2279,49 @@ class Circle: #---------------------------------------------------------------- verts.append([0,0,thic]) #center of top side center1 = len(verts)-2 center2 = len(verts)-1 - faces.extend([num+1, num, center1] for num in xrange(len1 - 1)) - faces.append([0, len1 - 1, center1]) - faces.extend([num+len1, num+1+len1, center2] for num in xrange(len1 - 1)) - faces.append([len1-1+len1, 0+len1, center2]) - #print 'deb:verts:', verts #--------------- - #print 'deb:faces:', faces #--------------- + f_bottom = [[num+1, num, center1] for num in xrange(len1 - 1)] + f_bottom.append([0, len1 - 1, center1]) + f_top = [[num+len1, num+1+len1, center2] for num in xrange(len1 - 1)] + f_top.append([len1-1+len1, 0+len1, center2]) + #print 'deb:circleDraw:verts:', verts #--------------- + faces = f_band + f_bottom + f_top + #print 'deb:circleDraw:faces:', faces #--------------- cir.verts.extend(verts) # add vertices to mesh cir.faces.extend(faces) # add faces to the mesh - else: - cir.verts.extend(verts) # add vertices to mesh - cir.edges.extend(edges) # add edges to the mesh + + if settings.var['meshSmooth_on']: # left and right side become smooth ---------------------- + for i in xrange(smooth_len): + cir.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 --------------------- + replace = Blender.Mesh.AssignModes.REPLACE #or .AssignModes.ADD + vg_band, vg_top, vg_bottom = [], [], [] + for v in f_band: vg_band.extend(v) + cir.addVertGroup('side.band') ; cir.assignVertsToGroup('side.band', list(set(vg_band)), 1.0, replace) + if settings.var['fill_on']: + for v in f_top: vg_top.extend(v) + for v in f_bottom: vg_bottom.extend(v) + cir.addVertGroup('side.top') ; cir.assignVertsToGroup('side.top', list(set(vg_top)), 1.0, replace) + cir.addVertGroup('side.bottom'); cir.assignVertsToGroup('side.bottom',list(set(vg_bottom)), 1.0, replace) + + else: # if thic == 0 + if settings.var['fill_on']: + len1 = len(verts) + verts.append([0,0,0]) #center of circle + center1 = len1 + faces = [] + faces.extend([[num, num+1, center1] for num in xrange(len1)]) + faces.append([len1-1, 0, center1]) + #print 'deb:circleDraw:verts:', verts #--------------- + #print 'deb:circleDraw:faces:', faces #--------------- + cir.verts.extend(verts) # add vertices to mesh + cir.faces.extend(faces) # add faces to the mesh + else: + cir.verts.extend(verts) # add vertices to mesh + edges = [[num, num+1] for num in xrange(len(verts))] + edges[-1][1] = 0 # it points the "new" last edge to the first vertex + cir.edges.extend(edges) # add edges to the mesh ob.loc = tuple(self.loc) transform(self.extrusion, 0, ob) @@ -1969,7 +2331,7 @@ class Circle: #---------------------------------------------------------------- class Arc: #----------------------------------------------------------------- - """Class for objects representing dxf arcs. + """Class for objects representing dxf ARCs. """ def __init__(self, obj): @@ -1993,6 +2355,7 @@ class Arc: #----------------------------------------------------------------- self.layer = getit(obj.data, 8, None) self.loc = self.get_loc(obj.data) self.extrusion = get_extrusion(obj.data) + #print 'deb:Arc__init__: center, radius, start, end:\n', self.loc, self.radius, self.start_angle, self.end_angle #--------- @@ -2023,44 +2386,126 @@ class Arc: #----------------------------------------------------------------- radius = self.radius start = self.start_angle end = self.end_angle - #print 'deb:drawArc: center, radius, start, end:\n', center, radius, start, end #--------- + #print 'deb:calcArcPoints:\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['curves_on']: - arc_res = 8 - verts, edges = drawArc(None, radius, start, end, arc_res) + if settings.var['curves_on']: # draw ARC 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(verts[0])) - for p in verts[1:]: + curve = arc.appendNurb(BezTriple.New(VectorTriples[0])) + for p in VectorTriples[1:]: curve.append(BezTriple.New(p)) for point in curve: - point.handleTypes = [AUTO, AUTO] - #print 'deb:arc.draw point=', point #--------------- - curve[0].handleTypes = [FREE, VECT] #remi--todo----- - curve[-1].handleTypes = [VECT, FREE] #remi--todo----- - curve.flagU = 0 # Set curve not cyclic=open - arc.update() + point.handleTypes = [FREE, FREE] + curve.flagU = 0 # 0 sets the curve not cyclic=open + arc.update() #important for handles calculation - #remi --todo-----to check--------------------------- - ob = SCENE.objects.new(arc) # create a new circle_mesh_object + 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 accepts only (0.0 - 2.0) + arc.setExt1(1.0) # curve-extrusion: Blender2.45 accepts only (0.0 - 5.0) ob.LocZ = thic + self.loc[2] transform(self.extrusion, 0, ob) if thic != 0.0: ob.SizeZ *= abs(thic) return ob - else: + else: # draw ARC as mesh -------------------- arc = Mesh.New(obname) # create a new mesh ob = SCENE.objects.new(arc) # create a new arc_object # set a number of segments in entire circle arc_res = settings.var['arc_res'] * sqrt(radius) / sqrt(settings.var['arc_rad']) - verts, edges = drawArc(None, radius, start, end, arc_res) - if thic != 0: - len1 = len(verts) + + verts = calcArc(None, radius, start, end, arc_res, False) + #verts = [list(point) for point in verts] + 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 + + #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 + + arc.verts.extend(verts) # add vertices to mesh + arc.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 + # each MeshSide becomes vertexGroup for easier material assignment --------------------- + 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) + 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) + + + 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 + + elif thic != 0: thic_verts = [] thic_verts.extend([[point[0], point[1], point[2]+thic] for point in verts]) if thic < 0.0: @@ -2070,12 +2515,17 @@ class Arc: #----------------------------------------------------------------- verts.extend(thic_verts) faces = [] #print 'deb:len1:', len1 #----------------------- - #print 'deb:verts:', verts #remi-todo----- why is this List inhomogene ---------- + #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 + if settings.var['meshSmooth_on']: # left and right side become smooth ---------------------- + for i in xrange(len(faces)): + arc.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 @@ -2124,7 +2574,7 @@ class BlockRecord: #----------------------------------------------------------- class Block: #----------------------------------------------------------------- - """Class for objects representing dxf blocks. + """Class for objects representing dxf BLOCKs. """ def __init__(self, obj): @@ -2166,7 +2616,7 @@ class Block: #----------------------------------------------------------------- class Insert: #----------------------------------------------------------------- - """Class for objects representing dxf inserts. + """Class for objects representing dxf INSERTs. """ def __init__(self, obj): @@ -2194,7 +2644,7 @@ class Insert: #---------------------------------------------------------------- def get_loc(self, data): - """Gets the center location for block type objects. + """Gets the origin location of the insert. """ loc = [0, 0, 0] loc[0] = getit(data, 10, 0.0) @@ -2205,7 +2655,7 @@ class Insert: #---------------------------------------------------------------- def get_scale(self, data): - """Gets the x/y/z scale factor for the block. + """Gets the x/y/z scale factors of the insert. """ scale = [1, 1, 1] scale[0] = getit(data, 41, 1.0) @@ -2236,22 +2686,20 @@ class Insert: #---------------------------------------------------------------- Blocks are made of three objects: the block_record in the tables section the block in the blocks section - the insert object in the entities section - - block_records give the insert units, blocks provide the objects drawn in the - block, and the insert object gives the location/scale/rotation of the block - instances. To draw a block you must first get a group with all the - blocks entities drawn in it, then scale the entities to match the world - units, then dupligroup that data to an object matching each insert object. + the insert object (one or more) in the entities section + block_record gives the insert units, + block provides the objects drawn in the block, + insert object gives the location/scale/rotation of the block instances. """ - obname = 'in_%s' %self.blockname # create object name from block name - obname = obname[:MAX_NAMELENGTH] + obname = settings.blocknamesmap[self.blockname] + obname = 'in_%s' %obname # create object name from block name + #obname = obname[:MAX_NAMELENGTH] if settings.drawTypes['insert']: #if insert_drawType activated 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 + 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 @@ -2274,7 +2722,7 @@ class Insert: #---------------------------------------------------------------- class Ellipse: #----------------------------------------------------------------- - """Class for objects representing dxf ellipses. + """Class for objects representing dxf ELLIPSEs. """ def __init__(self, obj): @@ -2354,8 +2802,8 @@ class Ellipse: #--------------------------------------------------------------- # set a number of segments in entire circle arc_res = settings.var['arc_res'] * sqrt(radius) / sqrt(settings.var['arc_rad']) - verts, edges = drawArc(None, radius, start, end, arc_res) - + verts = calcArc(None, radius, start, end, arc_res, False) + #verts = [list(point) for point in verts] if thic != 0: len1 = len(verts) thic_verts = [] @@ -2367,12 +2815,13 @@ class Ellipse: #--------------------------------------------------------------- verts.extend(thic_verts) faces = [] #print 'deb:len1:', len1 #----------------------- - #print 'deb:verts:', verts #remi--todo----- why is this List inhomogene? ---------- + #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 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 @@ -2385,7 +2834,7 @@ class Ellipse: #--------------------------------------------------------------- class Face: #----------------------------------------------------------------- - """Class for objects representing dxf 3d faces. + """Class for objects representing dxf 3DFACEs. """ def __init__(self, obj): @@ -2583,16 +3032,17 @@ class MatColors: #------------------------------------------------------------- """A smart container for dxf-color based materials. This class is a wrapper around a dictionary mapping dxf-color indicies to materials. - When called with a color index it returns a material corrisponding to that index. + When called with a color_index + it returns a material corresponding to that index. Behind the scenes it checks if that index is in its keys, and if not it creates a new material. It then adds the new index:material pair to its dict and returns the material. """ - def __init__(self, map): + def __init__(self, layersmap): """Expects a map - a dictionary mapping layer names to layers. """ - self.map = map # a dictionary of layername:layer + #self.layersmap = layersmap # a dictionary of layername:layerobject self.colMaterials = {} # a dictionary of color_index:blender_material #print 'deb:init_MatColors argument.map: ', map #------------------ @@ -2602,18 +3052,24 @@ class MatColors: #------------------------------------------------------------- If a layer name is provided, the color of that layer is used. """ - if not color: - color = 0 - if type(color) == str: - #print 'deb:color is string:--------------: ', color #--todo---bug with ARC from ARC-T0.DXF layer="T-3DARC-1"----- - try: - color = self.map[color].color + 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 #print 'deb:color=self.map[color].color:', color #------------------ - except KeyError: - layer = Layer(name=color, color=0, frozen=False) - self.map[color] = layer - color = 0 - color = abs(color) + #except KeyError: + #layer = Layer(name=color, color=256, frozen=False) + #self.layersmap[color] = layer + #color = 0 + color = layersmap[color].color + if color == 0: # color 0 = BYBLOCK + #--todo-- should looking for color of paret-BLOCK + #color = layersmap[color].color + pass + 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] @@ -2622,13 +3078,13 @@ class MatColors: #------------------------------------------------------------- def add(self, color): """Create a new material 'ColorNr-N' using the provided color index-N. """ - global color_map + #global color_map #--todo-- has not to be global? mat = Material.New('ColorNr-%s' %color) mat.setRGBCol(color_map[color]) - mat.mode |= Material.Modes.SHADELESS - mat.mode |= Material.Modes.WIRE -# try: mat.setMode('Shadeless', 'Wire') #work-around for 2.45rc-bug -# except: pass + #mat.mode |= Material.Modes.SHADELESS #--todo-- + #mat.mode |= Material.Modes.WIRE +# try: mat.setMode('Shadeless', 'Wire') #work-around for 2.45rc-bug +# except: pass self.colMaterials[color] = mat @@ -2643,41 +3099,48 @@ class MatLayers: #------------------------------------------------------------- the material. """ - def __init__(self, map): + def __init__(self, layersmap): """Expects a map - a dictionary mapping layer names to layers. """ - self.map = map # a dictionary of layername:layer + #self.layersmap = layersmap # a dictionary of layername:layer self.layMaterials = {} # a dictionary of layer_name:blender_material #print 'deb:init_MatLayers argument.map: ', map #------------------ - def __call__(self, layername=None): + def __call__(self, layername=None, color=None): """Return the material associated with dxf-layer. If a dxf-layername is not provided, create a new material """ - if layername not in self.layMaterials.keys(): - self.add(layername) - return self.layMaterials[layername] + #global layernamesmap + layername_short = layername + if layername in layernamesmap.keys(): + layername_short = layernamesmap[layername] + colorlayername = str(color) + layername_short + if colorlayername not in self.layMaterials.keys(): + self.add(layername, color, colorlayername) + return self.layMaterials[colorlayername] - def add(self, layername): + def add(self, layername, color, colorlayername): """Create a new material 'layername'. """ - try: mat = Material.Get('Lay-%s' %layername) - except: mat = Material.New('Lay-%s' %layername) + try: mat = Material.Get('L-%s' %colorlayername) + except: mat = Material.New('L-%s' %colorlayername) #print 'deb:MatLayers material: ', mat #---------- - #print 'deb:MatLayers getMode: ', mat.getMode() #---------- - global layersmap - color = layersmap[layername].color - #print 'deb:MatLayers layer_color: ', color #----------- - global color_map - mat.setRGBCol(color_map[color]) + #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 + 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 -# try: mat.setMode('Shadeless', 'Wire') #work-around for 2.45rc-bug -# except: pass - self.layMaterials[layername] = mat +# try: mat.setMode('Shadeless', 'Wire') #work-around for 2.45rc-bug +# except: pass + self.layMaterials[colorlayername] = mat @@ -2706,7 +3169,7 @@ class Blocks: #---------------------------------------------------------------- If that name is not in its keys, it creates a new data block. If no name is provided return entire self.blocks container. """ - if not name: + if name == None: return self.blocks if name not in self.blocks.keys(): self.addBlock(name) @@ -2716,7 +3179,8 @@ class Blocks: #---------------------------------------------------------------- def addBlock(self, name): """Create a new 'block group' for the block name. """ - block_def = Group.New('bl_%s' %name) # groupObject contains definition of BLOCK + + block_def = Group.New('bl_%s' %name) # Blender groupObject contains definition of BLOCK block = self.blocksmap[name] self.settings.write("\nDrawing block:\'%s\' ..." % name) drawEntities(block.entities, self.settings, block_def) @@ -2784,6 +3248,7 @@ class Settings: #-------------------------------------------------------------- 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'] # First sort out all the section_items sections = dict([(item.name, item) for item in drawing.data]) @@ -2796,8 +3261,11 @@ class Settings: #-------------------------------------------------------------- # The section:tables may be partialy or completely missing. self.layersTable = False - self.colMaterials = MatColors({}) - self.layMaterials = MatLayers({}) + self.colMaterials = MatColors({}) #A container for dxf-color based materials + self.layMaterials = MatLayers({}) #A container for dxf-layer based materials + #self.collayMaterials = MatColLayers({}) #A container for dxf-color+layer based materials + global layersmap, layernamesmap + layersmap, layernamesmap = {}, {} if 'tables' in sections.keys(): self.write("Found section:tables!") # First sort out all the tables @@ -2806,8 +3274,7 @@ class Settings: #-------------------------------------------------------------- self.write("Found table:layers!") self.layersTable = True # Read the layers table and get the layer colors - global layersmap - layersmap = getLayersmap(drawing) + layersmap, layernamesmap = getLayersmap(drawing) self.colMaterials = MatColors(layersmap) self.layMaterials = MatLayers(layersmap) else: @@ -2821,7 +3288,7 @@ class Settings: #-------------------------------------------------------------- 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.obj_number = getBlocksmap(drawing) #Build a dictionary of blockname:block_data pairs + blocksmap, self.blocknamesmap, self.obj_number = getBlocksmap(drawing) #Build a dictionary of blockname:block_data pairs self.blocks = Blocks(blocksmap, self) # initiates container for blocks_data #print 'deb: self.obj_number', self.obj_number #---------- @@ -2863,34 +3330,128 @@ class Settings: #-------------------------------------------------------------- Window.DrawProgressBar(progressbar, text) #print 'deb:drawer done, progressbar: ', done, progressbar #----------------------- - - def layer_isOff(self, name): + def layer_isOff(self, layername): # no more used ------- """Given a layer name, and return its visible status. """ - # colors are negative if layer is off - try: - #print 'deb:layer_isOff self.colMaterials.map:\n', self.colMaterials.map #-------------- - layer = self.colMaterials.map[name] - except KeyError: return False - if layer.color < 0: return True + # if layer is off then color_index is negative + if layersmap[layername].color < 0: return True #print 'deb:layer_isOff: layer is ON' #--------------- return False - def layer_isFrozen(self, name): + def layer_isFrozen(self, layername): # no more used ------- """Given a layer name, and return its frozen status. """ - # colors are negative if layer is off - try: - #print 'deb:layer_isFrozen self.colMaterials.map:\n', self.colMaterials.map #--------------- - layer = self.colMaterials.map[name] - except KeyError: return False - if layer.frozen: return True + if 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 + + """ + Window.WaitCursor(True) # Let the user know we are thinking + print 'start 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) + + # 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!" + else: print "File contains no section:header!" + + # The section:tables may be partialy or completely missing. + layersTable = False + global layersmap + layersmap = {} + if 'tables' in sections.keys(): + print "Found section:tables!" + for table in drawing.tables.data: + if table.name == 'layer': + print "Found table:layers!" + layers = table + break + if layers: + layersmap = {} + 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' + + key_list = layersmap.keys() + key_list.sort() + for key in key_list: + #for layer_name, layer_data in layersmap.iteritems(): + layer_name, layer_data = key, layersmap[key] + layer_str = '\'%s\': col=%s' %(layer_name,layer_data[0])#------------- + if layer_data[1]: layer_str += ', frozen' + layersmap_str += layer_str + '\n' + #print 'deb:analyzeDXF: layersmap_str=\n' , layersmap_str #------------- + else: + print "File contains no table:layers!" + else: + print "File contains no section:tables!" + print "File contains no table:layers!" + + # The section:blocks may be omited + if 'blocks' in sections.keys(): + 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 = [] + 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:analyzeDXF: blocksmap=' , blocksmap #------------- + blocksmap_str = '#list of BLOCKs: child, 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 + if block_data: + for block_item in block_data: + block_data_str = ' - %s\n' %block_item + blocksmap_str += block_data_str + #print 'deb:analyzeDXF: blocksmap_str=\n' , blocksmap_str #------------- + else: + 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' + try: + f = file(infFile, 'w') + f.write(INFFILE_HEADER + '\n# this is a comment line\n') + f.write(output_str) + f.close() + Draw.PupMenu('DXF importer: INF-file: Done!%t|see listing of DXF-model saved in:|' + '\'%s\'' %infFile) + except: + Draw.PupMenu('DXF importer: INF-file: Error!%t|failure by writing to ' + '\'%s\'|no listings saved!' %infFile) + + + + def main(dxfFile): #---------------#############################----------- #print 'deb:filename:', filename #-------------- @@ -2909,7 +3470,13 @@ def main(dxfFile): #---------------#############################----------- print "Getting settings..." global GUI_A, GUI_B if GUI_A['g_scale_on'].val: - GUI_A['g_scale'].val = 10.0 ** int(GUI_A['g_scale_as'].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: GUI_A['g_scale'].val = 1.0 @@ -2928,7 +3495,8 @@ def main(dxfFile): #---------------#############################----------- if not settings: #Draw.PupMenu('DXF importer: EXIT!%t') - print '\nDXF Import: terminated by user!' + #print '\nDXF Import: terminated by user!' + print '\nDXF Import: terminated, cause settings failure!' Window.WaitCursor(False) if editmode: Window.EditMode(1) # and put things back how we fond them return None @@ -2993,8 +3561,14 @@ 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: - return False + if az[0] == 0 and az[1] == 0: + if az[2] == 1.0: + return False + elif az[2] == -1.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 @@ -3052,7 +3626,7 @@ def rotXY_Vec(rotation, vec): #------------------------------------------------ def getLayersmap(drawing): #------------------------------------------------------ - """Build a dictionary of layername:layer pairs for the given drawing. + """Build two dictionaries: 1.layername:layer pairs and 2.layername:layername_short """ tables = drawing.tables for table in tables.data: @@ -3060,17 +3634,27 @@ def getLayersmap(drawing): #--------------------------------------------------- layers = table break layersmap = {} + layernamesmap = {} for item in layers.data: if type(item) != list and item.type == 'layer': layersmap[item.name] = item - return layersmap + layername_short = item.name[:MAX_NAMELENGTH-1] + i = 0 #sufix for layernames cause Blender-objectnames-limits + while layername_short in layernamesmap.keys(): + i += 1 + suffix = str(i) + layername_short = layername_short[:-2] + suffix + layernamesmap[item.name] = layername_short + return layersmap, layernamesmap def getBlocksmap(drawing): #-------------------------------------------------------- - """Build a dictionary of blockname:block_data pairs for the given drawing. + """Build a dictionary of blockname:block_data pairs and 2.blockname:blockname_short pairs """ blocksmap = {} + blocksmap_short = {} + blocknamesmap = {} obj_number = 0 for item in drawing.blocks.data: #print 'deb:getBlocksmap item=' ,item #-------- @@ -3083,9 +3667,16 @@ def getBlocksmap(drawing): #--------------------------------------------------- except KeyError: # annon block print 'Cannot map "%s" - "%s" as Block!' %(item.name, item) - return blocksmap, obj_number + 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 + return blocksmap, blocknamesmap, obj_number @@ -3105,6 +3696,8 @@ def drawer(_type, entities, settings, block_def): #---------------------------- If 'block_def': the entities are to be added to the Blender 'group'. """ + #print 'deb:drawer _type, entities:\n ', _type, entities #----------------------- + if entities: # Break out early if settings says we aren't drawing the current dxf-type global cur_COUNTER #counter for progress_bar @@ -3118,10 +3711,14 @@ def drawer(_type, entities, settings, block_def): #---------------------------- settings.progress(cur_COUNTER, message) return #print 'deb:drawer.todo:_type:', _type #----------------------- + #print 'deb:drawer entities:\n ', entities #----------------------- len_temp = len(entities) # filtering only model-space enitities (no paper-space enitities) - entities = [entity for entity in entities if entity.space == 0] + if settings.var['paper_space_on']: + entities = [entity for entity in entities if entity.space != 0] + else: + entities = [entity for entity in entities if entity.space == 0] # filtering only objects with color from acceptedColorsList if settings.var['colorFilter_on']: @@ -3129,11 +3726,12 @@ def drawer(_type, entities, settings, block_def): #---------------------------- # filtering only objects on layers from acceptedLayersList if settings.var['layerFilter_on']: -# entities = [entity for entity in entities if entity.layer[0] in ['M','3','0'] and not entity.layer.endswith('H')] + #entities = [entity for entity in entities if entity.layer[0] in ['M','3','0'] and not entity.layer.endswith('H')] entities = [entity for entity in entities if entity.layer in settings.acceptedLayers] # filtering only objects on not-frozen layers - entities = [entity for entity in entities if not settings.layer_isFrozen(entity.layer)] + if layersmap and not settings.var['layFrozen_on']: + entities = [entity for entity in entities if not layersmap[entity.layer].frozen] global activObjectLayer, activObjectName activObjectLayer = '' @@ -3162,7 +3760,7 @@ def drawer(_type, entities, settings, block_def): #---------------------------- # 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' % entity.layer[:MAX_NAMELENGTH-2]) + group = getGroup('l:%s' % layernamesmap[entity.layer]) if _type == 'insert': #---- INSERT and MINSERT=array ------------------------ #print 'deb:insert entity.loc:', entity.loc #---------------- @@ -3249,7 +3847,8 @@ def setObjectProperties(ob, group, entity, settings, block_def): #------------- setMaterial_from(entity, ob, settings, block_def) # Set the visibility - if settings.layer_isOff(entity.layer): + #if settings.layer_isOff(entity.layer): + if layersmap and layersmap[entity.layer].color < 0: # color is negative if layer is off #ob.layers = [20] #remi--todo------------- ob.restrictDisplay = True ob.restrictRender = True @@ -3287,17 +3886,25 @@ def setMaterial_from(entity, ob, settings, block_def): #----------------------- if settings.var['material_from'] == 1: # 1= material from color if entity.color_index == BYLAYER: mat = settings.colMaterials(entity.layer) + elif entity.color_index == BYBLOCK: + #--todo-- looking for block.color_index + #mat = settings.colMaterials(block.color_index) + mat = settings.colMaterials(entity.color_index) else: mat = settings.colMaterials(entity.color_index) - elif settings.var['material_from'] == 2: # 2= material from layer - mat = settings.layMaterials(entity.layer) -# elif settings.var['material_from'] == 3: # 3= material from layer+color -# mat = settings.layMaterials(entity.layer) -# color = entity.color_index -# if type(color) == int: -# mat.setRGBCol(color_map[abs(color)]) -# elif settings.var['material_from'] == 4: # 4= material from block -# elif settings.var['material_from'] == 5: # 5= material from INI-file + + elif settings.var['material_from'] == 2: # 2= material from layer_name + 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) + +# elif settings.var['material_from'] == 4: # 4= material from block_name + +# elif settings.var['material_from'] == 5: # 5= material from XDATA + +# elif settings.var['material_from'] == 6: # 6= material from INI-file + else: # set neutral material try: mat = Material.Get('dxf-neutral') @@ -3316,8 +3923,8 @@ def setMaterial_from(entity, ob, settings, block_def): #----------------------- -def drawBulge(p1, p2, arc_res, curve_on=False): #------------------------------------------------- - """return the center, radius, start angle, and end angle given two points. +def calcBulge(p1, p2, arc_res, triples=False): #------------------------------------------------- + """given startpoint, endpoint and bulge of arc, returns points/segments of its representation. Needs to take into account bulge sign. negative = clockwise @@ -3335,54 +3942,114 @@ def drawBulge(p1, p2, arc_res, curve_on=False): #----------------------------- rotate around p1 by angle to center, point to center. start angle = angle between (center - p1) and worldX end angle = angle between (center - p2) and worldX + + calculate the center, radius, start angle, and end angle + returns points/segments of its mesh representation + incl.startpoint, without endpoint """ bulge = p1.bulge - p2 = Mathutils.Vector(p2.loc) p1 = Mathutils.Vector(p1.loc) + p2 = Mathutils.Vector(p2.loc) cord = p2 - p1 # vector from p1 to p2 clength = cord.length s = (bulge * clength)/2.0 # sagitta (height) radius = abs(((clength/2.0)**2.0 + s**2.0)/(2.0*s)) # magic formula angle = (degrees(4.0*atan(bulge))) # theta (included angle) - if curve_on: - verts_num = 8 - else: - verts_num = arc_res * sqrt(radius) # set a number of segments in entire circle - if verts_num > 1024: verts_num = 1024 # Blender accepts only values [3:500] - if verts_num < 4: verts_num = 4 # Blender accepts only values [3:500] - pieces = int(abs(angle)/(360.0/verts_num)) - if pieces < 3: pieces = 3 #bulge under arc_resolution - #if pieces < 3: points = [p1, p2] ;return points - step = angle/pieces # set step so pieces * step = degrees in arc + radial = cord.normalize() * radius # a radius length vector aligned with cord delta = (180.0 - abs(angle))/2.0 # the angle from cord to center if bulge < 0: delta = -delta - radial = cord.normalize() * radius # a radius length vector aligned with cord rmat = Mathutils.RotationMatrix(-delta, 3, 'Z') center = p1 + (rmat * radial) # rotate radial by delta degrees, then add to p1 to find center #length = radians(abs(angle)) * radius - #print 'deb:drawBulge:\n angle, delta: ', angle, delta #---------------- + #print 'deb:calcBulge:\n angle, delta: ', angle, delta #---------------- #print 'deb:center, radius: ', center, radius #---------------------- - startpoint = p1 - center - #endpoint = p2 - center + endpoint = p2 - center + #print 'deb:calcBulg: startpoint:', startpoint #--------- + #print 'deb:calcBulg: endpoint:', endpoint #--------- + + if not triples: #IF mesh-representation ----------- + if arc_res > 1024: arc_res = 1024 + elif arc_res < 4: arc_res = 4 + pieces = int(abs(angle)/(360.0/arc_res)) # set a fixed step of ARC_RESOLUTION + if pieces < 3: pieces = 3 + else: #IF curve-representation ------------------------------- + if arc_res > 32: arc_res = 32 + elif arc_res < 3: arc_res = 3 + pieces = int(abs(angle)/(360.0/arc_res)) # set a fixed step of ARC_RESOLUTION + if pieces < 2: pieces = 2 + + step = angle/pieces # set step so pieces * step = degrees in arc stepmatrix = Mathutils.RotationMatrix(-step, 3, "Z") - points = [startpoint] - point = Mathutils.Vector(startpoint) - for i in xrange(int(pieces)-1): #fast (but not so acurate as: vector * RotMatrix(step * i) - point = stepmatrix * point - points.append(point) - points = [[point[0]+center[0], point[1]+center[1], point[2]+center[2]] for point in points] - return points + + if not triples: #IF mesh-representation ----------- + points = [startpoint] + point = startpoint + for i in xrange(int(pieces)-1): #fast (but not so acurate as: vector * RotMatrix(-step*i,3,"Z") + point = stepmatrix * point + points.append(point) + points = [ point+center for point in points] + # vector to point convertion: + points = [list(point) for point in points] + return points, list(center) + + else: #IF curve-representation ------------------------------- + # correct Bezier curves representation for free segmented circles/arcs + step2 = radians(step * 0.5) + bulg = radius * (1 - cos(step2)) + deltaY = 4.0 * bulg / (3.0 * sin(step2) ) + #print 'deb:calcArcCurve: bulg, deltaY:\n', bulg, deltaY #--------- + #print 'deb:calcArcCurve: step:\n', step #--------- + + #org handler0 = Mathutils.Vector(0.0, -deltaY, 0.0) + #handler = startmatrix * handler0 + #endhandler = endmatrix * handler0 + rotMatr90 = Mathutils.Matrix([0, -1, 0], [1, 0, 0], [0, 0, 1]) + handler = rotMatr90 * startpoint + handler = - deltaY * handler.normalize() + endhandler = rotMatr90 * endpoint + endhandler = - deltaY * endhandler.normalize() + + points = [startpoint] + handlers1 = [startpoint + handler] + handlers2 = [startpoint - handler] + point = Mathutils.Vector(startpoint) + for i in xrange(int(pieces)-1): + point = stepmatrix * point + handler = stepmatrix * handler + handler1 = point + handler + handler2 = point - handler + points.append(point) + handlers1.append(handler1) + handlers2.append(handler2) + points.append(endpoint) + handlers1.append(endpoint + endhandler) + handlers2.append(endpoint - endhandler) + + points = [point + center for point in points] + handlers1 = [point + center for point in handlers1] + handlers2 = [point + center for point in handlers2] + + VectorTriples = [list(h1)+list(p)+list(h2) for h1,p,h2 in zip(handlers1, points, handlers2)] + #print 'deb:calcBulgCurve: handlers1:\n', handlers1 #--------- + #print 'deb:calcBulgCurve: points:\n', points #--------- + #print 'deb:calcBulgCurve: handlers2:\n', handlers2 #--------- + #print 'deb:calcBulgCurve: VectorTriples:\n', VectorTriples #--------- + return VectorTriples + -def drawArc(center, radius, start, end, arc_res): #----------------------------------------- - """Draw a mesh arc with the given parameters. +def calcArc(center, radius, start, end, arc_res, triples): #----------------------------------------- + """calculate Points (or BezierTriples) for ARC/CIRCLEs representation. + + Given parameters of the ARC/CIRCLE, + returns points/segments (or BezierTriples) and centerPoint """ # center is currently set by object # if start > end: start = start - 360 - if end > 360: end = end%360.0 + if end > 360: end = end % 360.0 startmatrix = Mathutils.RotationMatrix(-start, 3, "Z") startpoint = startmatrix * Mathutils.Vector(radius, 0, 0) @@ -3393,27 +4060,68 @@ def drawArc(center, radius, start, end, arc_res): #---------------------------- angle = end - start #length = radians(angle) * radius - #if radius < MIN_DIST * 10: # if circumfence is too small - if arc_res > 1024: arc_res = 1024 - if arc_res < 4: arc_res = 4 - pieces = int(abs(angle)/(360.0/arc_res)) # set a fixed step of ARC_RESOLUTION - if pieces < 3: pieces = 3 #cambo----- - step = angle/pieces # set step so pieces * step = degrees in arc + if not triples: #IF mesh-representation ----------- + if arc_res > 1024: arc_res = 1024 + elif arc_res < 4: arc_res = 4 + pieces = int(abs(angle)/(360.0/arc_res)) # set a fixed step of ARC_RESOLUTION + if pieces < 3: pieces = 3 + step = angle/pieces # set step so pieces * step = degrees in arc + stepmatrix = Mathutils.RotationMatrix(-step, 3, "Z") - stepmatrix = Mathutils.RotationMatrix(-step, 3, "Z") - points = [startpoint] - point = Mathutils.Vector(startpoint) - for i in xrange(int(pieces)): - point = stepmatrix * point - points.append(point) - points.append(endpoint) + points = [startpoint] + point = startpoint + for i in xrange(int(pieces)-1): + point = stepmatrix * point + points.append(point) + points.append(endpoint) + + if center: + centerVec = Mathutils.Vector(center) + #points = [point + centerVec for point in points()] + points = [point + centerVec for point in points] + # vector to point convertion: + points = [list(point) for point in points] + return points - if center: - points = [[point[0]+center[0], point[1]+center[1], point[2]+center[2]] for point in points] - edges = [[num, num+1] for num in xrange(len(points)-1)] - - return points, edges + else: #IF curve-representation --------------- + if arc_res > 32: arc_res = 32 + elif arc_res < 3: arc_res = 3 + pieces = int(abs(angle)/(360.0/arc_res)) # set a fixed step of ARC_RESOLUTION + if pieces < 2: pieces = 2 + step = angle/pieces # set step so pieces * step = degrees in arc + stepmatrix = Mathutils.RotationMatrix(-step, 3, "Z") + # correct Bezier curves representation for free segmented circles/arcs + step2 = radians(step * 0.5) + bulg = radius * (1 - cos(step2)) + deltaY = 4.0 * bulg / (3.0 * sin(step2) ) + #print 'deb:calcArcCurve: bulg, deltaY:\n', bulg, deltaY #--------- + #print 'deb:calcArcCurve: step:\n', step #--------- + handler0 = Mathutils.Vector(0.0, -deltaY, 0.0) + + points = [startpoint] + handler = startmatrix * handler0 + endhandler = endmatrix * handler0 + handlers1 = [startpoint + handler] + handlers2 = [startpoint - handler] + point = Mathutils.Vector(startpoint) + for i in xrange(int(pieces)-1): + point = stepmatrix * point + handler = stepmatrix * handler + handler1 = point + handler + handler2 = point - handler + points.append(point) + handlers1.append(handler1) + handlers2.append(handler2) + points.append(endpoint) + handlers1.append(endpoint + endhandler) + handlers2.append(endpoint - endhandler) + VectorTriples = [list(h1)+list(p)+list(h2) for h1,p,h2 in zip(handlers1, points, handlers2)] + #print 'deb:calcArcCurve: handlers1:\n', handlers1 #--------- + #print 'deb:calcArcCurve: points:\n', points #--------- + #print 'deb:calcArcCurve: handlers2:\n', handlers2 #--------- + #print 'deb:calcArcCurve: VectorTriples:\n', VectorTriples #--------- + return VectorTriples def drawCurveCircle(circle): #--- no more used -------------------------------------------- @@ -3504,6 +4212,7 @@ EVENT_HELP = 9 EVENT_CONFIG = 10 EVENT_PRESETS = 11 EVENT_DXF_DIR = 12 +EVENT_LIST = 13 EVENT_PRESET2D = 20 EVENT_EXIT = 100 GUI_EVENT = EVENT_NONE @@ -3522,8 +4231,8 @@ 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" -material_from_menu= "material from: %t|COLOR %x1|LAYER %x2|*LAYER+COLOR %x3|*BLOCK %x4|*XDATA %x5|*INI-File %x6" -g_scale_list = "scale factor: %t|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" +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" dxfFileName = Draw.Create("") iniFileName = Draw.Create(INIFILE_DEFAULT_NAME + INIFILE_EXTENSION) @@ -3555,11 +4264,18 @@ keywords_org = { 'material_from': 2, 'pl_3d' : 1, 'fill_on' : 1, + 'meshSmooth_on': 1, + 'curve_res' : CURV_RESOLUTION, + 'curve_arc' : CURVARC_RESOLUTION, 'arc_res' : ARC_RESOLUTION, 'arc_rad' : ARC_RADIUS, 'thin_res' : THIN_RESOLUTION, - 'angle_cut' : ANGLECUT_LIMIT, - 'pl_section_on': 1, + 'pl_trim_max' : TRIM_LIMIT, + 'pl_trim_on': 1, + 'paper_space_on': 0, + 'layFrozen_on': 0, + 'Z_force_on': 0, + 'Z_elev': float(ELEVATION), 'points_as' : 2, 'lines_as' : 2, 'mlines_as' : 2, @@ -3615,8 +4331,8 @@ def saveConfig(): #remi--todo----------------------------------------------- iniFile = iniFileName.val #print 'deb:saveConfig inifFile: ', inifFile #---------------------- if iniFile.lower().endswith(INIFILE_EXTENSION): - output = '[%s,%s]' %(GUI_A, GUI_B) - if output =='None': + 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 @@ -3632,10 +4348,16 @@ def saveConfig(): #remi--todo----------------------------------------------- else: save_ok = True if save_ok: + # replace: ',' -> ',\n' + # replace: '{' -> '\n{\n' + # replace: '}' -> '\n}\n' + output_str = ',\n'.join(output_str.split(',')) + output_str = '\n}'.join(output_str.split('}')) + output_str = '{\n'.join(output_str.split('{')) try: f = file(iniFile, 'w') - f.write(INIFILE_HEADER + '\n') - f.write(output) + 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) except: @@ -3668,7 +4390,7 @@ def loadConfig(): #remi--todo----------------------------------------------- else: data_str = f.read() f.close() - #print 'deb:loadConfig data_str from %s: \n' %iniFile , data_str #-------------------------- + print 'deb:loadConfig data_str from %s: \n' %iniFile , data_str #-------------------------- data = eval(data_str) for k, v in data[0].iteritems(): try: @@ -3719,7 +4441,9 @@ def resetDefaultConfig_2D(): #----------------------------------------------- 'dist_force': 0, 'pl_3d' : 0, 'fill_on' : 0, - 'pl_section_on': 1, + 'pl_trim_on': 1, + 'Z_force_on': 0, + 'meshSmooth_on': 0, 'points_as' : 2, 'lines_as' : 2, 'mlines_as' : 2, @@ -3772,7 +4496,7 @@ def draw_UI(): #--------------------------------------------------------------- menu_w = (3 * butt_margin) + but_0c + but_1c + but_2c + but_3c #menu width simple_menu_h = 110 - extend_menu_h = 380 + extend_menu_h = 400 y = simple_menu_h # y is menu upper.y if config_UI.val: y += extend_menu_h x = 20 #menu left.x @@ -3848,7 +4572,8 @@ def draw_UI(): #--------------------------------------------------------------- y -= 20 Draw.BeginAlign() - GUI_B['block'] = Draw.Toggle('BLOCK / ARRAY', EVENT_NONE, but0c, y, but_0c+but_1c, 20, GUI_B['block'].val, "support dxf-BLOCK and ARRAY on/off") + 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() @@ -3856,35 +4581,55 @@ def draw_UI(): #--------------------------------------------------------------- y -= 20 Draw.BeginAlign() - GUI_A['material_from'] = Draw.Menu(material_from_menu, EVENT_NONE, but0c, y, but_0c+but_1c, 20, GUI_A['material_from'].val, "material assignment from?") - Draw.Label('-->', but2c, y, but_2c, 20) - GUI_A['material_on'] = Draw.Toggle('material', EVENT_NONE, but3c, y, but_3c, 20, GUI_A['material_on'].val, "support for material assignment on/off") + 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 -= 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['curves_on'] = Draw.Toggle('to Curves', EVENT_NONE, but1c, y, but_1c, 20, GUI_A['curves_on'].val, "drawing LINE/ARC/POLYLINE into Blender-Curves instead of Meshes on/off") + 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['dummy_on'] = Draw.Toggle('-', EVENT_NONE, but3c, y, but_3c, 20, GUI_A['dummy_on'].val, "dummy on/off") + Draw.EndAlign() 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") Draw.EndAlign() - y -= 20 - #Draw.Label('', but1c+but_1c/2, y, but_1c/2, 20) - GUI_A['one_mesh_on'] = Draw.Toggle('oneMesh', EVENT_NONE, but0c, y, but_0c, 20, GUI_A['one_mesh_on'].val, "drawing DXF-entities into one mesh-object. Recommended for big DXF-files. on/off") + 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") 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)") + 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") + Draw.EndAlign() + 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 lenght/distance (double.vertex removing)") + 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)") Draw.EndAlign() y -= 20 Draw.BeginAlign() - GUI_A['pl_section_on'] = Draw.Toggle('int.section', EVENT_NONE, but0c, y, but_0c, 20, GUI_A['pl_section_on'].val, "support POLYLINE-wide-segment-intersection on/off") - GUI_A['angle_cut'] = Draw.Number('', EVENT_NONE, but1c, y, but_1c, 20, GUI_A['angle_cut'].val, 1, 5, "it limits POLYLINE-wide-segment-intersection: 1.0-5.0") +# 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") 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") @@ -3895,10 +4640,10 @@ def draw_UI(): #--------------------------------------------------------------- y -= 20 Draw.BeginAlign() -# GUI_A['thin_res'] = Draw.Number('thin:', EVENT_NONE, but0c, y, but_0c, 20, GUI_A['thin_res'].val, 4, 500, "thin cylinder resolution - number of segments") - GUI_A['arc_rad'] = Draw.Number('radi:', EVENT_NONE, but0c, y, but_0c, 20, GUI_A['arc_rad'].val, 0.01, 100, "basis radius for arc/circle resolution") - GUI_A['arc_res'] = Draw.Number('res:', EVENT_NONE, but1c, y, but_1c-25, 20, GUI_A['arc_res'].val, 4, 500, "arc/circle resolution - number of segments") - GUI_A['fill_on'] = Draw.Toggle('cap', EVENT_NONE, but1c+but_1c-25, y, 25, 20, GUI_A['fill_on'].val, "draws top and bottom caps of CYLINDERs on/off") + #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") Draw.EndAlign() 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") @@ -3908,6 +4653,7 @@ def draw_UI(): #--------------------------------------------------------------- y -= 30 #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") @@ -3940,7 +4686,8 @@ def draw_UI(): #--------------------------------------------------------------- y -= 50 Draw.BeginAlign() Draw.PushButton('EXIT', EVENT_EXIT, but0c, y, but_0c, 40, '' ) - Draw.PushButton('HELP', EVENT_HELP, but1c, y, but_1c, 20, 'calls BlenderWiki for Manual, Updates and Support.') + 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('START IMPORT', EVENT_START, but2c, y, but_2c+but_3c+butt_margin, 40, 'Start the import procedure') Draw.EndAlign() @@ -3993,6 +4740,14 @@ def bevent(evt): if user_preset > 5: user_preset = 1 iniFileName.val = INIFILE_DEFAULT_NAME + str(user_preset) + INIFILE_EXTENSION Draw.Redraw() + elif (evt==EVENT_LIST): + dxfFile = dxfFileName.val + if dxfFile.lower().endswith('.dxf') and sys.exists(dxfFile): + analyzeDXF(dxfFile) + else: + Draw.PupMenu('DXF importer: Alert!%t|no valid DXF-file selected!') + print "DXF importer: error, no valid DXF-file selected! try again" + Draw.Redraw() elif (evt==EVENT_HELP): try: import webbrowser @@ -4032,6 +4787,7 @@ http://wiki.blender.org/index.php?title=Scripts/Manual/Import/DXF-3D') else: Draw.Redraw() elif dxfFile.lower().endswith('.dxf') and sys.exists(dxfFile): + print '\nStandard Mode: active' if GUI_A['newScene_on'].val: _dxf_file = dxfFile.split('/')[-1].split('\\')[-1] _dxf_file = _dxf_file[:-4] # cut last char:'.dxf' @@ -4066,7 +4822,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 'Searching for DXF-files in %s' %DIR + print 'Multifile Mode: searching for DXF-files in %s' %DIR files = \ [sys.join(DIR, f) for f in os.listdir(DIR) if f.lower().endswith('.dxf')] if not files: @@ -4076,7 +4832,7 @@ def multi_import(DIR): i = 0 for dxfFile in files: i += 1 - print 'Importing', dxfFile, ' NUMBER', i, 'of', len(files) + print '\nImporting', dxfFile, ' NUMBER', i, 'of', len(files) if GUI_A['newScene_on'].val: _dxf_file = dxfFile.split('/')[-1].split('\\')[-1] _dxf_file = _dxf_file[:-4] # cut last char:'.dxf' @@ -4136,4 +4892,4 @@ if 1: main(_dxf) print 'TOTAL TIME: %.6f' % (Blender.sys.time() - TIME) -""" \ No newline at end of file +""" diff --git a/release/scripts/mesh_skin.py b/release/scripts/mesh_skin.py index fdb721bc9f3..a554e128b41 100644 --- a/release/scripts/mesh_skin.py +++ b/release/scripts/mesh_skin.py @@ -628,7 +628,7 @@ def main(): try: me.faces.delete(1, [ f for f in me.faces if f.sel ]) except: pass - me.faces.extend(faces) + me.faces.extend(faces, smooth = True) print '\nSkin done in %.4f sec.' % (Blender.sys.time()-time1) diff --git a/release/scripts/mesh_wire.py b/release/scripts/mesh_wire.py index 35cfa325497..bd38c47a9b9 100644 --- a/release/scripts/mesh_wire.py +++ b/release/scripts/mesh_wire.py @@ -44,6 +44,7 @@ from BPyMathutils import angleToLength import mesh_solidify import BPyMessages +reload(BPyMessages) import bpy @@ -219,9 +220,7 @@ def solid_wire(ob_orig, me_orig, sce, PREF_THICKNESS, PREF_SOLID, PREF_SHARP, PR for ii in vusers: co += me.verts[ii].co co /= len(vusers) - - - + me.faces.delete(1, range(len(me.faces))) me.faces.extend(new_faces) @@ -245,6 +244,18 @@ def main(): BPyMessages.Error_NoMeshActive() return + # Saves the editmode state and go's out of + # editmode if its enabled, we cant make + # changes to the mesh data while in editmode. + is_editmode = Window.EditMode() + Window.EditMode(0) + + me = ob_act.getData(mesh=1) # old NMesh api is default + if len(me.faces)==0: + BPyMessages.Error_NoMeshFaces() + if is_editmode: Window.EditMode(1) + return + # Create the variables. PREF_THICK = Blender.Draw.Create(0.005) PREF_SOLID = Blender.Draw.Create(1) @@ -259,16 +270,10 @@ def main(): ] if not Blender.Draw.PupBlock('Solid Wireframe', pup_block): + if is_editmode: Window.EditMode(1) return - # Saves the editmode state and go's out of - # editmode if its enabled, we cant make - # changes to the mesh data while in editmode. - is_editmode = Window.EditMode() - Window.EditMode(0) - Window.WaitCursor(1) - me = ob_act.getData(mesh=1) # old NMesh api is default t = sys.time() # Run the mesh editing function @@ -282,4 +287,4 @@ def main(): # This lets you can import the script without running it if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/release/scripts/weightpaint_average.py b/release/scripts/weightpaint_average.py index 57c27605da5..4e8830256b2 100644 --- a/release/scripts/weightpaint_average.py +++ b/release/scripts/weightpaint_average.py @@ -103,7 +103,6 @@ def main(): if PREF_ALL_VGROUPS==-1: return - print "sd", PREF_ALL_VGROUPS Window.WaitCursor(1) me = ob_act.getData(mesh=1) # old NMesh api is default t = sys.time() diff --git a/source/blender/blenkernel/BKE_lattice.h b/source/blender/blenkernel/BKE_lattice.h index 3dc4b49b52b..bf505fa23d7 100644 --- a/source/blender/blenkernel/BKE_lattice.h +++ b/source/blender/blenkernel/BKE_lattice.h @@ -64,8 +64,8 @@ void lattice_deform_verts(struct Object *laOb, struct Object *target, int numVerts, char *vgroup); void armature_deform_verts(struct Object *armOb, struct Object *target, struct DerivedMesh *dm, float (*vertexCos)[3], - float (*defMats)[3][3], int numVerts, - int deformflag, const char *defgrp_name); + float (*defMats)[3][3], int numVerts, int deformflag, + float (*prevCos)[3], const char *defgrp_name); float (*lattice_getVertexCos(struct Object *ob, int *numVerts_r))[3]; void lattice_applyVertexCos(struct Object *ob, float (*vertexCos)[3]); void lattice_calc_modifiers(struct Object *ob); diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index f688c573bc8..59786afd999 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -790,7 +790,8 @@ static void pchan_bone_deform(bPoseChannel *pchan, float weight, float *vec, Dua void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm, float (*vertexCos)[3], float (*defMats)[3][3], - int numVerts, int deformflag, const char *defgrp_name) + int numVerts, int deformflag, + float (*prevCos)[3], const char *defgrp_name) { bPoseChannel *pchan, **defnrToPC = NULL; MDeformVert *dverts = NULL; @@ -800,6 +801,7 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm, int use_envelope = deformflag & ARM_DEF_ENVELOPE; int use_quaternion = deformflag & ARM_DEF_QUATERNION; int bbone_rest_def = deformflag & ARM_DEF_B_BONE_REST; + int invert_vgroup= deformflag & ARM_DEF_INVERT_VGROUP; int numGroups = 0; /* safety for vertexgroup index overflow */ int i, target_totvert = 0; /* safety for vertexgroup overflow */ int use_dverts = 0; @@ -881,11 +883,12 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm, for(i = 0; i < numVerts; i++) { MDeformVert *dvert; DualQuat sumdq, *dq = NULL; - float *co = vertexCos[i], dco[3]; + float *co, dco[3]; float sumvec[3], summat[3][3]; float *vec = NULL, (*smat)[3] = NULL; float contrib = 0.0f; - float armature_weight = 1.0f; /* default to 1 if no overall def group */ + float armature_weight = 1.0f; /* default to 1 if no overall def group */ + float prevco_weight = 1.0f; /* weight for optional cached vertexcos */ int j; if(use_quaternion) { @@ -917,11 +920,22 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm, break; } } + /* hackish: the blending factor can be used for blending with prevCos too */ + if(prevCos) { + if(invert_vgroup) + prevco_weight= 1.0f-armature_weight; + else + prevco_weight= armature_weight; + armature_weight= 1.0f; + } } /* check if there's any point in calculating for this vert */ if(armature_weight == 0.0f) continue; + /* get the coord we work on */ + co= prevCos?prevCos[i]:vertexCos[i]; + /* Apply the object's matrix */ Mat4MulVecfl(premat, co); @@ -1005,6 +1019,15 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm, /* always, check above code */ Mat4MulVecfl(postmat, co); + + + /* interpolate with previous modifier position using weight group */ + if(prevCos) { + float mw= 1.0f - prevco_weight; + vertexCos[i][0]= prevco_weight*vertexCos[i][0] + mw*co[0]; + vertexCos[i][1]= prevco_weight*vertexCos[i][1] + mw*co[1]; + vertexCos[i][2]= prevco_weight*vertexCos[i][2] + mw*co[2]; + } } if(dualquats) MEM_freeN(dualquats); @@ -1865,12 +1888,42 @@ static void where_is_ik_bone(bPoseChannel *pchan, float ik_mat[][3]) // nr = t static void do_strip_modifiers(Object *armob, Bone *bone, bPoseChannel *pchan) { bActionModifier *amod; - bActionStrip *strip; + bActionStrip *strip, *strip2; float scene_cfra= G.scene->r.cfra; + int do_modif; for (strip=armob->nlastrips.first; strip; strip=strip->next) { - if(scene_cfra>=strip->start && scene_cfra<=strip->end) { + do_modif=0; + + if (scene_cfra>=strip->start && scene_cfra<=strip->end) + do_modif=1; + + if ((scene_cfra > strip->end) && (strip->flag & ACTSTRIP_HOLDLASTFRAME)) { + do_modif=1; + /* if there are any other strips active, ignore modifiers for this strip - + * 'hold' option should only hold action modifiers if there are + * no other active strips */ + for (strip2=strip->next; strip2; strip2=strip2->next) { + if (strip2 == strip) continue; + + if (scene_cfra>=strip2->start && scene_cfra<=strip2->end) { + if (!(strip2->flag & ACTSTRIP_MUTE)) + do_modif=0; + } + } + + /* if there are any later, activated, strips with 'hold' set, they take precedence, + * so ignore modifiers for this strip */ + for (strip2=strip->next; strip2; strip2=strip2->next) { + if (scene_cfra < strip2->start) continue; + if ((strip2->flag & ACTSTRIP_HOLDLASTFRAME) && !(strip2->flag & ACTSTRIP_MUTE)) { + do_modif=0; + } + } + } + + if (do_modif) { /* temporal solution to prevent 2 strips accumulating */ if(scene_cfra==strip->end && strip->next && strip->next->start==scene_cfra) continue; diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c index 8da3ea0b994..234a096edce 100644 --- a/source/blender/blenkernel/intern/key.c +++ b/source/blender/blenkernel/intern/key.c @@ -680,11 +680,15 @@ static void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, i /* only with value, and no difference allowed */ if(icuval!=0.0f && kb->totelem==tot) { + KeyBlock *refb; float weight, *weights= kb->weights; poin= basispoin; - reffrom= key->refkey->data; from= kb->data; + /* reference now can be any block */ + refb= BLI_findlink(&key->block, kb->relative); + if(refb==NULL) continue; + reffrom= refb->data; poin+= start*ofs[0]; reffrom+= key->elemsize*start; // key elemsize yes! diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index a07e53a2a5e..85dc1ca44fb 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -241,12 +241,29 @@ static void latticeModifier_updateDepgraph(ModifierData *md, DagForest *forest, } } +static void modifier_vgroup_cache(ModifierData *md, float (*vertexCos)[3]) +{ + md= md->next; + if(md) { + if(md->type==eModifierType_Armature) { + ArmatureModifierData *amd = (ArmatureModifierData*) md; + if(amd->multi) + amd->prevCos= MEM_dupallocN(vertexCos); + } + /* lattice/mesh modifier too */ + } +} + + static void latticeModifier_deformVerts( ModifierData *md, Object *ob, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) { LatticeModifierData *lmd = (LatticeModifierData*) md; + + modifier_vgroup_cache(md, vertexCos); /* if next modifier needs original vertices */ + lattice_deform_verts(lmd->object, ob, derivedData, vertexCos, numVerts, lmd->name); } @@ -4667,8 +4684,16 @@ static void armatureModifier_deformVerts( { ArmatureModifierData *amd = (ArmatureModifierData*) md; + modifier_vgroup_cache(md, vertexCos); /* if next modifier needs original vertices */ + armature_deform_verts(amd->object, ob, derivedData, vertexCos, NULL, - numVerts, amd->deformflag, amd->defgrp_name); + numVerts, amd->deformflag, + amd->prevCos, amd->defgrp_name); + /* free cache */ + if(amd->prevCos) { + MEM_freeN(amd->prevCos); + amd->prevCos= NULL; + } } static void armatureModifier_deformVertsEM( @@ -4681,7 +4706,7 @@ static void armatureModifier_deformVertsEM( if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data); armature_deform_verts(amd->object, ob, dm, vertexCos, NULL, numVerts, - amd->deformflag, amd->defgrp_name); + amd->deformflag, NULL, amd->defgrp_name); if(!derivedData) dm->release(dm); } @@ -4697,7 +4722,7 @@ static void armatureModifier_deformMatricesEM( if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data); armature_deform_verts(amd->object, ob, dm, vertexCos, defMats, numVerts, - amd->deformflag, amd->defgrp_name); + amd->deformflag, NULL, amd->defgrp_name); if(!derivedData) dm->release(dm); } @@ -5494,6 +5519,8 @@ static void meshdeformModifier_deformVerts( else dm= derivedData; + modifier_vgroup_cache(md, vertexCos); /* if next modifier needs original vertices */ + meshdeformModifier_do(md, ob, dm, vertexCos, numVerts); if(dm != derivedData) diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index a08256eb4a0..095d6f525a9 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -1178,6 +1178,8 @@ void object_make_proxy(Object *ob, Object *target, Object *gob) VECCOPY(ob->loc, gob->loc); VECCOPY(ob->rot, gob->rot); VECCOPY(ob->size, gob->size); + + group_tag_recalc(gob->dup_group); } else { VECCOPY(ob->loc, target->loc); diff --git a/source/blender/blenlib/BLI_fnmatch.h b/source/blender/blenlib/BLI_fnmatch.h new file mode 100644 index 00000000000..af1dcf523bf --- /dev/null +++ b/source/blender/blenlib/BLI_fnmatch.h @@ -0,0 +1,69 @@ +/* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc. + +NOTE: The canonical source of this file is maintained with the GNU C Library. +Bugs can be reported to bug-glibc@prep.ai.mit.edu. + +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, 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. */ + +#ifndef _FNMATCH_H + +#define _FNMATCH_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined (__cplusplus) || (defined (__STDC__) && __STDC__) +#undef __P +#define __P(protos) protos +#else /* Not C++ or ANSI C. */ +#undef __P +#define __P(protos) () +/* We can get away without defining `const' here only because in this file + it is used only inside the prototype for `fnmatch', which is elided in + non-ANSI C where `const' is problematical. */ +#endif /* C++ or ANSI C. */ + + +/* We #undef these before defining them because some losing systems + (HP-UX A.08.07 for example) define these in . */ +#undef FNM_PATHNAME +#undef FNM_NOESCAPE +#undef FNM_PERIOD + +/* Bits set in the FLAGS argument to `fnmatch'. */ +#define FNM_PATHNAME (1 << 0) /* No wildcard can ever match `/'. */ +#define FNM_NOESCAPE (1 << 1) /* Backslashes don't quote special chars. */ +#define FNM_PERIOD (1 << 2) /* Leading `.' is matched only explicitly. */ + +#if !defined (_POSIX_C_SOURCE) || _POSIX_C_SOURCE < 2 || defined (_GNU_SOURCE) +#define FNM_FILE_NAME FNM_PATHNAME /* Preferred GNU name. */ +#define FNM_LEADING_DIR (1 << 3) /* Ignore `/...' after a match. */ +#define FNM_CASEFOLD (1 << 4) /* Compare without regard to case. */ +#endif + +/* Value returned by `fnmatch' if STRING does not match PATTERN. */ +#define FNM_NOMATCH 1 + +/* Match STRING against the filename pattern PATTERN, + returning zero if it matches, FNM_NOMATCH if not. */ +extern int fnmatch __P ((const char *__pattern, const char *__string, + int __flags)); + +#ifdef __cplusplus +} +#endif + +#endif /* fnmatch.h */ diff --git a/source/blender/blenlib/intern/fnmatch.c b/source/blender/blenlib/intern/fnmatch.c new file mode 100644 index 00000000000..54114ad3448 --- /dev/null +++ b/source/blender/blenlib/intern/fnmatch.c @@ -0,0 +1,250 @@ +/* Copyright (C) 1991, 1992, 1993, 1996, 1997 Free Software Foundation, Inc. + + 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, 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. */ + +#ifdef WIN32 + +#if HAVE_CONFIG_H +# include +#endif + +/* Enable GNU extensions in fnmatch.h. */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif + +#include +#include +#include + + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ + +#if defined _LIBC || !defined __GNU_LIBRARY__ + + +# if defined STDC_HEADERS || !defined isascii +# define ISASCII(c) 1 +# else +# define ISASCII(c) isascii(c) +# endif + +# define ISUPPER(c) (ISASCII (c) && isupper (c)) + + +# ifndef errno +extern int errno; +# endif + +/* Match STRING against the filename pattern PATTERN, returning zero if + it matches, nonzero if not. */ +int +fnmatch (const char *pattern, const char *string, int flags) +{ + register const char *p = pattern, *n = string; + register char c; + +/* Note that this evaluates C many times. */ +# define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c)) + + while ((c = *p++) != '\0') + { + c = FOLD (c); + + switch (c) + { + case '?': + if (*n == '\0') + return FNM_NOMATCH; + else if ((flags & FNM_FILE_NAME) && *n == '/') + return FNM_NOMATCH; + else if ((flags & FNM_PERIOD) && *n == '.' && + (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/'))) + return FNM_NOMATCH; + break; + + case '\\': + if (!(flags & FNM_NOESCAPE)) + { + c = *p++; + if (c == '\0') + /* Trailing \ loses. */ + return FNM_NOMATCH; + c = FOLD (c); + } + if (FOLD (*n) != c) + return FNM_NOMATCH; + break; + + case '*': + if ((flags & FNM_PERIOD) && *n == '.' && + (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/'))) + return FNM_NOMATCH; + + for (c = *p++; c == '?' || c == '*'; c = *p++) + { + if ((flags & FNM_FILE_NAME) && *n == '/') + /* A slash does not match a wildcard under FNM_FILE_NAME. */ + return FNM_NOMATCH; + else if (c == '?') + { + /* A ? needs to match one character. */ + if (*n == '\0') + /* There isn't another character; no match. */ + return FNM_NOMATCH; + else + /* One character of the string is consumed in matching + this ? wildcard, so *??? won't match if there are + less than three characters. */ + ++n; + } + } + + if (c == '\0') + return 0; + + { + char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c; + c1 = FOLD (c1); + for (--p; *n != '\0'; ++n) + if ((c == '[' || FOLD (*n) == c1) && + fnmatch (p, n, flags & ~FNM_PERIOD) == 0) + return 0; + return FNM_NOMATCH; + } + + case '[': + { + /* Nonzero if the sense of the character class is inverted. */ + register int not; + + if (*n == '\0') + return FNM_NOMATCH; + + if ((flags & FNM_PERIOD) && *n == '.' && + (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/'))) + return FNM_NOMATCH; + + not = (*p == '!' || *p == '^'); + if (not) + ++p; + + c = *p++; + for (;;) + { + register char cstart = c, cend = c; + + if (!(flags & FNM_NOESCAPE) && c == '\\') + { + if (*p == '\0') + return FNM_NOMATCH; + cstart = cend = *p++; + } + + cstart = cend = FOLD (cstart); + + if (c == '\0') + /* [ (unterminated) loses. */ + return FNM_NOMATCH; + + c = *p++; + c = FOLD (c); + + if ((flags & FNM_FILE_NAME) && c == '/') + /* [/] can never match. */ + return FNM_NOMATCH; + + if (c == '-' && *p != ']') + { + cend = *p++; + if (!(flags & FNM_NOESCAPE) && cend == '\\') + cend = *p++; + if (cend == '\0') + return FNM_NOMATCH; + cend = FOLD (cend); + + c = *p++; + } + + if (FOLD (*n) >= cstart && FOLD (*n) <= cend) + goto matched; + + if (c == ']') + break; + } + if (!not) + return FNM_NOMATCH; + break; + + matched:; + /* Skip the rest of the [...] that already matched. */ + while (c != ']') + { + if (c == '\0') + /* [... (unterminated) loses. */ + return FNM_NOMATCH; + + c = *p++; + if (!(flags & FNM_NOESCAPE) && c == '\\') + { + if (*p == '\0') + return FNM_NOMATCH; + /* XXX 1003.2d11 is unclear if this is right. */ + ++p; + } + } + if (not) + return FNM_NOMATCH; + } + break; + + default: + if (c != FOLD (*n)) + return FNM_NOMATCH; + } + + ++n; + } + + if (*n == '\0') + return 0; + + if ((flags & FNM_LEADING_DIR) && *n == '/') + /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */ + return 0; + + return FNM_NOMATCH; + +# undef FOLD +} + +#endif /* _LIBC or not __GNU_LIBRARY__. */ + +#else + +static void BLI_FNMATCH_C_IS_EMPTY_FOR_UNIX(void) +{ + /*intentionally empty*/ +} + +#endif /* WIN32 */ + + diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 5861ba39da2..6d16a326a0b 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -3226,7 +3226,6 @@ static void direct_link_scene(FileData *fd, Scene *sce) Editing *ed; Sequence *seq; MetaStack *ms; - StripElem *se; int a; sce->theDag = NULL; @@ -3262,8 +3261,6 @@ static void direct_link_scene(FileData *fd, Scene *sce) /* a patch: after introduction of effects with 3 input strips */ if(seq->seq3==0) seq->seq3= seq->seq2; - seq->curelem= 0; - seq->plugin= newdataadr(fd, seq->plugin); seq->effectdata= newdataadr(fd, seq->effectdata); @@ -3274,59 +3271,17 @@ static void direct_link_scene(FileData *fd, Scene *sce) seq->strip= newdataadr(fd, seq->strip); if(seq->strip && seq->strip->done==0) { seq->strip->done= 1; + seq->strip->tstripdata = 0; - /* standard: strips from effects/metas are not written, but are mallocced */ - - if(seq->type==SEQ_IMAGE) { - seq->strip->stripdata= newdataadr(fd, seq->strip->stripdata); - se= seq->strip->stripdata; - if(se) { - for(a=0; astrip->len; a++, se++) { - se->ok= 1; - se->ibuf= 0; - } - } + if(seq->type == SEQ_IMAGE || + seq->type == SEQ_MOVIE || + seq->type == SEQ_RAM_SOUND || + seq->type == SEQ_HD_SOUND) { + seq->strip->stripdata = newdataadr( + fd, seq->strip->stripdata); + } else { + seq->strip->stripdata = 0; } - else if(seq->type==SEQ_MOVIE) { - /* only first stripelem is in file */ - se= newdataadr(fd, seq->strip->stripdata); - - if(se) { - seq->strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem"); - *seq->strip->stripdata= *se; - MEM_freeN(se); - - se= seq->strip->stripdata; - - for(a=0; astrip->len; a++, se++) { - se->ok= 1; - se->ibuf= 0; - se->nr= a + 1; - } - } - } - else if(seq->type==SEQ_RAM_SOUND - || seq->type == SEQ_HD_SOUND) { - /* only first stripelem is in file */ - se= newdataadr(fd, seq->strip->stripdata); - - if(se) { - seq->strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem"); - *seq->strip->stripdata= *se; - MEM_freeN(se); - - se= seq->strip->stripdata; - - for(a=0; astrip->len; a++, se++) { - se->ok= 2; /* why? */ - se->ibuf= 0; - se->nr= a + 1; - } - } - } - else if(seq->len>0) - seq->strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem"); - } } END_SEQ diff --git a/source/blender/include/BSE_sequence.h b/source/blender/include/BSE_sequence.h index ff79d417537..fdf584b38f4 100644 --- a/source/blender/include/BSE_sequence.h +++ b/source/blender/include/BSE_sequence.h @@ -37,6 +37,7 @@ struct PluginSeq; struct StripElem; +struct TStripElem; struct Strip; struct Sequence; struct ListBase; @@ -44,9 +45,9 @@ struct Editing; struct ImBuf; struct Scene; -void free_stripdata(int len, struct StripElem *se); +void free_tstripdata(int len, struct TStripElem *se); void free_strip(struct Strip *strip); -void new_stripdata(struct Sequence *seq); +void new_tstripdata(struct Sequence *seq); void free_sequence(struct Sequence *seq); void build_seqar(struct ListBase *seqbase, struct Sequence ***seqar, int *totseq); void free_editing(struct Editing *ed); @@ -57,17 +58,20 @@ void clear_scene_in_allseqs(struct Scene *sce); int evaluate_seq_frame(int cfra); struct StripElem *give_stripelem(struct Sequence *seq, int cfra); +struct TStripElem *give_tstripelem(struct Sequence *seq, int cfra); void set_meta_stripdata(struct Sequence *seqm); struct ImBuf *give_ibuf_seq(int rectx, int recty, int cfra, int chansel); /* chansel: render this channel. Default=0 (renders end result)*/ +struct ImBuf *give_ibuf_seq_direct(int rectx, int recty, int cfra, + struct Sequence * seq); /* sequence prefetch API */ void seq_start_threads(); void seq_stop_threads(); void give_ibuf_prefetch_request(int rectx, int recty, int cfra, int chanshown); void seq_wait_for_prefetch_ready(); -struct ImBuf * give_ibuf_threaded(int rectx, int recty, int cfra, - int chanshown); +struct ImBuf * give_ibuf_seq_threaded(int rectx, int recty, int cfra, + int chanshown); void free_imbuf_seq_except(int cfra); diff --git a/source/blender/makesdna/DNA_armature_types.h b/source/blender/makesdna/DNA_armature_types.h index 82d120533d6..f5eacede809 100644 --- a/source/blender/makesdna/DNA_armature_types.h +++ b/source/blender/makesdna/DNA_armature_types.h @@ -112,10 +112,11 @@ typedef struct bArmature { #define ARM_ENVELOPE 3 /* armature->deformflag */ -#define ARM_DEF_VGROUP 1 -#define ARM_DEF_ENVELOPE 2 -#define ARM_DEF_QUATERNION 4 -#define ARM_DEF_B_BONE_REST 8 +#define ARM_DEF_VGROUP 1 +#define ARM_DEF_ENVELOPE 2 +#define ARM_DEF_QUATERNION 4 +#define ARM_DEF_B_BONE_REST 8 +#define ARM_DEF_INVERT_VGROUP 16 /* armature->pathflag */ #define ARM_PATH_FNUMS (1<<0) diff --git a/source/blender/makesdna/DNA_key_types.h b/source/blender/makesdna/DNA_key_types.h index 3292e07f80e..785cf515a42 100644 --- a/source/blender/makesdna/DNA_key_types.h +++ b/source/blender/makesdna/DNA_key_types.h @@ -44,8 +44,8 @@ typedef struct KeyBlock { float pos; float curval; - short type, adrcode; - int totelem; + short type, adrcode, relative, pad1; /* relative == 0 means first key is reference */ + int totelem, pad2; void *data; float *weights; diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 68290c6e9b5..903f1a540b3 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -316,9 +316,10 @@ typedef struct WaveModifierData { typedef struct ArmatureModifierData { ModifierData modifier; - short deformflag, pad1; /* deformflag replaces armature->deformflag */ + short deformflag, multi; /* deformflag replaces armature->deformflag */ int pad2; struct Object *object; + float *prevCos; /* stored input of previous modifier, for vertexgroup blending */ char defgrp_name[32]; } ArmatureModifierData; diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h index 839d804fbea..0f9b55723bc 100644 --- a/source/blender/makesdna/DNA_sequence_types.h +++ b/source/blender/makesdna/DNA_sequence_types.h @@ -46,12 +46,15 @@ struct Scene; typedef struct StripElem { char name[80]; +} StripElem; + +typedef struct TStripElem { struct ImBuf *ibuf; - struct StripElem *se1, *se2, *se3; + struct TStripElem *se1, *se2, *se3; short ok; short pad; int nr; -} StripElem; +} TStripElem; typedef struct Strip { struct Strip *next, *prev; @@ -59,6 +62,7 @@ typedef struct Strip { StripElem *stripdata; char dir[160]; int orx, ory; + TStripElem *tstripdata; } Strip; @@ -87,7 +91,6 @@ typedef struct PluginSeq { /* WATCH IT: first part identical to ID (for use in ipo's) */ typedef struct Sequence { - struct Sequence *next, *prev; void *tmp; /* tmp var for copying, and tagging for linked selection */ void *lib; /* needed (to be like ipo), else it will raise libdata warnings, this should never be used */ @@ -104,7 +107,6 @@ typedef struct Sequence { int sfra; /* starting frame according to the timeline of the scene. */ Strip *strip; - StripElem *curelem; /* reference the current frame - value from give_stripelem */ struct Ipo *ipo; struct Scene *scene; @@ -234,6 +236,9 @@ typedef struct SpeedControlVars { #define SEQ_COLOR 28 #define SEQ_SPEED 29 +#define STRIPELEM_FAILED 0 +#define STRIPELEM_OK 1 +#define STRIPELEM_META 2 #endif diff --git a/source/blender/python/api2_2x/Mesh.c b/source/blender/python/api2_2x/Mesh.c index 88fa09bd607..8a832d0deeb 100644 --- a/source/blender/python/api2_2x/Mesh.c +++ b/source/blender/python/api2_2x/Mesh.c @@ -5004,7 +5004,8 @@ static PyObject *MFaceSeq_extend( BPy_MEdgeSeq * self, PyObject *args, Mesh *mesh = self->mesh; int ignore_dups = 0; PyObject *return_list = NULL; - + char flag = ME_FACE_SEL; + /* before we try to add faces, add edges; if it fails; exit */ tmp = MEdgeSeq_extend( self, args ); @@ -5034,6 +5035,20 @@ static PyObject *MFaceSeq_extend( BPy_MEdgeSeq * self, PyObject *args, return_list = PyList_New( 0 ); } } + + res = PyDict_GetItemString( keywds, "smooth" ); + if (res) { + switch( PyObject_IsTrue( res ) ) { + case 0: + break; + case -1: + return EXPP_ReturnPyObjError( PyExc_TypeError, + "keyword argument \"smooth\" expected True/False or 0/1" ); + default: + flag |= ME_SMOOTH; + + } + } } /* make sure we get a tuple of sequences of something */ @@ -5319,7 +5334,7 @@ static PyObject *MFaceSeq_extend( BPy_MEdgeSeq * self, PyObject *args, tmpface->v3 = tmppair->v[index[2]]; tmpface->v4 = tmppair->v[index[3]]; - tmpface->flag = ME_FACE_SEL; + tmpface->flag = flag; if( return_list ) { tmp = PyInt_FromLong( mesh->totface ); @@ -6409,6 +6424,10 @@ static PyObject *Mesh_removeVertGroup( PyObject * self, PyObject * value ) int nIndex; bDeformGroup *pGroup; + if( G.obedit ) + return EXPP_ReturnPyObjError(PyExc_RuntimeError, + "can't use removeVertGroup() while in edit mode" ); + if( !groupStr ) return EXPP_ReturnPyObjError( PyExc_TypeError, "expected string argument" ); @@ -6431,8 +6450,8 @@ static PyObject *Mesh_removeVertGroup( PyObject * self, PyObject * value ) nIndex++; object->actdef = (unsigned short)nIndex; - del_defgroup( object ); - + del_defgroup_in_object_mode( object ); + EXPP_allqueue( REDRAWBUTSALL, 1 ); Py_RETURN_NONE; @@ -7585,7 +7604,7 @@ static int Mesh_setVerts( BPy_Mesh * self, PyObject * args ) free_mesh( me ); me->mvert = NULL; me->medge = NULL; me->mface = NULL; me->mtface = NULL; me->dvert = NULL; me->mcol = NULL; - me->msticky = NULL; me->mat = NULL; me->bb = NULL; + me->msticky = NULL; me->mat = NULL; me->bb = NULL; me->mselect = NULL; me->totvert = me->totedge = me->totface = me->totcol = 0; mesh_update( me ); return 0; diff --git a/source/blender/python/api2_2x/Window.c b/source/blender/python/api2_2x/Window.c index 323f209651a..c5c0860a921 100644 --- a/source/blender/python/api2_2x/Window.c +++ b/source/blender/python/api2_2x/Window.c @@ -61,6 +61,19 @@ #include "gen_utils.h" #include "Armature.h" +/* Pivot Types +-0 for Bounding Box Center; \n\ +-1 for 3D Cursor\n\ +-2 for Individual Centers\n\ +-3 for Median Point\n\ +-4 for Active Object"; */ + +#define PIVOT_BOUNDBOX 0 +#define PIVOT_CURSOR 1 +#define PIVOT_INDIVIDUAL 2 +#define PIVOT_MEDIAN 3 +#define PIVOT_ACTIVE 4 + /* See Draw.c */ extern int EXPP_disable_force_draw; extern void setcameratoview3d(void); @@ -106,6 +119,9 @@ static PyObject *M_Window_GetScreens( PyObject * self ); static PyObject *M_Window_SetScreen( PyObject * self, PyObject * value ); static PyObject *M_Window_GetScreenInfo( PyObject * self, PyObject * args, PyObject * kwords ); +static PyObject *M_Window_GetPivot( PyObject * self ); +static PyObject *M_Window_SetPivot( PyObject * self, PyObject * value ); + PyObject *Window_Init( void ); @@ -287,6 +303,18 @@ Each dictionary has keys:\n\ 'win': window type, see Blender.Window.Types dict;\n\ 'id': area's id."; +static char M_Window_SetPivot_doc[] = + "(Pivot) - Set Pivot Mode for 3D Viewport:\n\ +Options are: \n\ +-PivotTypes.BOUNDBOX for Bounding Box Center; \n\ +-PivotTypes.CURSOR for 3D Cursor\n\ +-PivotTypes.INDIVIDUAL for Individual Centers\n\ +-PivotTypes.MEDIAN for Median Point\n\ +-PivotTypes.ACTIVE for Active Object"; + +static char M_Window_GetPivot_doc[] = + "Return the pivot for the active 3d window"; + /*****************************************************************************/ /* Python method structure definition for Blender.Window module: */ /*****************************************************************************/ @@ -374,6 +402,10 @@ struct PyMethodDef M_Window_methods[] = { M_Window_SetScreen_doc}, {"GetScreenInfo", ( PyCFunction ) M_Window_GetScreenInfo, METH_VARARGS | METH_KEYWORDS, M_Window_GetScreenInfo_doc}, + {"GetPivot", ( PyCFunction ) M_Window_GetPivot, METH_NOARGS, + M_Window_GetPivot_doc}, + {"SetPivot", ( PyCFunction ) M_Window_SetPivot, METH_O, + M_Window_SetPivot_doc}, {NULL, NULL, 0, NULL} }; @@ -1454,12 +1486,38 @@ static PyObject *M_Window_GetScreenInfo( PyObject * self, PyObject * args, return list; } +static PyObject *M_Window_GetPivot( PyObject * self ) +{ + if (G.vd) { + return PyInt_FromLong( G.vd->around ); + } + Py_RETURN_NONE; +} + +static PyObject *M_Window_SetPivot( PyObject * self, PyObject * value) + +{ + short pivot; + if (G.vd) { + pivot = (short)PyInt_AsLong( value ); + + if ( pivot > 4 || pivot < 0 ) + return EXPP_ReturnPyObjError( PyExc_AttributeError, + "Expected a constant from Window.PivotTypes" ); + + G.vd->around = pivot; + } + Py_RETURN_NONE; +} + + + /*****************************************************************************/ /* Function: Window_Init */ /*****************************************************************************/ PyObject *Window_Init( void ) { - PyObject *submodule, *Types, *Qual, *MButs, *dict; + PyObject *submodule, *Types, *Qual, *MButs, *PivotTypes, *dict; submodule = Py_InitModule3( "Blender.Window", M_Window_methods, @@ -1472,6 +1530,7 @@ PyObject *Window_Init( void ) Types = PyConstant_New( ); Qual = PyConstant_New( ); MButs = PyConstant_New( ); + PivotTypes = PyConstant_New( ); if( Types ) { BPy_constant *d = ( BPy_constant * ) Types; @@ -1522,5 +1581,16 @@ PyObject *Window_Init( void ) PyModule_AddObject( submodule, "MButs", MButs ); } + if( PivotTypes ) { + BPy_constant *d = ( BPy_constant * ) PivotTypes; + + PyConstant_Insert(d, "BOUNDBOX", PyInt_FromLong( PIVOT_BOUNDBOX ) ); + PyConstant_Insert(d, "CURSOR", PyInt_FromLong( PIVOT_CURSOR ) ); + PyConstant_Insert(d, "MEDIAN", PyInt_FromLong( PIVOT_MEDIAN ) ); + PyConstant_Insert(d, "ACTIVE", PyInt_FromLong( PIVOT_ACTIVE ) ); + PyConstant_Insert(d, "INDIVIDUAL", PyInt_FromLong( PIVOT_INDIVIDUAL ) ); + + PyModule_AddObject( submodule, "PivotTypes", PivotTypes ); + } return submodule; } diff --git a/source/blender/python/api2_2x/doc/Curve.py b/source/blender/python/api2_2x/doc/Curve.py index 5e6df688953..5ccf5834ebd 100644 --- a/source/blender/python/api2_2x/doc/Curve.py +++ b/source/blender/python/api2_2x/doc/Curve.py @@ -115,9 +115,9 @@ class Curve: @type resolv: int @ivar width: The Curve Data width [0 - 2]. @type width: float - @ivar ext1: The Curve Data extent1 (for bevels). + @ivar ext1: The Curve Data extent1 Called "Extrude" in the user interface (for bevels only). @type ext1: float - @ivar ext2: The Curve Data extent2 (for bevels). + @ivar ext2: The Curve Data extent2 - Called "Bevel Depth" in the user interface (for bevels only). @type ext2: float @ivar loc: The Curve Data location(from the center). @type loc: list of 3 floats diff --git a/source/blender/python/api2_2x/doc/Text3d.py b/source/blender/python/api2_2x/doc/Text3d.py index 78993b9e8f3..a7d8c585078 100644 --- a/source/blender/python/api2_2x/doc/Text3d.py +++ b/source/blender/python/api2_2x/doc/Text3d.py @@ -153,13 +153,13 @@ class Text3d: @param width: The new text3d's width value. """ - def getgetExtrudeDepth(): + def getExtrudeDepth(): """ Get the text3d's ext1 value. @rtype: float """ - def setgetExtrudeDepth(ext1): + def setExtrudeDepth(ext1): """ Set the text3d's ext1 value. @rtype: None diff --git a/source/blender/python/api2_2x/doc/Texture.py b/source/blender/python/api2_2x/doc/Texture.py index 823f34b14bd..dfba93c9978 100644 --- a/source/blender/python/api2_2x/doc/Texture.py +++ b/source/blender/python/api2_2x/doc/Texture.py @@ -532,6 +532,8 @@ class MTex: @ivar mtAmb: How texture maps to ambient value @ivar mtDisp: How texture maps to displacement @ivar mtWarp: How texture maps to warp + @ivar uvlayer: The name of the UV Layer this texture is mapped to (when left blank uses render layer) + @type uvlayer: string """ def getIpo(): diff --git a/source/blender/python/api2_2x/doc/Window.py b/source/blender/python/api2_2x/doc/Window.py index b5145d34ca2..7fceeb757de 100644 --- a/source/blender/python/api2_2x/doc/Window.py +++ b/source/blender/python/api2_2x/doc/Window.py @@ -210,6 +210,20 @@ def SetCursorPos (coords): can be done with L{Redraw}. """ +def GetPivot (): + """ + Get the pivot for the active 3D view. + @rtype: int + @return: constant - Window.PivotTypes + """ + +def SetPivot (pivot): + """ + Set the pivot on the active 3D view. + @type pivot: int + @param pivot: constant - Window.PivotTypes + """ + def WaitCursor (bool): """ Set cursor to wait or back to normal mode. diff --git a/source/blender/python/api2_2x/sceneSequence.c b/source/blender/python/api2_2x/sceneSequence.c index 6ddaaf345c3..fee1bde149c 100644 --- a/source/blender/python/api2_2x/sceneSequence.c +++ b/source/blender/python/api2_2x/sceneSequence.c @@ -156,7 +156,6 @@ static PyObject *NewSeq_internal(ListBase *seqbase, PyObject * args, Scene *sce) for(a=0; alen; a++) { name = PyString_AsString(PyList_GetItem( list, a )); strncpy(se->name, name, FILE_MAXFILE-1); - se->ok= 1; se++; } @@ -179,16 +178,10 @@ static PyObject *NewSeq_internal(ListBase *seqbase, PyObject * args, Scene *sce) strip->len= totframe; strip->us= 1; strncpy(strip->dir, sound->name, FILE_MAXDIR-1); - strip->stripdata= se= MEM_callocN(totframe*sizeof(StripElem), "stripelem"); + strip->stripdata= se= MEM_callocN(sizeof(StripElem), "stripelem"); /* name sound in first strip */ strncpy(se->name, sound->name, FILE_MAXFILE-1); - - for(a=1; a<=totframe; a++, se++) { - se->ok= 2; /* why? */ - se->ibuf= 0; - se->nr= a; - } } else if (BPy_Scene_Check(py_data)) { /* scene */ @@ -205,8 +198,6 @@ static PyObject *NewSeq_internal(ListBase *seqbase, PyObject * args, Scene *sce) sizeof(seq->name) - 2); strip->len= seq->len; strip->us= 1; - if(seq->len>0) strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem"); - } else { /* movie, pydata is a path to a movie file */ char *name = PyString_AsString ( py_data ); diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index 25540106356..70d1c092066 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -1647,7 +1647,7 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco if(wmd->flag & MOD_WAVE_NORM) height += 19; } else if (md->type==eModifierType_Armature) { - height = 86; + height = 105; } else if (md->type==eModifierType_Hook) { HookModifierData *hmd = (HookModifierData*) md; height = 86; @@ -1978,12 +1978,17 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco ArmatureModifierData *amd = (ArmatureModifierData*) md; uiDefIDPoinBut(block, modifier_testArmatureObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &amd->object, "Armature object to deform with"); - but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ", lx, (cy-=19), buttonWidth,19, &amd->defgrp_name, 0.0, 31.0, 0, 0, "Vertex Group name to control overall armature influence"); + but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ", lx, (cy-=19), buttonWidth-40,19, &amd->defgrp_name, 0.0, 31.0, 0, 0, "Vertex Group name to control overall armature influence"); uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob); + uiDefButBitS(block, TOG, ARM_DEF_INVERT_VGROUP, B_ARM_RECALCDATA, "Inv", lx+buttonWidth-40,cy, 40, 20, &amd->deformflag, 0, 0, 0, 0, "Invert vertex group influence"); + uiDefButBitS(block, TOG, ARM_DEF_VGROUP, B_ARM_RECALCDATA, "Vert.Groups", lx,cy-=19,buttonWidth/2,20, &amd->deformflag, 0, 0, 0, 0, "Enable VertexGroups defining deform"); uiDefButBitS(block, TOG, ARM_DEF_ENVELOPE, B_ARM_RECALCDATA, "Envelopes", lx+buttonWidth/2,cy,(buttonWidth + 1)/2,20, &amd->deformflag, 0, 0, 0, 0, "Enable Bone Envelopes defining deform"); uiDefButBitS(block, TOG, ARM_DEF_QUATERNION, B_ARM_RECALCDATA, "Quaternion", lx,(cy-=19),buttonWidth/2,20, &amd->deformflag, 0, 0, 0, 0, "Enable deform rotation interpolation with Quaternions"); uiDefButBitS(block, TOG, ARM_DEF_B_BONE_REST, B_ARM_RECALCDATA, "B-Bone Rest", lx+buttonWidth/2,cy,(buttonWidth + 1)/2,20, &amd->deformflag, 0, 0, 0, 0, "Make B-Bones deform already in rest position"); + + uiDefButS(block, TOG, B_ARM_RECALCDATA, "MultiModifier", lx,cy-=19, buttonWidth, 20, &amd->multi, 0, 0, 0, 0, "Use same input as previous modifier, and mix results using overall vgroup"); + } else if (md->type==eModifierType_Hook) { HookModifierData *hmd = (HookModifierData*) md; uiDefButF(block, NUM, B_MODIFIER_RECALC, "Falloff: ", lx, (cy-=19), buttonWidth,19, &hmd->falloff, 0.0, 100.0, 100, 0, "If not zero, the distance from hook where influence ends"); @@ -2245,7 +2250,7 @@ static void editing_panel_modifiers(Object *ob) if(yco < 0) uiNewPanelHeight(block, 204-yco); } -static char *make_key_menu(Key *key) +static char *make_key_menu(Key *key, int startindex) { KeyBlock *kb; int index= 1; @@ -2255,7 +2260,7 @@ static char *make_key_menu(Key *key) str= MEM_mallocN(index*40, "key string"); str[0]= 0; - index= 1; + index= startindex; for (kb = key->block.first; kb; kb=kb->next, index++) { sprintf (item, "|%s%%x%d", kb->name, index); strcat(str, item); @@ -2301,9 +2306,10 @@ static void editing_panel_shapes(Object *ob) uiDefIconButBitS(block, TOG, OB_SHAPE_LOCK, B_LOCKKEY, icon, 10,150,25,20, &ob->shapeflag, 0, 0, 0, 0, "Always show the current Shape for this Object"); uiSetButLock(G.obedit==ob, "Unable to perform in EditMode"); uiDefIconBut(block, BUT, B_PREVKEY, ICON_TRIA_LEFT, 35,150,20,20, NULL, 0, 0, 0, 0, "Previous Shape Key"); - strp= make_key_menu(key); - uiDefButS(block, MENU, B_SETKEY, strp, 55,150,20,20, &ob->shapenr, 0, 0, 0, 0, "Browses existing choices or adds NEW"); + strp= make_key_menu(key, 1); + uiDefButS(block, MENU, B_SETKEY, strp, 55,150,20,20, &ob->shapenr, 0, 0, 0, 0, "Browse existing choices"); MEM_freeN(strp); + uiDefIconBut(block, BUT, B_NEXTKEY, ICON_TRIA_RIGHT, 75,150,20,20, NULL, 0, 0, 0, 0, "Next Shape Key"); uiClearButLock(); uiDefBut(block, TEX, B_NAMEKEY, "", 95, 150, 190, 20, kb->name, 0.0, 31.0, 0, 0, "Current Shape Key name"); @@ -2317,9 +2323,14 @@ static void editing_panel_shapes(Object *ob) uiDefButF(block, NUM, B_REDR, "Max ", 235,120, 75, 20, &kb->slidermax, -10.0, 10.0, 100, 1, "Maximum for slider"); uiBlockEndAlign(block); } - if(key->type && ob->shapenr!=1) + if(key->type && ob->shapenr!=1) { uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ", 10, 90, 150,19, &kb->vgroup, 0.0, 31.0, 0, 0, "Vertex Weight Group name, to blend with Basis Shape"); + strp= make_key_menu(key, 0); + uiDefButS(block, MENU, B_MODIFIER_RECALC, strp, 160, 90, 150,19, &kb->relative, 0.0, 0.0, 0, 0, "Shape used as a relative key"); + MEM_freeN(strp); + } + if(key->type==0) uiDefButS(block, NUM, B_DIFF, "Slurph:", 10, 60, 150, 19, &(key->slurph), -500.0, 500.0, 0, 0, "Creates a delay in amount of frames in applying keypositions, first vertex goes first"); diff --git a/source/blender/src/buttons_shading.c b/source/blender/src/buttons_shading.c index f422a39266a..258afa1175e 100644 --- a/source/blender/src/buttons_shading.c +++ b/source/blender/src/buttons_shading.c @@ -1953,7 +1953,7 @@ static void world_panel_mapto(World *wrld) /* TEXTURE OUTPUT */ uiBlockBeginAlign(block); - uiDefButBitS(block, TOG, MTEX_STENCIL, B_WORLDPRV, "Stencil", 10,125,45,19, &(mtex->texflag), 0, 0, 0, 0, "Sets the texture mapping to stencil mode"); + uiDefButBitS(block, TOG, MTEX_STENCIL, B_WORLDPRV, "Stencil", 10,125,45,19, &(mtex->texflag), 0, 0, 0, 0, "Use this texture as a blending value on the next texture"); uiDefButBitS(block, TOG, MTEX_NEGATIVE, B_WORLDPRV, "Neg", 55,125,30,19, &(mtex->texflag), 0, 0, 0, 0, "Inverts the values of the texture to reverse its effect"); uiDefButBitS(block, TOG, MTEX_RGBTOINT, B_WORLDPRV, "No RGB", 85,125,60,19, &(mtex->texflag), 0, 0, 0, 0, "Converts texture RGB values to intensity (gray) values"); uiBlockEndAlign(block); @@ -2098,13 +2098,13 @@ static void world_panel_mistaph(World *wrld) uiBlockSetCol(block, TH_AUTO); uiBlockBeginAlign(block); - uiDefButS(block, ROW, B_WORLDPRV2, "Qua", 10, 90, 40, 19, &wrld->mistype, 1.0, 0.0, 0, 0, "Mist uses quadratic progression"); + uiDefButS(block, ROW, B_WORLDPRV2, "Quad", 10, 90, 40, 19, &wrld->mistype, 1.0, 0.0, 0, 0, "Mist uses quadratic progression"); uiDefButS(block, ROW, B_WORLDPRV2, "Lin", 50, 90, 50, 19, &wrld->mistype, 1.0, 1.0, 0, 0, "Mist uses linear progression"); uiDefButS(block, ROW, B_WORLDPRV2, "Sqr", 100, 90, 50, 19, &wrld->mistype, 1.0, 2.0, 0, 0, "Mist uses inverse quadratic progression"); uiBlockBeginAlign(block); - uiDefButF(block, NUM,B_WORLDPRV2, "Sta:",10,70,140,19, &wrld->miststa, 0.0, 10000.0, 10, 0, "Specifies the starting distance of the mist"); - uiDefButF(block, NUM,B_WORLDPRV2, "Di:",10,50,140,19, &wrld->mistdist, 0.0,10000.0, 10, 00, "Specifies the depth of the mist"); - uiDefButF(block, NUM,B_WORLDPRV2,"Hi:", 10,30,140,19, &wrld->misthi,0.0,100.0, 10, 0, "Specifies the factor for a less dense mist with increasing height"); + uiDefButF(block, NUM,B_WORLDPRV2, "Start:",10,70,140,19, &wrld->miststa, 0.0, 10000.0, 10, 0, "Specifies the starting distance of the mist"); + uiDefButF(block, NUM,B_WORLDPRV2, "Dist:",10,50,140,19, &wrld->mistdist, 0.0,10000.0, 10, 00, "Specifies the depth of the mist"); + uiDefButF(block, NUM,B_WORLDPRV2,"Height:", 10,30,140,19, &wrld->misthi,0.0,100.0, 10, 0, "Specifies the factor for a less dense mist with increasing height"); uiDefButF(block, NUMSLI, B_WORLDPRV2, "Misi ", 10,10,140,19, &(wrld->misi), 0., 1.0, 0, 0, "Sets the mist intensity"); uiBlockEndAlign(block); @@ -2384,7 +2384,7 @@ static void lamp_panel_mapto(Object *ob, Lamp *la) /* TEXTURE OUTPUT */ uiBlockBeginAlign(block); - uiDefButBitS(block, TOG, MTEX_STENCIL, B_LAMPPRV, "Stencil", 10,125,45,19, &(mtex->texflag), 0, 0, 0, 0, "Sets the texture mapping to stencil mode"); + uiDefButBitS(block, TOG, MTEX_STENCIL, B_LAMPPRV, "Stencil", 10,125,45,19, &(mtex->texflag), 0, 0, 0, 0, "Use this texture as a blending value on the next texture"); uiDefButBitS(block, TOG, MTEX_NEGATIVE, B_LAMPPRV, "Neg", 55,125,30,19, &(mtex->texflag), 0, 0, 0, 0, "Inverts the values of the texture to reverse its effect"); uiDefButBitS(block, TOG, MTEX_RGBTOINT, B_LAMPPRV, "No RGB", 85,125,60,19, &(mtex->texflag), 0, 0, 0, 0, "Converts texture RGB values to intensity (gray) values"); uiBlockEndAlign(block); @@ -3065,7 +3065,7 @@ static void material_panel_map_to(Material *ma, int from_nodes) /* TEXTURE OUTPUT */ uiBlockBeginAlign(block); - uiDefButBitS(block, TOG, MTEX_STENCIL, B_MATPRV, "Stencil", 10,125,45,19, &(mtex->texflag), 0, 0, 0, 0, "Sets the texture mapping to stencil mode"); + uiDefButBitS(block, TOG, MTEX_STENCIL, B_MATPRV, "Stencil", 10,125,45,19, &(mtex->texflag), 0, 0, 0, 0, "Use this texture as a blending value on the next texture"); uiDefButBitS(block, TOG, MTEX_NEGATIVE, B_MATPRV, "Neg", 55,125,30,19, &(mtex->texflag), 0, 0, 0, 0, "Inverts the values of the texture to reverse its effect"); uiDefButBitS(block, TOG,MTEX_RGBTOINT, B_MATPRV, "No RGB", 85,125,60,19, &(mtex->texflag), 0, 0, 0, 0, "Converts texture RGB values to intensity (gray) values"); uiBlockEndAlign(block); diff --git a/source/blender/src/drawarmature.c b/source/blender/src/drawarmature.c index c424a24718b..c907bab5a23 100644 --- a/source/blender/src/drawarmature.c +++ b/source/blender/src/drawarmature.c @@ -1737,8 +1737,8 @@ static void draw_pose_paths(Object *ob) CfraElem *ce; ListBase ak; float *fp; - int a; - int stepsize, sfra; + int a, stepsize; + int sfra, efra; if(G.vd->zbuf) glDisable(GL_DEPTH_TEST); @@ -1758,16 +1758,39 @@ static void draw_pose_paths(Object *ob) pchan->pathef= EFRA; } - /* get start frame of calculated range */ + /* get frame ranges */ sfra= pchan->pathsf; + efra = sfra + pchan->pathlen; /* draw curve-line of path */ - // TODO: show before/after with slight difference in colour intensity - BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7); - glBegin(GL_LINE_STRIP); - for(a=0, fp= pchan->path; apathlen; a++, fp+=3) - glVertex3fv(fp); - glEnd(); + if ((CFRA > sfra) && (CFRA < efra)) { + /* Show before/after current frame with slight difference in colour intensity + * This is done in two loops, as there seems to be some problems with changing color + * or something during a loop (noted somewhere in the codebase) + */ + + /* before cfra (darker) */ + BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.2); + glBegin(GL_LINE_STRIP); + for (a=0, fp=pchan->path; (sfra+a)<=CFRA; a++, fp+=3) + glVertex3fv(fp); + glEnd(); + + /* after cfra (lighter) - backtrack a bit so that we don't have gaps */ + BIF_ThemeColorBlend(TH_WIRE, TH_BONE_POSE, 0.7); + glBegin(GL_LINE_STRIP); + for (--a, fp-=3; apathlen; a++, fp+=3) + glVertex3fv(fp); + glEnd(); + } + else { + /* show both directions with same intensity (cfra somewhere else) */ + BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7); + glBegin(GL_LINE_STRIP); + for (a=0, fp= pchan->path; apathlen; a++, fp+=3) + glVertex3fv(fp); + glEnd(); + } glPointSize(1.0); @@ -1791,7 +1814,7 @@ static void draw_pose_paths(Object *ob) for(a=0, fp= pchan->path; apathlen; a+=stepsize, fp+=(stepsize*3)) { char str[32]; - /* only draw framenum if several consecutive highlighted points occur on same point */ + /* only draw framenum if several consecutive highlighted points don't occur on same point */ if (a == 0) { glRasterPos3fv(fp); sprintf(str, " %d\n", (a+sfra)); diff --git a/source/blender/src/drawimage.c b/source/blender/src/drawimage.c index e7a43086fa3..342e361d869 100644 --- a/source/blender/src/drawimage.c +++ b/source/blender/src/drawimage.c @@ -309,9 +309,25 @@ void image_changed(SpaceImage *sima, Image *image) return; /* skip assigning these procedural images... */ - if(image && (image->type==IMA_TYPE_R_RESULT || image->type==IMA_TYPE_COMPOSITE)) {; + if(image && (image->type==IMA_TYPE_R_RESULT || image->type==IMA_TYPE_COMPOSITE)) { return; - } else if (EM_texFaceCheck()) { + } else if ((G.obedit) && + (G.obedit->type == OB_MESH) && + (G.editMesh) && + (G.editMesh->faces.first) + ) { + + /* Add a UV layer if there is none, editmode only */ + if ( !CustomData_has_layer(&G.editMesh->fdata, CD_MTFACE) ) { + EM_add_data_layer(&em->fdata, CD_MTFACE); + CustomData_set_layer_active(&em->fdata, CD_MTFACE, 0); /* always zero because we have no other UV layers */ + change = 1; /* so we update the object, incase no faces are selected */ + + /* BIF_undo_push("New UV Texture"); - undo should be done by whatever changes the image */ + allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWBUTSEDIT, 0); + } + for (efa= em->faces.first; efa; efa= efa->next) { tface = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); if (efa->h==0 && efa->f & SELECT) { diff --git a/source/blender/src/drawseq.c b/source/blender/src/drawseq.c index 36a857abfe1..bb04440bd0f 100644 --- a/source/blender/src/drawseq.c +++ b/source/blender/src/drawseq.c @@ -775,7 +775,6 @@ void set_special_seq_update(int val) static void draw_image_seq(ScrArea *sa) { SpaceSeq *sseq; - StripElem *se; struct ImBuf *ibuf; int x1, y1, rectx, recty; int free_ibuf = 0; @@ -800,10 +799,18 @@ static void draw_image_seq(ScrArea *sa) return; else { recursive= 1; - if (!U.prefetchframes || (G.f & G_PLAYANIM) == 0) { - ibuf= (ImBuf *)give_ibuf_seq(rectx, recty, (G.scene->r.cfra), sseq->chanshown); + if (special_seq_update) { + ibuf= give_ibuf_seq_direct( + rectx, recty, (G.scene->r.cfra), + special_seq_update); + } else if (!U.prefetchframes || (G.f & G_PLAYANIM) == 0) { + ibuf= (ImBuf *)give_ibuf_seq( + rectx, recty, (G.scene->r.cfra), + sseq->chanshown); } else { - ibuf= (ImBuf *)give_ibuf_threaded(rectx, recty, (G.scene->r.cfra), sseq->chanshown); + ibuf= (ImBuf *)give_ibuf_seq_threaded( + rectx, recty, (G.scene->r.cfra), + sseq->chanshown); } recursive= 0; @@ -815,16 +822,6 @@ static void draw_image_seq(ScrArea *sa) } } - if(special_seq_update) { - se = special_seq_update->curelem; - if(se) { - if(se->ok==2) { - if(se->se1) - ibuf= se->se1->ibuf; - } - else ibuf= se->ibuf; - } - } if(ibuf==NULL) return; if(ibuf->rect_float && ibuf->rect==NULL) @@ -862,7 +859,7 @@ static void draw_image_seq(ScrArea *sa) if (free_ibuf) { IMB_freeImBuf(ibuf); - } + } sa->win_swap= WIN_BACK_OK; } @@ -917,9 +914,9 @@ static void draw_extra_seqinfo(void) if(last_seq->type==SEQ_IMAGE) { if (last_seq->len > 1) { /* CURRENT */ - se= (StripElem *)give_stripelem(last_seq, (G.scene->r.cfra)); + se= give_stripelem(last_seq, (G.scene->r.cfra)); if(se) { - sprintf(str, "Cur: %s", se->name); + sprintf(str, "Cur: %s%s", last_seq->strip->dir, se->name); glRasterPos3f(xco, yco, 0.0); BMF_DrawString(G.font, str); xco += xfac*BMF_GetStringWidth(G.font, str) +10.0*xfac; @@ -937,21 +934,22 @@ static void draw_extra_seqinfo(void) glRasterPos3f(xco, yco, 0.0); BMF_DrawString(G.font, str); xco += xfac*BMF_GetStringWidth(G.font, str) +30.0*xfac; - - /* orig size */ - sprintf(str, "OrigSize: %d x %d", last_seq->strip->orx, last_seq->strip->ory); - glRasterPos3f(xco, yco, 0.0); - BMF_DrawString(G.font, str); - xco += xfac*BMF_GetStringWidth(G.font, str) +30.0*xfac; } } else { /* single image */ if (last_seq->strip) { - sprintf(str, "Single: %s len: %d", last_seq->strip->stripdata->name, last_seq->enddisp-last_seq->startdisp); + sprintf(str, "Single: %s%s len: %d", last_seq->strip->dir, last_seq->strip->stripdata->name, last_seq->enddisp-last_seq->startdisp); glRasterPos3f(xco, yco, 0.0); BMF_DrawString(G.font, str); xco += xfac*BMF_GetStringWidth(G.font, str) +30.0*xfac; } } + /* orig size */ + if(last_seq->strip) { + sprintf(str, "OrigSize: %d x %d", last_seq->strip->orx, last_seq->strip->ory); + glRasterPos3f(xco, yco, 0.0); + BMF_DrawString(G.font, str); + xco += xfac*BMF_GetStringWidth(G.font, str) +30.0*xfac; + } } else if(last_seq->type==SEQ_MOVIE) { @@ -966,7 +964,7 @@ static void draw_extra_seqinfo(void) BMF_DrawString(G.font, str); } else if(last_seq->type==SEQ_SCENE) { - se= (StripElem *)give_stripelem(last_seq, (G.scene->r.cfra)); + TStripElem * se= give_tstripelem(last_seq, (G.scene->r.cfra)); if(se && last_seq->scene) { sprintf(str, "Cur: %d First: %d Last: %d", last_seq->sfra+se->nr, last_seq->sfra, last_seq->sfra+last_seq->len-1); glRasterPos3f(xco, yco, 0.0); diff --git a/source/blender/src/edit.c b/source/blender/src/edit.c index 7d784dcecfd..f6b60a3d8fc 100644 --- a/source/blender/src/edit.c +++ b/source/blender/src/edit.c @@ -1221,7 +1221,7 @@ void snap_sel_to_grid() } ob->pose->flag |= (POSE_LOCKED|POSE_DO_UNLOCK); - /* autokeyframing */ + /* auto-keyframing */ autokeyframe_pose_cb_func(ob, TFM_TRANSLATION, 0); DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); } @@ -1231,10 +1231,10 @@ void snap_sel_to_grid() vec[0]= -ob->obmat[3][0]+G.vd->gridview*floor(.5+ ob->obmat[3][0]/gridf); vec[1]= -ob->obmat[3][1]+G.vd->gridview*floor(.5+ ob->obmat[3][1]/gridf); vec[2]= -ob->obmat[3][2]+G.vd->gridview*floor(.5+ ob->obmat[3][2]/gridf); - + if(ob->parent) { where_is_object(ob); - + Mat3Inv(imat, originmat); Mat3MulVecfl(imat, vec); ob->loc[0]+= vec[0]; @@ -1334,7 +1334,7 @@ void snap_sel_to_curs() } ob->pose->flag |= (POSE_LOCKED|POSE_DO_UNLOCK); - /* autokeyframing */ + /* auto-keyframing */ autokeyframe_pose_cb_func(ob, TFM_TRANSLATION, 0); DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); } @@ -1686,7 +1686,7 @@ void snap_to_center() } } - /* autokeyframing */ + /* auto-keyframing */ ob->pose->flag |= POSE_DO_UNLOCK; autokeyframe_pose_cb_func(ob, TFM_TRANSLATION, 0); DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); diff --git a/source/blender/src/editarmature.c b/source/blender/src/editarmature.c index 3e7e00ef240..24c8382a445 100644 --- a/source/blender/src/editarmature.c +++ b/source/blender/src/editarmature.c @@ -1076,6 +1076,19 @@ void delete_armature(void) TEST_EDITARMATURE; if (okee("Erase selected bone(s)")==0) return; + + /* Select mirrored bones */ + if (arm->flag & ARM_MIRROR_EDIT) { + for (curBone=G.edbo.first; curBone; curBone=curBone->next) { + if (arm->layer & curBone->layer) { + if (curBone->flag & BONE_SELECTED) { + next = armature_bone_get_mirrored(curBone); + if (next) + next->flag |= BONE_SELECTED; + } + } + } + } /* First erase any associated pose channel */ if (G.obedit->pose) { @@ -1321,13 +1334,19 @@ void auto_align_armature(short mode) { bArmature *arm= G.obedit->data; EditBone *ebone; + EditBone *flipbone = NULL; float delta[3]; float curmat[3][3]; float *cursor= give_cursor(); for (ebone = G.edbo.first; ebone; ebone=ebone->next) { - if(arm->layer & ebone->layer) { - if (ebone->flag & BONE_SELECTED) { + if (arm->layer & ebone->layer) { + if (arm->flag & ARM_MIRROR_EDIT) + flipbone = armature_bone_get_mirrored(ebone); + + if ((ebone->flag & BONE_SELECTED) || + (flipbone && flipbone->flag & BONE_SELECTED)) + { /* specific method used to calculate roll depends on mode */ if (mode == 1) { /* Z-Axis point towards cursor */ @@ -1386,7 +1405,7 @@ void auto_align_armature(short mode) Mat3MulMat3(diffmat, imat, curmat); ebone->roll = atan2(diffmat[2][0], diffmat[2][2]); - } + } } } } @@ -1713,11 +1732,24 @@ void adduplicate_armature(void) EditBone *firstDup=NULL; /* The beginning of the duplicated bones in the edbo list */ countall(); // flushes selection! + + /* Select mirrored bones */ + if (arm->flag & ARM_MIRROR_EDIT) { + for (curBone=G.edbo.first; curBone; curBone=curBone->next) { + if (arm->layer & curBone->layer) { + if (curBone->flag & BONE_SELECTED) { + eBone = armature_bone_get_mirrored(curBone); + if (eBone) + eBone->flag |= BONE_SELECTED; + } + } + } + } /* Find the selected bones and duplicate them as needed */ for (curBone=G.edbo.first; curBone && curBone!=firstDup; curBone=curBone->next){ - if(arm->layer & curBone->layer) { - if (curBone->flag & BONE_SELECTED){ + if (arm->layer & curBone->layer) { + if (curBone->flag & BONE_SELECTED) { eBone=MEM_callocN(sizeof(EditBone), "addup_editbone"); eBone->flag |= BONE_SELECTED; @@ -2034,10 +2066,22 @@ void make_bone_parent(void) return; } +static void editbone_clear_parent(EditBone *ebone, int mode) +{ + if (ebone->parent) { + /* for nice selection */ + ebone->parent->flag &= ~(BONE_TIPSEL); + } + + if(mode==1) ebone->parent= NULL; + ebone->flag &= ~BONE_CONNECTED; +} + void clear_bone_parent(void) { bArmature *arm= G.obedit->data; EditBone *ebone; + EditBone *flipbone = NULL; short val; val= pupmenu("Clear Parent%t|Clear Parent%x1|Disconnect Bone%x2"); @@ -2046,13 +2090,13 @@ void clear_bone_parent(void) for (ebone = G.edbo.first; ebone; ebone=ebone->next) { if(arm->layer & ebone->layer) { if(ebone->flag & BONE_SELECTED) { - if(ebone->parent) { - /* for nice selection */ - ebone->parent->flag &= ~(BONE_TIPSEL); + + if(arm->flag & ARM_MIRROR_EDIT) + flipbone = armature_bone_get_mirrored(ebone); - if(val==1) ebone->parent= NULL; - ebone->flag &= ~BONE_CONNECTED; - } + if (flipbone) + editbone_clear_parent(flipbone, val); + editbone_clear_parent(ebone, val); } } } @@ -3179,3 +3223,4 @@ void transform_armature_mirror_update(void) + diff --git a/source/blender/src/editimasel.c b/source/blender/src/editimasel.c index abc19b53671..d57df3aaccf 100644 --- a/source/blender/src/editimasel.c +++ b/source/blender/src/editimasel.c @@ -117,12 +117,14 @@ static int imasel_has_func(SpaceImaSel *simasel) return 0; } -/* ugly, needs to be moved to platform specific files - elubie */ -#if defined WIN32 || defined __BeOS +#if defined __BeOS static int fnmatch(const char *pattern, const char *string, int flags) { return 0; } +#elif defined WIN32 && !defined _LIBC + /* use fnmatch included in blenlib */ + #include "BLI_fnmatch.h" #else #include #endif diff --git a/source/blender/src/editseq.c b/source/blender/src/editseq.c index 8f328afc222..27ee7a14315 100644 --- a/source/blender/src/editseq.c +++ b/source/blender/src/editseq.c @@ -777,7 +777,7 @@ void mouse_select_seq(void) if (marker) { int oldflag; /* select timeline marker */ - if ((G.qual & LR_SHIFTKEY)==0) { + if (G.qual & LR_SHIFTKEY) { oldflag= marker->flag; deselect_markers(0, 0); @@ -985,7 +985,6 @@ static Sequence *sfile_to_sequence(SpaceFile *sfile, int cfra, int machine, int if(sfile->filelist[a].flags & ACTIVE) { if( (sfile->filelist[a].type & S_IFDIR)==0 ) { strncpy(se->name, sfile->filelist[a].relname, FILE_MAXFILE-1); - se->ok= 1; se++; } } @@ -993,7 +992,6 @@ static Sequence *sfile_to_sequence(SpaceFile *sfile, int cfra, int machine, int /* no selected file: */ if(totsel==1 && se==strip->stripdata) { strncpy(se->name, sfile->file, FILE_MAXFILE-1); - se->ok= 1; } /* last active name */ @@ -1010,7 +1008,7 @@ static int sfile_to_mv_sequence_load(SpaceFile *sfile, int cfra, struct anim *anim; Strip *strip; StripElem *se; - int totframe, a; + int totframe; char name[160], rel[160]; char str[FILE_MAXDIR+FILE_MAXFILE]; @@ -1054,7 +1052,7 @@ static int sfile_to_mv_sequence_load(SpaceFile *sfile, int cfra, strip->len= totframe; strip->us= 1; strncpy(strip->dir, name, FILE_MAXDIR-1); - strip->stripdata= se= MEM_callocN(totframe*sizeof(StripElem), "stripelem"); + strip->stripdata= se= MEM_callocN(sizeof(StripElem), "stripelem"); /* name movie in first strip */ if(index<0) @@ -1062,11 +1060,6 @@ static int sfile_to_mv_sequence_load(SpaceFile *sfile, int cfra, else strncpy(se->name, sfile->filelist[index].relname, FILE_MAXFILE-1); - for(a=1; a<=totframe; a++, se++) { - se->ok= 1; - se->nr= a; - } - /* last active name */ strncpy(last_imagename, seq->strip->dir, FILE_MAXDIR-1); return(cfra+totframe); @@ -1111,7 +1104,6 @@ static Sequence *sfile_to_ramsnd_sequence(SpaceFile *sfile, Strip *strip; StripElem *se; double totframe; - int a; char name[160], rel[160]; char str[256]; @@ -1157,17 +1149,11 @@ static Sequence *sfile_to_ramsnd_sequence(SpaceFile *sfile, strip->len= totframe; strip->us= 1; strncpy(strip->dir, name, FILE_MAXDIR-1); - strip->stripdata= se= MEM_callocN(totframe*sizeof(StripElem), "stripelem"); + strip->stripdata= se= MEM_callocN(sizeof(StripElem), "stripelem"); /* name sound in first strip */ strncpy(se->name, sfile->file, FILE_MAXFILE-1); - for(a=1; a<=totframe; a++, se++) { - se->ok= 2; /* why? */ - se->ibuf= 0; - se->nr= a; - } - /* last active name */ strncpy(last_sounddir, seq->strip->dir, FILE_MAXDIR-1); @@ -1181,7 +1167,7 @@ static int sfile_to_hdsnd_sequence_load(SpaceFile *sfile, int cfra, struct hdaudio *hdaudio; Strip *strip; StripElem *se; - int totframe, a; + int totframe; char name[160], rel[160]; char str[FILE_MAXDIR+FILE_MAXFILE]; @@ -1224,7 +1210,7 @@ static int sfile_to_hdsnd_sequence_load(SpaceFile *sfile, int cfra, strip->len= totframe; strip->us= 1; strncpy(strip->dir, name, FILE_MAXDIR-1); - strip->stripdata= se= MEM_callocN(totframe*sizeof(StripElem), "stripelem"); + strip->stripdata= se= MEM_callocN(sizeof(StripElem), "stripelem"); /* name movie in first strip */ if(index<0) @@ -1232,12 +1218,6 @@ static int sfile_to_hdsnd_sequence_load(SpaceFile *sfile, int cfra, else strncpy(se->name, sfile->filelist[index].relname, FILE_MAXFILE-1); - for(a=1; a<=totframe; a++, se++) { - se->ok= 2; - se->ibuf = 0; - se->nr= a; - } - /* last active name */ strncpy(last_sounddir, seq->strip->dir, FILE_MAXDIR-1); return(cfra+totframe); @@ -2013,7 +1993,7 @@ void change_sequence(void) last_seq->sfra= sce->r.sfra; /* bad code to change seq->len? update_changed_seq_and_deps() expects the strip->len to be OK */ - new_stripdata(last_seq); + new_tstripdata(last_seq); update_changed_seq_and_deps(last_seq, 1, 1); @@ -2169,25 +2149,23 @@ void del_seq(void) static void recurs_dupli_seq(ListBase *old, ListBase *new) { - Sequence *seq, *seqn; + Sequence *seq; + Sequence *seqn = 0; Sequence *last_seq = get_last_seq(); - StripElem *se; - int a; seq= old->first; while(seq) { seq->tmp= NULL; if(seq->flag & SELECT) { - if(seq->type==SEQ_META) { seqn= MEM_dupallocN(seq); seq->tmp= seqn; BLI_addtail(new, seqn); seqn->strip= MEM_dupallocN(seq->strip); - - if(seq->len>0) seq->strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem"); + seqn->strip->stripdata = 0; + seqn->strip->tstripdata = 0; seq->flag &= SEQ_DESEL; seqn->flag &= ~(SEQ_LEFTSEL+SEQ_RIGHTSEL); @@ -2202,8 +2180,8 @@ static void recurs_dupli_seq(ListBase *old, ListBase *new) BLI_addtail(new, seqn); seqn->strip= MEM_dupallocN(seq->strip); - - if(seq->len>0) seqn->strip->stripdata = MEM_callocN(seq->len*sizeof(StripElem), "stripelem"); + seqn->strip->stripdata = 0; + seqn->strip->tstripdata = 0; seq->flag &= SEQ_DESEL; seqn->flag &= ~(SEQ_LEFTSEL+SEQ_RIGHTSEL); @@ -2214,20 +2192,11 @@ static void recurs_dupli_seq(ListBase *old, ListBase *new) BLI_addtail(new, seqn); seqn->strip= MEM_dupallocN(seq->strip); + seqn->strip->stripdata = + MEM_dupallocN(seq->strip->stripdata); + seqn->strip->tstripdata = 0; seqn->anim= 0; - if(seqn->len>0) { - seqn->strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem"); - /* copy first elem */ - *seqn->strip->stripdata= *seq->strip->stripdata; - se= seqn->strip->stripdata; - a= seq->len; - while(a--) { - se->ok= 1; - se++; - } - } - seq->flag &= SEQ_DESEL; seqn->flag &= ~(SEQ_LEFTSEL+SEQ_RIGHTSEL); } @@ -2237,22 +2206,14 @@ static void recurs_dupli_seq(ListBase *old, ListBase *new) BLI_addtail(new, seqn); seqn->strip= MEM_dupallocN(seq->strip); + seqn->strip->stripdata = + MEM_dupallocN(seq->strip->stripdata); + seqn->strip->tstripdata = 0; + seqn->anim= 0; seqn->sound->id.us++; if(seqn->ipo) seqn->ipo->id.us++; - if(seqn->len>0) { - seqn->strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem"); - /* copy first elem */ - *seqn->strip->stripdata= *seq->strip->stripdata; - se= seqn->strip->stripdata; - a= seq->len; - while(a--) { - se->ok= 1; - se++; - } - } - seq->flag &= SEQ_DESEL; seqn->flag &= ~(SEQ_LEFTSEL+SEQ_RIGHTSEL); } @@ -2262,36 +2223,29 @@ static void recurs_dupli_seq(ListBase *old, ListBase *new) BLI_addtail(new, seqn); seqn->strip= MEM_dupallocN(seq->strip); + seqn->strip->stripdata = + MEM_dupallocN(seq->strip->stripdata); + seqn->strip->tstripdata = 0; seqn->anim= 0; seqn->hdaudio = 0; if(seqn->ipo) seqn->ipo->id.us++; - if(seqn->len>0) { - seqn->strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem"); - /* copy first elem */ - *seqn->strip->stripdata= *seq->strip->stripdata; - se= seqn->strip->stripdata; - a= seq->len; - while(a--) { - se->ok= 1; - se++; - } - } - seq->flag &= SEQ_DESEL; seqn->flag &= ~(SEQ_LEFTSEL+SEQ_RIGHTSEL); - } - else if(seq->type < SEQ_EFFECT) { + } else if(seq->type == SEQ_IMAGE) { seqn= MEM_dupallocN(seq); seq->tmp= seqn; BLI_addtail(new, seqn); - seqn->strip->us++; + seqn->strip= MEM_dupallocN(seq->strip); + seqn->strip->stripdata = + MEM_dupallocN(seq->strip->stripdata); + seqn->strip->tstripdata = 0; + seq->flag &= SEQ_DESEL; seqn->flag &= ~(SEQ_LEFTSEL+SEQ_RIGHTSEL); - } - else { + } else if(seq->type >= SEQ_EFFECT) { seqn= MEM_dupallocN(seq); seq->tmp= seqn; BLI_addtail(new, seqn); @@ -2310,12 +2264,16 @@ static void recurs_dupli_seq(ListBase *old, ListBase *new) } seqn->strip= MEM_dupallocN(seq->strip); - - if(seq->len>0) seq->strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem"); + seqn->strip->stripdata = 0; + seqn->strip->tstripdata = 0; seq->flag &= SEQ_DESEL; seqn->flag &= ~(SEQ_LEFTSEL+SEQ_RIGHTSEL); + } else { + fprintf(stderr, "Aiiiiekkk! sequence type not " + "handled in duplicate!\nExpect a crash" + " now...\n"); } if (seq == last_seq) { set_last_seq(seqn); @@ -2564,7 +2522,7 @@ void make_meta(void) seqm->strip= MEM_callocN(sizeof(Strip), "metastrip"); seqm->strip->len= seqm->len; seqm->strip->us= 1; - if(seqm->len) seqm->strip->stripdata= MEM_callocN(seqm->len*sizeof(StripElem), "metastripdata"); + set_meta_stripdata(seqm); BIF_undo_push("Make Meta Strip, Sequencer"); @@ -3496,8 +3454,6 @@ void seq_separate_images(void) /* new stripdata */ strip_new->stripdata= se_new= MEM_callocN(sizeof(StripElem)*1, "stripelem"); strncpy(se_new->name, se->name, FILE_MAXFILE-1); - se_new->ok= 1; - calc_sequence(seq_new); seq_new->flag &= ~SEQ_OVERLAP; if (test_overlap_seq(seq_new)) { diff --git a/source/blender/src/filesel.c b/source/blender/src/filesel.c index 10f234fcd21..599c6d5aae2 100644 --- a/source/blender/src/filesel.c +++ b/source/blender/src/filesel.c @@ -116,11 +116,14 @@ #include "FTF_Api.h" #endif -#if defined WIN32 || defined __BeOS +#if defined __BeOS static int fnmatch(const char *pattern, const char *string, int flags) { return 0; } +#elif defined WIN32 && !defined _LIBC + /* use fnmatch included in blenlib */ + #include "BLI_fnmatch.h" #else #include #endif diff --git a/source/blender/src/poseobject.c b/source/blender/src/poseobject.c index c0835c84e62..68af3d7c64c 100644 --- a/source/blender/src/poseobject.c +++ b/source/blender/src/poseobject.c @@ -917,6 +917,7 @@ void pose_movetolayer(void) else if (G.obedit) { /* the check for editbone layer moving needs to occur before posemode one to work */ EditBone *ebo; + EditBone *flipBone; for (ebo= G.edbo.first; ebo; ebo= ebo->next) { if (arm->layer & ebo->layer) { @@ -931,8 +932,14 @@ void pose_movetolayer(void) for (ebo= G.edbo.first; ebo; ebo= ebo->next) { if (arm->layer & ebo->layer) { - if (ebo->flag & BONE_SELECTED) + if (ebo->flag & BONE_SELECTED) { ebo->layer= lay; + if (arm->flag & ARM_MIRROR_EDIT) { + flipBone = armature_bone_get_mirrored(ebo); + if (flipBone) + flipBone->layer = lay; + } + } } } diff --git a/source/blender/src/sequence.c b/source/blender/src/sequence.c index e93cc1b1075..1e0026cde93 100644 --- a/source/blender/src/sequence.c +++ b/source/blender/src/sequence.c @@ -75,15 +75,18 @@ int seqrectx, seqrecty; -void free_stripdata(int len, StripElem *se) +void free_tstripdata(int len, TStripElem *se) { - StripElem *seo; + TStripElem *seo; int a; seo= se; + if (!se) { + return; + } for(a=0; aibuf && se->ok!=2) { + if(se->ibuf && se->ok != STRIPELEM_META) { IMB_freeImBuf(se->ibuf); se->ibuf = 0; } @@ -103,18 +106,20 @@ void free_strip(Strip *strip) } if(strip->stripdata) { - free_stripdata(strip->len, strip->stripdata); + MEM_freeN(strip->stripdata); } + + free_tstripdata(strip->len, strip->tstripdata); + MEM_freeN(strip); } -void new_stripdata(Sequence *seq) +void new_tstripdata(Sequence *seq) { if(seq->strip) { - if(seq->strip->stripdata) free_stripdata(seq->strip->len, seq->strip->stripdata); - seq->strip->stripdata= 0; + free_tstripdata(seq->strip->len, seq->strip->tstripdata); + seq->strip->tstripdata= 0; seq->strip->len= seq->len; - if(seq->len>0) seq->strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelems"); } } @@ -265,7 +270,7 @@ void calc_sequence(Sequence *seq) } if(seq->strip && seq->len!=seq->strip->len) { - new_stripdata(seq); + new_tstripdata(seq); } } @@ -284,7 +289,7 @@ void calc_sequence(Sequence *seq) seq->len= max-min; if(seq->strip && seq->len!=seq->strip->len) { - new_stripdata(seq); + new_tstripdata(seq); } } } @@ -426,9 +431,9 @@ static void multibuf(ImBuf *ibuf, float fmul) } } -static void do_effect(int cfra, Sequence *seq, StripElem *se) +static void do_effect(int cfra, Sequence *seq, TStripElem *se) { - StripElem *se1, *se2, *se3; + TStripElem *se1, *se2, *se3; float fac, facf; int x, y; int early_out; @@ -464,14 +469,13 @@ static void do_effect(int cfra, Sequence *seq, StripElem *se) return; } - /* if metastrip: other se's */ - if(se->se1->ok==2) se1= se->se1->se1; + if(se->se1->ok == STRIPELEM_META) se1= se->se1->se1; else se1= se->se1; - if(se->se2->ok==2) se2= se->se2->se1; + if(se->se2->ok == STRIPELEM_META) se2= se->se2->se1; else se2= se->se2; - if(se->se3->ok==2) se3= se->se3->se1; + if(se->se3->ok == STRIPELEM_META) se3= se->se3->se1; else se3= se->se3; if ( (se1==0 || se2==0 || se3==0) @@ -487,8 +491,7 @@ static void do_effect(int cfra, Sequence *seq, StripElem *se) return; } - /* if metastrip: other se's */ - if(se->se1->ok==2) se1= se->se1->se1; + if(se->se1->ok == STRIPELEM_META) se1= se->se1->se1; else se1= se->se1; if (se1 == 0 || se1->ibuf == 0) { @@ -508,8 +511,7 @@ static void do_effect(int cfra, Sequence *seq, StripElem *se) return; } - /* if metastrip: other se's */ - if(se->se2->ok==2) se2= se->se2->se1; + if(se->se2->ok == STRIPELEM_META) se2= se->se2->se1; else se2= se->se2; if (se2 == 0 || se2->ibuf == 0) { @@ -548,17 +550,11 @@ static void do_effect(int cfra, Sequence *seq, StripElem *se) se->ibuf); } -StripElem *give_stripelem(Sequence *seq, int cfra) +static int give_stripelem_index(Sequence *seq, int cfra) { - Strip *strip; - StripElem *se; int nr; - strip= seq->strip; - se= strip->stripdata; - - if(se==0) return 0; - if(seq->startdisp >cfra || seq->enddisp <= cfra) return 0; + if(seq->startdisp >cfra || seq->enddisp <= cfra) return -1; if(seq->flag&SEQ_REVERSE_FRAMES) { /*reverse frame in this sequence */ @@ -574,13 +570,51 @@ StripElem *give_stripelem(Sequence *seq, int cfra) if (seq->strobe > 1.0) { nr -= (int)fmod((double)nr, (double)seq->strobe); } + + return nr; +} + +TStripElem *give_tstripelem(Sequence *seq, int cfra) +{ + TStripElem *se; + int nr; + + se = seq->strip->tstripdata; + if (se == 0 && seq->len > 0) { + int i; + se = seq->strip->tstripdata = MEM_callocN( + seq->len*sizeof(TStripElem), "tstripelems"); + for (i = 0; i < seq->len; i++) { + se[i].ok = STRIPELEM_OK; + } + } + nr = give_stripelem_index(seq, cfra); + + if (nr == -1) return 0; + if (se == 0) return 0; - se+= nr; /* don't get confused by the increment, this is the same as strip->stripdata[nr], which works on some compilers...*/ + se+= nr; se->nr= nr; return se; } +StripElem *give_stripelem(Sequence *seq, int cfra) +{ + StripElem *se; + int nr; + + se = seq->strip->stripdata; + nr = give_stripelem_index(seq, cfra); + + if (nr == -1) return 0; + if (se == 0) return 0; + + se += nr; + + return se; +} + static int evaluate_seq_frame_gen( Sequence ** seq_arr, ListBase *seqbase, int cfra) { @@ -664,36 +698,57 @@ static Sequence * get_shown_seq_from_metastrip(Sequence * seqm, int cfra) void set_meta_stripdata(Sequence *seqm) { Sequence *seq; - StripElem *se; + TStripElem *se; int a, cfra; + se= seqm->strip->tstripdata; + + if (se == 0 && seqm->len > 0) { + int i; + se = seqm->strip->tstripdata = MEM_callocN( + seqm->len*sizeof(TStripElem), "tstripelems"); + for (i = 0; i < seqm->len; i++) { + se[i].ok = STRIPELEM_META; + } + } + /* sets all ->se1 pointers in stripdata, to read the ibuf from it */ - se= seqm->strip->stripdata; for(a=0; alen; a++, se++) { cfra= a+seqm->start; seq = get_shown_seq_from_metastrip(seqm, cfra); if (seq) { - se->se1= give_stripelem(seq, cfra); + se->se1= give_tstripelem(seq, cfra); } else { se->se1= 0; } } } -static void do_build_seq_ibuf(Sequence * seq, int cfra) +static TStripElem* do_build_seq_recursively(Sequence * seq, int cfra); + +static void do_build_seq_ibuf(Sequence * seq, TStripElem *se, int cfra) { - StripElem *se = seq->curelem; char name[FILE_MAXDIR+FILE_MAXFILE]; if(seq->type == SEQ_META) { - se->ok= 2; - if(se->se1==0) set_meta_stripdata(seq); + if(seq->seqbase.first) { + Sequence * seqmshown= + get_shown_seq_from_metastrip(seq, cfra); + if (seqmshown) { + if(cfra< seq->start) + do_build_seq_recursively(seqmshown, seq->start); + else if(cfra> seq->start+seq->len-1) + do_build_seq_recursively(seqmshown, seq->start + seq->len-1); + else do_build_seq_recursively(seqmshown, cfra); + } + } + + se->ok = STRIPELEM_META; + if(se->se1 == 0) set_meta_stripdata(seq); if(se->se1) { se->ibuf= se->se1->ibuf; } - } else if(seq->type == SEQ_RAM_SOUND || seq->type == SEQ_HD_SOUND) { - se->ok= 2; } else if(seq->type & SEQ_EFFECT) { /* test if image is too small or discarded from cache: reload */ @@ -706,22 +761,13 @@ static void do_build_seq_ibuf(Sequence * seq, int cfra) /* should the effect be recalculated? */ - if(se->ibuf==0 - || (seq->seq1 && se->se1 != seq->seq1->curelem) - || (seq->seq2 && se->se2 != seq->seq2->curelem) - || (seq->seq3 && se->se3 != seq->seq3->curelem)) { - if (seq->seq1) se->se1= seq->seq1->curelem; - if (seq->seq2) se->se2= seq->seq2->curelem; - if (seq->seq3) se->se3= seq->seq3->curelem; - - if(se->ibuf==NULL) { - /* if one of two first inputs are rectfloat, output is float too */ - if((se->se1 && se->se1->ibuf && se->se1->ibuf->rect_float) || - (se->se2 && se->se2->ibuf && se->se2->ibuf->rect_float)) - se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rectfloat, 0); - else - se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rect, 0); - } + if(se->ibuf == 0) { + /* if one of two first inputs are rectfloat, output is float too */ + if((se->se1 && se->se1->ibuf && se->se1->ibuf->rect_float) || + (se->se2 && se->se2->ibuf && se->se2->ibuf->rect_float)) + se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rectfloat, 0); + else + se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rect, 0); do_effect(cfra, seq, se); } @@ -743,27 +789,30 @@ static void do_build_seq_ibuf(Sequence * seq, int cfra) if(se->ibuf->x < seqrectx || se->ibuf->y < seqrecty || !(se->ibuf->rect || se->ibuf->rect_float)) { IMB_freeImBuf(se->ibuf); se->ibuf= 0; - se->ok= 1; + se->ok= STRIPELEM_OK; } } if(seq->type==SEQ_IMAGE) { - if(se->ok && se->ibuf==0) { + if(se->ok == STRIPELEM_OK && se->ibuf==0) { + StripElem * s_elem = give_stripelem(seq, cfra); + /* if playanim or render: no waitcursor */ if((G.f & G_PLAYANIM)==0) waitcursor(1); strncpy(name, seq->strip->dir, FILE_MAXDIR-1); - strncat(name, se->name, FILE_MAXFILE); + strncat(name, s_elem->name, FILE_MAXFILE); BLI_convertstringcode(name, G.sce, G.scene->r.cfra); se->ibuf= IMB_loadiffname(name, IB_rect); if((G.f & G_PLAYANIM)==0) waitcursor(0); - if(se->ibuf==0) se->ok= 0; - else { + if(se->ibuf == 0) { + se->ok = STRIPELEM_FAILED; + } else { if(seq->flag & SEQ_MAKE_PREMUL) { if(se->ibuf->depth==32 && se->ibuf->zbuf==0) converttopremul(se->ibuf); } @@ -778,7 +827,7 @@ static void do_build_seq_ibuf(Sequence * seq, int cfra) } } else if(seq->type==SEQ_MOVIE) { - if(se->ok && se->ibuf==0) { + if(se->ok == STRIPELEM_OK && se->ibuf==0) { if(seq->anim==0) { strncpy(name, seq->strip->dir, FILE_MAXDIR-1); strncat(name, seq->strip->stripdata->name, FILE_MAXFILE-1); @@ -791,8 +840,9 @@ static void do_build_seq_ibuf(Sequence * seq, int cfra) se->ibuf = IMB_anim_absolute(seq->anim, se->nr); } - if(se->ibuf==0) se->ok= 0; - else { + if(se->ibuf == 0) { + se->ok = STRIPELEM_FAILED; + } else { if(seq->flag & SEQ_MAKE_PREMUL) { if(se->ibuf->depth==32) converttopremul(se->ibuf); } @@ -893,21 +943,23 @@ static void do_build_seq_ibuf(Sequence * seq, int cfra) } } - if (se->ibuf) { + if (se->ibuf && seq->type != SEQ_META) { IMB_cache_limiter_insert(se->ibuf); IMB_cache_limiter_ref(se->ibuf); IMB_cache_limiter_touch(se->ibuf); } } -static void do_build_seq_recursively(Sequence * seq, int cfra); - -static void do_effect_seq_recursively(int cfra, Sequence * seq, StripElem *se) +static void do_effect_seq_recursively(Sequence * seq, TStripElem *se, int cfra) { float fac, facf; struct SeqEffectHandle sh = get_sequence_effect(seq); int early_out; + se->se1 = 0; + se->se2 = 0; + se->se3 = 0; + if(seq->ipo && seq->ipo->curve.first) { do_seq_ipo(seq); fac= seq->facf0; @@ -924,79 +976,50 @@ static void do_effect_seq_recursively(int cfra, Sequence * seq, StripElem *se) /* no input needed */ break; case 0: - do_build_seq_recursively(seq->seq1, cfra); - do_build_seq_recursively(seq->seq2, cfra); + se->se1 = do_build_seq_recursively(seq->seq1, cfra); + se->se2 = do_build_seq_recursively(seq->seq2, cfra); if (seq->seq3) { - do_build_seq_recursively(seq->seq3, cfra); + se->se3 = do_build_seq_recursively(seq->seq3, cfra); } break; case 1: - do_build_seq_recursively(seq->seq1, cfra); + se->se1 = do_build_seq_recursively(seq->seq1, cfra); break; case 2: - do_build_seq_recursively(seq->seq2, cfra); + se->se2 = do_build_seq_recursively(seq->seq2, cfra); break; } - do_build_seq_ibuf(seq, cfra); + do_build_seq_ibuf(seq, se, cfra); /* children are not needed anymore ... */ - switch (early_out) { - case 0: - if (seq->seq1->curelem && seq->seq1->curelem->ibuf) - IMB_cache_limiter_unref(seq->seq1->curelem->ibuf); - if (seq->seq2->curelem && seq->seq2->curelem->ibuf) - IMB_cache_limiter_unref(seq->seq2->curelem->ibuf); - if (seq->seq3) { - if (seq->seq3->curelem && seq->seq3->curelem->ibuf) - IMB_cache_limiter_unref( - seq->seq3->curelem->ibuf); - } - break; - case 1: - if (seq->seq1->curelem && seq->seq1->curelem->ibuf) - IMB_cache_limiter_unref(seq->seq1->curelem->ibuf); - break; - case 2: - if (seq->seq2->curelem && seq->seq2->curelem->ibuf) - IMB_cache_limiter_unref(seq->seq2->curelem->ibuf); - break; + if (se->se1 && se->se1->ibuf) { + IMB_cache_limiter_unref(se->se1->ibuf); + } + if (se->se2 && se->se2->ibuf) { + IMB_cache_limiter_unref(se->se2->ibuf); + } + if (se->se3 && se->se3->ibuf) { + IMB_cache_limiter_unref(se->se3->ibuf); } } -static void do_build_seq_recursively_impl(Sequence * seq, int cfra) +static TStripElem* do_build_seq_recursively_impl(Sequence * seq, int cfra) { - StripElem *se; + TStripElem *se; - se = seq->curelem = give_stripelem(seq, cfra); + se = give_tstripelem(seq, cfra); if(se) { - int unref_meta = FALSE; - if(seq->seqbase.first) { - Sequence * seqmshown= get_shown_seq_from_metastrip(seq, cfra); - if (seqmshown) { - if(cfra< seq->start) - do_build_seq_recursively(seqmshown, seq->start); - else if(cfra> seq->start+seq->len-1) - do_build_seq_recursively(seqmshown, seq->start + seq->len-1); - else do_build_seq_recursively(seqmshown, cfra); - - unref_meta = TRUE; - } - } - if (seq->type & SEQ_EFFECT) { - do_effect_seq_recursively(cfra, seq, se); + do_effect_seq_recursively(seq, se, cfra); } else { - do_build_seq_ibuf(seq, cfra); - } - - if(unref_meta && seq->curelem->ibuf) { - IMB_cache_limiter_unref(seq->curelem->ibuf); + do_build_seq_ibuf(seq, se, cfra); } } + return se; } /* FIXME: @@ -1007,16 +1030,16 @@ instead of faking using the blend code below... */ -static void do_handle_speed_effect(Sequence * seq, int cfra) +static TStripElem* do_handle_speed_effect(Sequence * seq, int cfra) { SpeedControlVars * s = (SpeedControlVars *)seq->effectdata; int nr = cfra - seq->start; float f_cfra; int cfra_left; int cfra_right; - StripElem * se = 0; - StripElem * se1 = 0; - StripElem * se2 = 0; + TStripElem * se = 0; + TStripElem * se1 = 0; + TStripElem * se2 = 0; sequence_effect_speed_rebuild_map(seq, 0); @@ -1025,7 +1048,7 @@ static void do_handle_speed_effect(Sequence * seq, int cfra) cfra_left = (int) floor(f_cfra); cfra_right = (int) ceil(f_cfra); - se = seq->curelem = give_stripelem(seq, cfra); + se = give_tstripelem(seq, cfra); if (cfra_left == cfra_right || (s->flags & SEQ_SPEED_BLEND) == 0) { @@ -1038,9 +1061,8 @@ static void do_handle_speed_effect(Sequence * seq, int cfra) } if (se->ibuf == NULL) { - do_build_seq_recursively_impl(seq->seq1, cfra_left); - - se1 = seq->seq1->curelem; + se1 = do_build_seq_recursively_impl( + seq->seq1, cfra_left); if((se1 && se1->ibuf && se1->ibuf->rect_float)) se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rectfloat, 0); @@ -1072,11 +1094,10 @@ static void do_handle_speed_effect(Sequence * seq, int cfra) } if (se->ibuf == NULL) { - do_build_seq_recursively_impl(seq->seq1, cfra_left); - se1 = seq->seq1->curelem; - do_build_seq_recursively_impl(seq->seq1, cfra_right); - se2 = seq->seq1->curelem; - + se1 = do_build_seq_recursively_impl( + seq->seq1, cfra_left); + se2 = do_build_seq_recursively_impl( + seq->seq1, cfra_right); if((se1 && se1->ibuf && se1->ibuf->rect_float)) se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rectfloat, 0); @@ -1110,35 +1131,43 @@ static void do_handle_speed_effect(Sequence * seq, int cfra) IMB_cache_limiter_unref(se1->ibuf); if (se2 && se2->ibuf) IMB_cache_limiter_unref(se2->ibuf); + + return se; } /* * build all ibufs recursively * - * if successfull, seq->curelem->ibuf contains the (referenced!) imbuf + * if successfull, the returned TStripElem contains the (referenced!) imbuf * that means: you _must_ call * - * IMB_cache_limiter_unref(seq->curelem->ibuf); + * IMB_cache_limiter_unref(rval); * - * if seq->curelem exists! + * if rval != 0 * */ -static void do_build_seq_recursively(Sequence * seq, int cfra) +static TStripElem* do_build_seq_recursively(Sequence * seq, int cfra) { if (seq->type == SEQ_SPEED) { - do_handle_speed_effect(seq, cfra); + return do_handle_speed_effect(seq, cfra); } else { - do_build_seq_recursively_impl(seq, cfra); + return do_build_seq_recursively_impl(seq, cfra); } } -ImBuf *give_ibuf_seq(int rectx, int recty, int cfra, int chanshown) +/* + * returned ImBuf is refed! + * you have to unref after usage! + */ + +static ImBuf *give_ibuf_seq_impl(int rectx, int recty, int cfra, int chanshown) { Sequence *seqfirst=0; Editing *ed; int count; ListBase *seqbasep; + TStripElem *se; ed= G.scene->ed; if(ed==0) return 0; @@ -1160,18 +1189,44 @@ ImBuf *give_ibuf_seq(int rectx, int recty, int cfra, int chanshown) return 0; } - do_build_seq_recursively(seqfirst, cfra); + se = do_build_seq_recursively(seqfirst, cfra); - if(!seqfirst->curelem) { + if(!se) { return 0; } - if (seqfirst->curelem->ibuf) { - IMB_cache_limiter_unref(seqfirst->curelem->ibuf); + return se->ibuf; +} + +ImBuf *give_ibuf_seq_direct(int rectx, int recty, int cfra, + Sequence * seq) +{ + TStripElem* se; + + seqrectx= rectx; /* bad bad global! */ + seqrecty= recty; + + se = do_build_seq_recursively(seq, cfra); + + if(!se) { + return 0; } - return seqfirst->curelem->ibuf; + if (se->ibuf) { + IMB_cache_limiter_unref(se->ibuf); + } + return se->ibuf; +} + +ImBuf *give_ibuf_seq(int rectx, int recty, int cfra, int chanshown) +{ + ImBuf* i = give_ibuf_seq_impl(rectx, recty, cfra, chanshown); + + if (i) { + IMB_cache_limiter_unref(i); + } + return i; } /* threading api */ @@ -1253,12 +1308,8 @@ static void * seq_prefetch_thread(void * This_) This->running = TRUE; if (e->cfra >= s_last) { - e->ibuf = give_ibuf_seq(e->rectx, e->recty, e->cfra, - e->chanshown); - } - - if (e->ibuf) { - IMB_cache_limiter_ref(e->ibuf); + e->ibuf = give_ibuf_seq_impl( + e->rectx, e->recty, e->cfra, e->chanshown); } pthread_mutex_lock(&queue_lock); @@ -1413,7 +1464,7 @@ void seq_wait_for_prefetch_ready() fprintf(stderr, "SEQ-THREAD: prefetch done\n"); } -ImBuf * give_ibuf_threaded(int rectx, int recty, int cfra, int chanshown) +ImBuf * give_ibuf_seq_threaded(int rectx, int recty, int cfra, int chanshown) { PrefetchQueueElem * e = 0; int found_something = FALSE; @@ -1493,13 +1544,13 @@ ImBuf * give_ibuf_threaded(int rectx, int recty, int cfra, int chanshown) /* Functions to free imbuf and anim data on changes */ -static void free_imbuf_strip_elem(StripElem *se) +static void free_imbuf_strip_elem(TStripElem *se) { if (se->ibuf) { - if (se->ok != 2) + if (se->ok != STRIPELEM_META && se->ibuf != 0) IMB_freeImBuf(se->ibuf); se->ibuf= 0; - se->ok= 1; + se->ok= STRIPELEM_OK; se->se1= se->se2= se->se3= 0; } } @@ -1516,15 +1567,17 @@ void free_imbuf_seq_except(int cfra) { Editing *ed= G.scene->ed; Sequence *seq; - StripElem *se; + TStripElem *se; int a; if(ed==0) return; WHILE_SEQ(&ed->seqbase) { if(seq->strip) { - for(a=0, se= seq->strip->stripdata; alen; a++, se++) - if(se!=seq->curelem) + TStripElem * curelem = give_tstripelem(seq, cfra); + + for(a=0, se= seq->strip->tstripdata; alen; a++, se++) + if(se != curelem) free_imbuf_strip_elem(se); if(seq->type==SEQ_MOVIE) @@ -1539,15 +1592,17 @@ void free_imbuf_seq() { Editing *ed= G.scene->ed; Sequence *seq; - StripElem *se; + TStripElem *se; int a; if(ed==0) return; WHILE_SEQ(&ed->seqbase) { if(seq->strip) { - for(a=0, se= seq->strip->stripdata; alen; a++, se++) - free_imbuf_strip_elem(se); + if (seq->strip->tstripdata) { + for(a=0, se= seq->strip->tstripdata; alen; a++, se++) + free_imbuf_strip_elem(se); + } if(seq->type==SEQ_MOVIE) free_anim_seq(seq); @@ -1582,7 +1637,7 @@ static int update_changed_seq_recurs(Sequence *seq, Sequence *changed_seq, int l { Sequence *subseq; int a, free_imbuf = 0; - StripElem *se; + TStripElem *se; /* recurs downwards to see if this seq depends on the changed seq */ @@ -1594,24 +1649,27 @@ static int update_changed_seq_recurs(Sequence *seq, Sequence *changed_seq, int l for(subseq=seq->seqbase.first; subseq; subseq=subseq->next) if(update_changed_seq_recurs(subseq, changed_seq, len_change, ibuf_change)) - free_imbuf = 1; + free_imbuf = TRUE; if(seq->seq1) if(update_changed_seq_recurs(seq->seq1, changed_seq, len_change, ibuf_change)) - free_imbuf = 1; + free_imbuf = TRUE; if(seq->seq2 && (seq->seq2 != seq->seq1)) if(update_changed_seq_recurs(seq->seq2, changed_seq, len_change, ibuf_change)) - free_imbuf = 1; + free_imbuf = TRUE; if(seq->seq3 && (seq->seq3 != seq->seq1) && (seq->seq3 != seq->seq2)) if(update_changed_seq_recurs(seq->seq3, changed_seq, len_change, ibuf_change)) - free_imbuf = 1; + free_imbuf = TRUE; if(free_imbuf) { if(ibuf_change) { - for(a=0, se= seq->strip->stripdata; alen; a++, se++) - free_imbuf_strip_elem(se); + se= seq->strip->tstripdata; + if (se) { + for(a=0; alen; a++, se++) + free_imbuf_strip_elem(se); + } - if(seq->type==SEQ_MOVIE) + if(seq->type == SEQ_MOVIE) free_anim_seq(seq); if(seq->type == SEQ_SPEED) { sequence_effect_speed_rebuild_map(seq, 1); @@ -1646,7 +1704,6 @@ void do_render_seq(RenderResult *rr, int cfra) ibuf= give_ibuf_seq(rr->rectx, rr->recty, cfra, 0); if(ibuf) { - if(ibuf->rect_float) { if (!rr->rectf) rr->rectf= MEM_mallocN(4*sizeof(float)*rr->rectx*rr->recty, "render_seq rectf"); diff --git a/source/blender/src/transform_conversions.c b/source/blender/src/transform_conversions.c index 259e82968da..d357ad1bce5 100644 --- a/source/blender/src/transform_conversions.c +++ b/source/blender/src/transform_conversions.c @@ -2694,11 +2694,11 @@ void autokeyframe_ob_cb_func(Object *ob, int tmode) char *actname=""; if (G.flags & G_RECORDKEYS) { - if(ob->ipoflag & OB_ACTION_OB) + if (ob->ipoflag & OB_ACTION_OB) actname= "Object"; - - if(U.uiflag & USER_KEYINSERTAVAI) { - if(ob->ipo || ob->action) { + + if (U.uiflag & USER_KEYINSERTAVAI) { + if (ob->ipo || ob->action) { ID *id= (ID *)(ob); if (ob->ipo) { @@ -2714,7 +2714,7 @@ void autokeyframe_ob_cb_func(Object *ob, int tmode) icu= NULL; } - while(icu) { + while (icu) { icu->flag &= ~IPO_SELECT; if (U.uiflag & USER_KEYINSERTNEED) insertkey_smarter(id, ID_OB, actname, NULL, icu->adrcode); @@ -2725,36 +2725,65 @@ void autokeyframe_ob_cb_func(Object *ob, int tmode) } } else if (U.uiflag & USER_KEYINSERTNEED) { - if (tmode==TFM_RESIZE) { - insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_SIZE_X); - insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_SIZE_Y); - insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_SIZE_Z); + short doLoc=0, doRot=0, doScale=0; + + /* filter the conditions when this happens (assume that curarea->spacetype==SPACE_VIE3D) */ + if (tmode == TFM_TRANSLATION) { + doLoc = 1; } - else if (tmode==TFM_ROTATION) { + else if (tmode == TFM_ROTATION) { + if (G.vd->around == V3D_ACTIVE) { + if (ob != OBACT) + doLoc = 1; + } + else if (G.vd->around == V3D_CURSOR) + doLoc = 1; + + if ((G.vd->flag & V3D_ALIGN)==0) + doRot = 1; + } + else if (tmode == TFM_RESIZE) { + if (G.vd->around == V3D_ACTIVE) { + if (ob != OBACT) + doLoc = 1; + } + else if (G.vd->around == V3D_CURSOR) + doLoc = 1; + + if ((G.vd->flag & V3D_ALIGN)==0) + doScale = 1; + } + + if (doLoc) { + insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_LOC_X); + insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_LOC_Y); + insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_LOC_Z); + } + if (doRot) { insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_ROT_X); insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_ROT_Y); insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_ROT_Z); } - else if (tmode==TFM_TRANSLATION) { - insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_LOC_X); - insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_LOC_Y); - insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_LOC_Z); + if (doScale) { + insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_SIZE_X); + insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_SIZE_Y); + insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_SIZE_Z); } } else { insertkey(&ob->id, ID_OB, actname, NULL, OB_ROT_X, 0); insertkey(&ob->id, ID_OB, actname, NULL, OB_ROT_Y, 0); insertkey(&ob->id, ID_OB, actname, NULL, OB_ROT_Z, 0); - + insertkey(&ob->id, ID_OB, actname, NULL, OB_LOC_X, 0); insertkey(&ob->id, ID_OB, actname, NULL, OB_LOC_Y, 0); insertkey(&ob->id, ID_OB, actname, NULL, OB_LOC_Z, 0); - + insertkey(&ob->id, ID_OB, actname, NULL, OB_SIZE_X, 0); insertkey(&ob->id, ID_OB, actname, NULL, OB_SIZE_Y, 0); insertkey(&ob->id, ID_OB, actname, NULL, OB_SIZE_Z, 0); } - + remake_object_ipos(ob); allqueue(REDRAWMARKER, 0); } @@ -2785,7 +2814,7 @@ void autokeyframe_pose_cb_func(Object *ob, int tmode, short targetless_ik) pchan->bone->flag &= ~BONE_UNKEYED; /* only insert into available channels? */ - if(U.uiflag & USER_KEYINSERTAVAI) { + if (U.uiflag & USER_KEYINSERTAVAI) { bActionChannel *achan; for (achan = act->chanbase.first; achan; achan=achan->next){ @@ -2803,18 +2832,42 @@ void autokeyframe_pose_cb_func(Object *ob, int tmode, short targetless_ik) } /* only insert keyframe if needed? */ else if (U.uiflag & USER_KEYINSERTNEED) { - if ((tmode==TFM_TRANSLATION) && (targetless_ik==0)) { + short doLoc=0, doRot=0, doScale=0; + + /* filter the conditions when this happens (assume that curarea->spacetype==SPACE_VIE3D) */ + if (tmode == TFM_TRANSLATION) { + if (targetless_ik) + doRot= 1; + else + doLoc = 1; + } + else if (tmode == TFM_ROTATION) { + if (ELEM(G.vd->around, V3D_CURSOR, V3D_ACTIVE)) + doLoc = 1; + + if ((G.vd->flag & V3D_ALIGN)==0) + doRot = 1; + } + else if (tmode == TFM_RESIZE) { + if (ELEM(G.vd->around, V3D_CURSOR, V3D_ACTIVE)) + doLoc = 1; + + if ((G.vd->flag & V3D_ALIGN)==0) + doScale = 1; + } + + if (doLoc) { insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_X); insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_Y); insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_Z); } - if ((tmode==TFM_ROTATION) || ((tmode==TFM_TRANSLATION) && targetless_ik)) { + if (doRot) { insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_W); insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_X); insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_Y); insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_Z); } - if (tmode==TFM_RESIZE) { + if (doScale) { insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_X); insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_Y); insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_Z); @@ -2889,7 +2942,7 @@ void special_aftertrans_update(TransInfo *t) if (t->spacetype==SPACE_VIEW3D) EM_automerge(1); - if(t->spacetype == SPACE_ACTION) { + if (t->spacetype == SPACE_ACTION) { void *data; short datatype; @@ -2929,7 +2982,7 @@ void special_aftertrans_update(TransInfo *t) DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA); } } - else if(t->spacetype == SPACE_NLA) { + else if (t->spacetype == SPACE_NLA) { synchronize_action_strips(); /* cleanup */ @@ -2938,35 +2991,35 @@ void special_aftertrans_update(TransInfo *t) recalc_all_ipos(); // bad } - else if(t->spacetype == SPACE_IPO) { + else if (t->spacetype == SPACE_IPO) { // FIXME! is there any code from the old transform_ipo that needs to be added back? /* resetting slow-parents isn't really necessary when editing sequence ipo's */ if (G.sipo->blocktype==ID_SEQ) resetslowpar= 0; } - else if(G.obedit) { - if(t->mode==TFM_BONESIZE || t->mode==TFM_BONE_ENVELOPE) + else if (G.obedit) { + if (t->mode==TFM_BONESIZE || t->mode==TFM_BONE_ENVELOPE) allqueue(REDRAWBUTSEDIT, 0); /* table needs to be created for each edit command, since vertices can move etc */ mesh_octree_table(G.obedit, NULL, 'e'); } - else if( (t->flag & T_POSE) && t->poseobj) { + else if ((t->flag & T_POSE) && (t->poseobj)) { bArmature *arm; bPose *pose; bPoseChannel *pchan; short targetless_ik= 0; - + ob= t->poseobj; arm= ob->data; pose= ob->pose; /* this signal does one recalc on pose, then unlocks, so ESC or edit will work */ pose->flag |= POSE_DO_UNLOCK; - + /* if target-less IK grabbing, we calculate the pchan transforms and clear flag */ - if(!cancelled && t->mode==TFM_TRANSLATION) + if (!cancelled && t->mode==TFM_TRANSLATION) targetless_ik= apply_targetless_ik(ob); else { /* not forget to clear the auto flag */ @@ -2976,15 +3029,15 @@ void special_aftertrans_update(TransInfo *t) } } - if(t->mode==TFM_TRANSLATION) + if (t->mode==TFM_TRANSLATION) pose_grab_with_ik_clear(ob); /* automatic inserting of keys and unkeyed tagging - only if transform wasn't cancelled (or TFM_DUMMY) */ - if(!cancelled && (t->mode != TFM_DUMMY)) { + if (!cancelled && (t->mode != TFM_DUMMY)) { autokeyframe_pose_cb_func(ob, t->mode, targetless_ik); DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); } - else if(arm->flag & ARM_DELAYDEFORM) { + else if (arm->flag & ARM_DELAYDEFORM) { /* old optimize trick... this enforces to bypass the depgraph */ DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); ob->recalc= 0; // is set on OK position already by recalcData() @@ -2992,18 +3045,20 @@ void special_aftertrans_update(TransInfo *t) else DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); - if(t->mode==TFM_BONESIZE || t->mode==TFM_BONE_ENVELOPE) + if (t->mode==TFM_BONESIZE || t->mode==TFM_BONE_ENVELOPE) allqueue(REDRAWBUTSEDIT, 0); } else { base= FIRSTBASE; - while(base) { + + while (base) { + if(base->flag & BA_DO_IPO) redrawipo= 1; ob= base->object; - if(modifiers_isSoftbodyEnabled(ob)) ob->softflag |= OB_SB_REDO; + if (modifiers_isSoftbodyEnabled(ob)) ob->softflag |= OB_SB_REDO; else if(modifiers_isClothEnabled(ob)) { cloth_free_modifier(modifiers_isClothEnabled(ob)); } @@ -3020,7 +3075,7 @@ void special_aftertrans_update(TransInfo *t) clear_trans_object_base_flags(); - if(redrawipo) { + if (redrawipo) { allqueue(REDRAWNLA, 0); allqueue(REDRAWACTION, 0); allqueue(REDRAWIPO, 0); diff --git a/source/gameengine/Converter/BL_SkinDeformer.cpp b/source/gameengine/Converter/BL_SkinDeformer.cpp index 90b5fc5308d..e9ec6f9116b 100644 --- a/source/gameengine/Converter/BL_SkinDeformer.cpp +++ b/source/gameengine/Converter/BL_SkinDeformer.cpp @@ -175,7 +175,7 @@ void BL_SkinDeformer::Update(void) for (int v =0; vtotvert; v++) VECCOPY(m_transverts[v], m_bmesh->mvert[v].co); - armature_deform_verts( par_arma, m_objMesh, NULL, m_transverts, NULL, m_bmesh->totvert, ARM_DEF_VGROUP, NULL ); + armature_deform_verts( par_arma, m_objMesh, NULL, m_transverts, NULL, m_bmesh->totvert, ARM_DEF_VGROUP, NULL, NULL ); RecalcNormals(); /* Update the current frame */